emdash 0.0.0-a → 0.0.1
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.
- package/README.md +87 -1
- package/dist/adapters-BLMa4JGD.d.mts +106 -0
- package/dist/adapters-BLMa4JGD.d.mts.map +1 -0
- package/dist/apply-Bjfq_b4-.mjs +1293 -0
- package/dist/apply-Bjfq_b4-.mjs.map +1 -0
- package/dist/astro/index.d.mts +51 -0
- package/dist/astro/index.d.mts.map +1 -0
- package/dist/astro/index.mjs +1333 -0
- package/dist/astro/index.mjs.map +1 -0
- package/dist/astro/middleware/auth.d.mts +31 -0
- package/dist/astro/middleware/auth.d.mts.map +1 -0
- package/dist/astro/middleware/auth.mjs +654 -0
- package/dist/astro/middleware/auth.mjs.map +1 -0
- package/dist/astro/middleware/redirect.d.mts +22 -0
- package/dist/astro/middleware/redirect.d.mts.map +1 -0
- package/dist/astro/middleware/redirect.mjs +63 -0
- package/dist/astro/middleware/redirect.mjs.map +1 -0
- package/dist/astro/middleware/request-context.d.mts +18 -0
- package/dist/astro/middleware/request-context.d.mts.map +1 -0
- package/dist/astro/middleware/request-context.mjs +1310 -0
- package/dist/astro/middleware/request-context.mjs.map +1 -0
- package/dist/astro/middleware/setup.d.mts +20 -0
- package/dist/astro/middleware/setup.d.mts.map +1 -0
- package/dist/astro/middleware/setup.mjs +47 -0
- package/dist/astro/middleware/setup.mjs.map +1 -0
- package/dist/astro/middleware.d.mts +13 -0
- package/dist/astro/middleware.d.mts.map +1 -0
- package/dist/astro/middleware.mjs +1613 -0
- package/dist/astro/middleware.mjs.map +1 -0
- package/dist/astro/types.d.mts +250 -0
- package/dist/astro/types.d.mts.map +1 -0
- package/dist/astro/types.mjs +1 -0
- package/dist/base64-MBPo9ozB.mjs +59 -0
- package/dist/base64-MBPo9ozB.mjs.map +1 -0
- package/dist/byline-CL847F26.mjs +213 -0
- package/dist/byline-CL847F26.mjs.map +1 -0
- package/dist/bylines-C2a-2TGt.mjs +136 -0
- package/dist/bylines-C2a-2TGt.mjs.map +1 -0
- package/dist/chunk-ClPoSABd.mjs +21 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +3909 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/client/cf-access.d.mts +60 -0
- package/dist/client/cf-access.d.mts.map +1 -0
- package/dist/client/cf-access.mjs +179 -0
- package/dist/client/cf-access.mjs.map +1 -0
- package/dist/client/index.d.mts +398 -0
- package/dist/client/index.d.mts.map +1 -0
- package/dist/client/index.mjs +346 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/config-CKE8p9xM.mjs +55 -0
- package/dist/config-CKE8p9xM.mjs.map +1 -0
- package/dist/connection-B4zVnQIa.mjs +40 -0
- package/dist/connection-B4zVnQIa.mjs.map +1 -0
- package/dist/content-D6C2WsZC.mjs +824 -0
- package/dist/content-D6C2WsZC.mjs.map +1 -0
- package/dist/db/index.d.mts +4 -0
- package/dist/db/index.mjs +62 -0
- package/dist/db/index.mjs.map +1 -0
- package/dist/db/libsql.d.mts +11 -0
- package/dist/db/libsql.d.mts.map +1 -0
- package/dist/db/libsql.mjs +17 -0
- package/dist/db/libsql.mjs.map +1 -0
- package/dist/db/postgres.d.mts +11 -0
- package/dist/db/postgres.d.mts.map +1 -0
- package/dist/db/postgres.mjs +30 -0
- package/dist/db/postgres.mjs.map +1 -0
- package/dist/db/sqlite.d.mts +11 -0
- package/dist/db/sqlite.d.mts.map +1 -0
- package/dist/db/sqlite.mjs +16 -0
- package/dist/db/sqlite.mjs.map +1 -0
- package/dist/default-Cyi4aAxu.mjs +81 -0
- package/dist/default-Cyi4aAxu.mjs.map +1 -0
- package/dist/dialect-helpers-B9uSp2GJ.mjs +90 -0
- package/dist/dialect-helpers-B9uSp2GJ.mjs.map +1 -0
- package/dist/error-Cxz0tQeO.mjs +27 -0
- package/dist/error-Cxz0tQeO.mjs.map +1 -0
- package/dist/index-C1xF3OGh.d.mts +4527 -0
- package/dist/index-C1xF3OGh.d.mts.map +1 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +30 -0
- package/dist/load-yOOlckBj.mjs +28 -0
- package/dist/load-yOOlckBj.mjs.map +1 -0
- package/dist/loader-fz8Q_3EO.mjs +447 -0
- package/dist/loader-fz8Q_3EO.mjs.map +1 -0
- package/dist/manifest-schema-Dcl0R6nM.mjs +184 -0
- package/dist/manifest-schema-Dcl0R6nM.mjs.map +1 -0
- package/dist/media/index.d.mts +26 -0
- package/dist/media/index.d.mts.map +1 -0
- package/dist/media/index.mjs +55 -0
- package/dist/media/index.mjs.map +1 -0
- package/dist/media/local-runtime.d.mts +39 -0
- package/dist/media/local-runtime.d.mts.map +1 -0
- package/dist/media/local-runtime.mjs +133 -0
- package/dist/media/local-runtime.mjs.map +1 -0
- package/dist/media-DqHVh136.mjs +200 -0
- package/dist/media-DqHVh136.mjs.map +1 -0
- package/dist/mode-C2EzN1uE.mjs +23 -0
- package/dist/mode-C2EzN1uE.mjs.map +1 -0
- package/dist/page/index.d.mts +140 -0
- package/dist/page/index.d.mts.map +1 -0
- package/dist/page/index.mjs +416 -0
- package/dist/page/index.mjs.map +1 -0
- package/dist/placeholder-CmGAmqeO.d.mts +276 -0
- package/dist/placeholder-CmGAmqeO.d.mts.map +1 -0
- package/dist/placeholder-SmpOx-_v.mjs +243 -0
- package/dist/placeholder-SmpOx-_v.mjs.map +1 -0
- package/dist/plugin-utils.d.mts +58 -0
- package/dist/plugin-utils.d.mts.map +1 -0
- package/dist/plugin-utils.mjs +78 -0
- package/dist/plugin-utils.mjs.map +1 -0
- package/dist/plugins/adapt-sandbox-entry.d.mts +22 -0
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -0
- package/dist/plugins/adapt-sandbox-entry.mjs +113 -0
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -0
- package/dist/query-CS_iSj34.mjs +460 -0
- package/dist/query-CS_iSj34.mjs.map +1 -0
- package/dist/redirect-DIfIni3r.mjs +329 -0
- package/dist/redirect-DIfIni3r.mjs.map +1 -0
- package/dist/registry-D_w5HW4G.mjs +863 -0
- package/dist/registry-D_w5HW4G.mjs.map +1 -0
- package/dist/request-context.d.mts +49 -0
- package/dist/request-context.d.mts.map +1 -0
- package/dist/request-context.mjs +43 -0
- package/dist/request-context.mjs.map +1 -0
- package/dist/runner-B-u2F2b6.mjs +1412 -0
- package/dist/runner-B-u2F2b6.mjs.map +1 -0
- package/dist/runner-EAtf0ZIe.d.mts +27 -0
- package/dist/runner-EAtf0ZIe.d.mts.map +1 -0
- package/dist/runtime.d.mts +26 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +42 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/search-DG603UrT.mjs +9211 -0
- package/dist/search-DG603UrT.mjs.map +1 -0
- package/dist/seed/index.d.mts +3 -0
- package/dist/seed/index.mjs +15 -0
- package/dist/seo/index.d.mts +70 -0
- package/dist/seo/index.d.mts.map +1 -0
- package/dist/seo/index.mjs +70 -0
- package/dist/seo/index.mjs.map +1 -0
- package/dist/storage/local.d.mts +39 -0
- package/dist/storage/local.d.mts.map +1 -0
- package/dist/storage/local.mjs +166 -0
- package/dist/storage/local.mjs.map +1 -0
- package/dist/storage/s3.d.mts +32 -0
- package/dist/storage/s3.d.mts.map +1 -0
- package/dist/storage/s3.mjs +175 -0
- package/dist/storage/s3.mjs.map +1 -0
- package/dist/tokens-DpgrkrXK.mjs +171 -0
- package/dist/tokens-DpgrkrXK.mjs.map +1 -0
- package/dist/transport-BFGblqwG.d.mts +42 -0
- package/dist/transport-BFGblqwG.d.mts.map +1 -0
- package/dist/transport-yxiQsi8I.mjs +418 -0
- package/dist/transport-yxiQsi8I.mjs.map +1 -0
- package/dist/types-BRuPJGdV.d.mts +102 -0
- package/dist/types-BRuPJGdV.d.mts.map +1 -0
- package/dist/types-C4-fAxN3.d.mts +182 -0
- package/dist/types-C4-fAxN3.d.mts.map +1 -0
- package/dist/types-CMMN0pNg.mjs +31 -0
- package/dist/types-CMMN0pNg.mjs.map +1 -0
- package/dist/types-CUBbjgmP.mjs +16 -0
- package/dist/types-CUBbjgmP.mjs.map +1 -0
- package/dist/types-DRjfYOEv.d.mts +426 -0
- package/dist/types-DRjfYOEv.d.mts.map +1 -0
- package/dist/types-DY5zk5HN.mjs +73 -0
- package/dist/types-DY5zk5HN.mjs.map +1 -0
- package/dist/types-DaNLHo_T.d.mts +184 -0
- package/dist/types-DaNLHo_T.d.mts.map +1 -0
- package/dist/types-DvhsUmSJ.d.mts +1111 -0
- package/dist/types-DvhsUmSJ.d.mts.map +1 -0
- package/dist/validate-CpBtVMsD.d.mts +378 -0
- package/dist/validate-CpBtVMsD.d.mts.map +1 -0
- package/dist/validate-CqRJb_xU.mjs +97 -0
- package/dist/validate-CqRJb_xU.mjs.map +1 -0
- package/dist/validate-O7PWmlnq.mjs +328 -0
- package/dist/validate-O7PWmlnq.mjs.map +1 -0
- package/locals.d.ts +46 -0
- package/package.json +233 -19
- package/src/api/authorize.ts +63 -0
- package/src/api/csrf.ts +48 -0
- package/src/api/error.ts +99 -0
- package/src/api/errors.ts +445 -0
- package/src/api/escape.ts +9 -0
- package/src/api/handlers/api-tokens.ts +240 -0
- package/src/api/handlers/comments.ts +314 -0
- package/src/api/handlers/content.ts +1315 -0
- package/src/api/handlers/dashboard.ts +205 -0
- package/src/api/handlers/device-flow.ts +687 -0
- package/src/api/handlers/index.ts +163 -0
- package/src/api/handlers/manifest.ts +158 -0
- package/src/api/handlers/marketplace.ts +930 -0
- package/src/api/handlers/media.ts +207 -0
- package/src/api/handlers/menus.ts +493 -0
- package/src/api/handlers/oauth-authorization.ts +429 -0
- package/src/api/handlers/oauth-clients.ts +353 -0
- package/src/api/handlers/oauth-user-lookup.ts +39 -0
- package/src/api/handlers/plugins.ts +254 -0
- package/src/api/handlers/redirects.ts +360 -0
- package/src/api/handlers/revision.ts +145 -0
- package/src/api/handlers/schema.ts +534 -0
- package/src/api/handlers/sections.ts +289 -0
- package/src/api/handlers/seo.ts +115 -0
- package/src/api/handlers/settings.ts +49 -0
- package/src/api/handlers/snapshot.ts +350 -0
- package/src/api/handlers/taxonomies.ts +523 -0
- package/src/api/index.ts +6 -0
- package/src/api/openapi/document.ts +2368 -0
- package/src/api/openapi/index.ts +1 -0
- package/src/api/parse.ts +139 -0
- package/src/api/redirect.ts +14 -0
- package/src/api/rev.ts +67 -0
- package/src/api/schemas/auth.ts +112 -0
- package/src/api/schemas/bylines.ts +85 -0
- package/src/api/schemas/comments.ts +117 -0
- package/src/api/schemas/common.ts +89 -0
- package/src/api/schemas/content.ts +191 -0
- package/src/api/schemas/import.ts +52 -0
- package/src/api/schemas/index.ts +17 -0
- package/src/api/schemas/media.ts +116 -0
- package/src/api/schemas/menus.ts +111 -0
- package/src/api/schemas/redirects.ts +155 -0
- package/src/api/schemas/schema.ts +203 -0
- package/src/api/schemas/search.ts +63 -0
- package/src/api/schemas/sections.ts +67 -0
- package/src/api/schemas/settings.ts +63 -0
- package/src/api/schemas/setup.ts +37 -0
- package/src/api/schemas/taxonomies.ts +113 -0
- package/src/api/schemas/users.ts +96 -0
- package/src/api/schemas/widgets.ts +80 -0
- package/src/api/site-url.ts +25 -0
- package/src/api/types.ts +82 -0
- package/src/astro/index.ts +27 -0
- package/src/astro/integration/index.ts +303 -0
- package/src/astro/integration/routes.ts +834 -0
- package/src/astro/integration/runtime.ts +338 -0
- package/src/astro/integration/virtual-modules.ts +469 -0
- package/src/astro/integration/vite-config.ts +328 -0
- package/src/astro/middleware/auth.ts +743 -0
- package/src/astro/middleware/redirect.ts +89 -0
- package/src/astro/middleware/request-context.ts +129 -0
- package/src/astro/middleware/setup.ts +89 -0
- package/src/astro/middleware.ts +398 -0
- package/src/astro/routes/PluginRegistry.tsx +15 -0
- package/src/astro/routes/admin.astro +81 -0
- package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
- package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
- package/src/astro/routes/api/admin/api-tokens/[id].ts +40 -0
- package/src/astro/routes/api/admin/api-tokens/index.ts +68 -0
- package/src/astro/routes/api/admin/bylines/[id]/index.ts +87 -0
- package/src/astro/routes/api/admin/bylines/index.ts +72 -0
- package/src/astro/routes/api/admin/comments/[id]/status.ts +120 -0
- package/src/astro/routes/api/admin/comments/[id].ts +64 -0
- package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
- package/src/astro/routes/api/admin/comments/counts.ts +30 -0
- package/src/astro/routes/api/admin/comments/index.ts +46 -0
- package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +91 -0
- package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
- package/src/astro/routes/api/admin/oauth-clients/[id].ts +110 -0
- package/src/astro/routes/api/admin/oauth-clients/index.ts +71 -0
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +39 -0
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +39 -0
- package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +48 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +59 -0
- package/src/astro/routes/api/admin/plugins/index.ts +32 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +61 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +62 -0
- package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
- package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
- package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
- package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +61 -0
- package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
- package/src/astro/routes/api/admin/users/[id]/disable.ts +69 -0
- package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
- package/src/astro/routes/api/admin/users/[id]/index.ts +146 -0
- package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
- package/src/astro/routes/api/admin/users/index.ts +66 -0
- package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
- package/src/astro/routes/api/auth/invite/accept.ts +52 -0
- package/src/astro/routes/api/auth/invite/complete.ts +84 -0
- package/src/astro/routes/api/auth/invite/index.ts +99 -0
- package/src/astro/routes/api/auth/logout.ts +40 -0
- package/src/astro/routes/api/auth/magic-link/send.ts +89 -0
- package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
- package/src/astro/routes/api/auth/me.ts +60 -0
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +219 -0
- package/src/astro/routes/api/auth/oauth/[provider].ts +119 -0
- package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
- package/src/astro/routes/api/auth/passkey/index.ts +54 -0
- package/src/astro/routes/api/auth/passkey/options.ts +82 -0
- package/src/astro/routes/api/auth/passkey/register/options.ts +86 -0
- package/src/astro/routes/api/auth/passkey/register/verify.ts +117 -0
- package/src/astro/routes/api/auth/passkey/verify.ts +66 -0
- package/src/astro/routes/api/auth/signup/complete.ts +85 -0
- package/src/astro/routes/api/auth/signup/request.ts +77 -0
- package/src/astro/routes/api/auth/signup/verify.ts +53 -0
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +312 -0
- package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +54 -0
- package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +61 -0
- package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +33 -0
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +56 -0
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +54 -0
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +105 -0
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +140 -0
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +30 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +56 -0
- package/src/astro/routes/api/content/[collection]/[id].ts +137 -0
- package/src/astro/routes/api/content/[collection]/index.ts +59 -0
- package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
- package/src/astro/routes/api/dashboard.ts +32 -0
- package/src/astro/routes/api/dev/emails.ts +36 -0
- package/src/astro/routes/api/import/probe.ts +47 -0
- package/src/astro/routes/api/import/wordpress/analyze.ts +510 -0
- package/src/astro/routes/api/import/wordpress/execute.ts +283 -0
- package/src/astro/routes/api/import/wordpress/media.ts +338 -0
- package/src/astro/routes/api/import/wordpress/prepare.ts +181 -0
- package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +393 -0
- package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
- package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +347 -0
- package/src/astro/routes/api/manifest.ts +62 -0
- package/src/astro/routes/api/mcp.ts +124 -0
- package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
- package/src/astro/routes/api/media/[id].ts +145 -0
- package/src/astro/routes/api/media/file/[key].ts +79 -0
- package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +86 -0
- package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
- package/src/astro/routes/api/media/providers/index.ts +30 -0
- package/src/astro/routes/api/media/upload-url.ts +137 -0
- package/src/astro/routes/api/media.ts +190 -0
- package/src/astro/routes/api/menus/[name]/items.ts +87 -0
- package/src/astro/routes/api/menus/[name]/reorder.ts +33 -0
- package/src/astro/routes/api/menus/[name].ts +65 -0
- package/src/astro/routes/api/menus/index.ts +47 -0
- package/src/astro/routes/api/oauth/authorize.ts +412 -0
- package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
- package/src/astro/routes/api/oauth/device/code.ts +51 -0
- package/src/astro/routes/api/oauth/device/token.ts +69 -0
- package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
- package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
- package/src/astro/routes/api/oauth/token.ts +184 -0
- package/src/astro/routes/api/openapi.json.ts +32 -0
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +92 -0
- package/src/astro/routes/api/redirects/404s/index.ts +72 -0
- package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
- package/src/astro/routes/api/redirects/[id].ts +84 -0
- package/src/astro/routes/api/redirects/index.ts +52 -0
- package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
- package/src/astro/routes/api/revisions/[revisionId]/restore.ts +62 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +76 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +52 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +32 -0
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +80 -0
- package/src/astro/routes/api/schema/collections/index.ts +47 -0
- package/src/astro/routes/api/schema/index.ts +109 -0
- package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
- package/src/astro/routes/api/schema/orphans/index.ts +26 -0
- package/src/astro/routes/api/search/enable.ts +64 -0
- package/src/astro/routes/api/search/index.ts +55 -0
- package/src/astro/routes/api/search/rebuild.ts +72 -0
- package/src/astro/routes/api/search/stats.ts +35 -0
- package/src/astro/routes/api/search/suggest.ts +53 -0
- package/src/astro/routes/api/sections/[slug].ts +84 -0
- package/src/astro/routes/api/sections/index.ts +52 -0
- package/src/astro/routes/api/settings/email.ts +150 -0
- package/src/astro/routes/api/settings.ts +67 -0
- package/src/astro/routes/api/setup/admin-verify.ts +100 -0
- package/src/astro/routes/api/setup/admin.ts +94 -0
- package/src/astro/routes/api/setup/dev-bypass.ts +199 -0
- package/src/astro/routes/api/setup/dev-reset.ts +40 -0
- package/src/astro/routes/api/setup/index.ts +126 -0
- package/src/astro/routes/api/setup/status.ts +122 -0
- package/src/astro/routes/api/snapshot.ts +75 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +95 -0
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +69 -0
- package/src/astro/routes/api/taxonomies/index.ts +59 -0
- package/src/astro/routes/api/themes/preview.ts +77 -0
- package/src/astro/routes/api/typegen.ts +114 -0
- package/src/astro/routes/api/well-known/auth.ts +68 -0
- package/src/astro/routes/api/well-known/oauth-authorization-server.ts +44 -0
- package/src/astro/routes/api/well-known/oauth-protected-resource.ts +37 -0
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +72 -0
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +127 -0
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +80 -0
- package/src/astro/routes/api/widget-areas/[name].ts +87 -0
- package/src/astro/routes/api/widget-areas/index.ts +99 -0
- package/src/astro/routes/api/widget-components.ts +22 -0
- package/src/astro/routes/robots.txt.ts +77 -0
- package/src/astro/routes/sitemap.xml.ts +97 -0
- package/src/astro/storage/adapters.ts +74 -0
- package/src/astro/storage/index.ts +19 -0
- package/src/astro/storage/types.ts +60 -0
- package/src/astro/types.ts +346 -0
- package/src/auth/api-tokens.ts +25 -0
- package/src/auth/challenge-store.ts +80 -0
- package/src/auth/mode.ts +96 -0
- package/src/auth/oauth-state-store.ts +96 -0
- package/src/auth/passkey-config.ts +27 -0
- package/src/auth/rate-limit.ts +158 -0
- package/src/auth/scopes.ts +33 -0
- package/src/auth/types.ts +104 -0
- package/src/aws-sdk.d.ts +100 -0
- package/src/bylines/index.ts +237 -0
- package/src/cleanup.ts +153 -0
- package/src/cli/client-factory.ts +100 -0
- package/src/cli/commands/auth.ts +46 -0
- package/src/cli/commands/bundle-utils.ts +247 -0
- package/src/cli/commands/bundle.ts +609 -0
- package/src/cli/commands/content.ts +442 -0
- package/src/cli/commands/dev.ts +191 -0
- package/src/cli/commands/doctor.ts +211 -0
- package/src/cli/commands/export-seed.ts +630 -0
- package/src/cli/commands/import/wordpress.ts +1056 -0
- package/src/cli/commands/init.ts +192 -0
- package/src/cli/commands/login.ts +547 -0
- package/src/cli/commands/media.ts +165 -0
- package/src/cli/commands/menu.ts +67 -0
- package/src/cli/commands/plugin-init.ts +291 -0
- package/src/cli/commands/plugin-validate.ts +31 -0
- package/src/cli/commands/plugin.ts +33 -0
- package/src/cli/commands/publish.ts +699 -0
- package/src/cli/commands/schema.ts +233 -0
- package/src/cli/commands/search-cmd.ts +54 -0
- package/src/cli/commands/seed.ts +288 -0
- package/src/cli/commands/taxonomy.ts +128 -0
- package/src/cli/commands/types.ts +68 -0
- package/src/cli/credentials.ts +236 -0
- package/src/cli/index.ts +70 -0
- package/src/cli/output.ts +75 -0
- package/src/cli/wxr/parser.ts +969 -0
- package/src/client/cf-access.ts +193 -0
- package/src/client/index.ts +854 -0
- package/src/client/portable-text.ts +413 -0
- package/src/client/transport.ts +200 -0
- package/src/comments/moderator.ts +46 -0
- package/src/comments/notifications.ts +144 -0
- package/src/comments/query.ts +105 -0
- package/src/comments/service.ts +213 -0
- package/src/components/Break.astro +45 -0
- package/src/components/Button.astro +71 -0
- package/src/components/Buttons.astro +49 -0
- package/src/components/Code.astro +59 -0
- package/src/components/Columns.astro +59 -0
- package/src/components/CommentForm.astro +315 -0
- package/src/components/Comments.astro +232 -0
- package/src/components/Cover.astro +128 -0
- package/src/components/EmDashBodyEnd.astro +32 -0
- package/src/components/EmDashBodyStart.astro +32 -0
- package/src/components/EmDashHead.astro +53 -0
- package/src/components/EmDashImage.astro +178 -0
- package/src/components/EmDashMedia.astro +167 -0
- package/src/components/Embed.astro +128 -0
- package/src/components/File.astro +122 -0
- package/src/components/Gallery.astro +93 -0
- package/src/components/HtmlBlock.astro +33 -0
- package/src/components/Image.astro +178 -0
- package/src/components/InlineEditor.astro +27 -0
- package/src/components/InlinePortableTextEditor.tsx +1905 -0
- package/src/components/LiveSearch.astro +614 -0
- package/src/components/PortableText.astro +51 -0
- package/src/components/Pullquote.astro +51 -0
- package/src/components/Table.astro +108 -0
- package/src/components/WidgetArea.astro +22 -0
- package/src/components/WidgetRenderer.astro +72 -0
- package/src/components/index.ts +116 -0
- package/src/components/marks/Link.astro +31 -0
- package/src/components/marks/StrikeThrough.astro +7 -0
- package/src/components/marks/Subscript.astro +7 -0
- package/src/components/marks/Superscript.astro +7 -0
- package/src/components/marks/Underline.astro +7 -0
- package/src/components/widgets/Archives.astro +65 -0
- package/src/components/widgets/Categories.astro +35 -0
- package/src/components/widgets/RecentPosts.astro +51 -0
- package/src/components/widgets/Search.astro +18 -0
- package/src/components/widgets/Tags.astro +38 -0
- package/src/content/converters/index.ts +9 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +385 -0
- package/src/content/converters/prosemirror-to-portable-text.ts +413 -0
- package/src/content/converters/types.ts +120 -0
- package/src/content/index.ts +5 -0
- package/src/database/connection.ts +67 -0
- package/src/database/dialect-helpers.ts +138 -0
- package/src/database/index.ts +5 -0
- package/src/database/migrations/001_initial.ts +136 -0
- package/src/database/migrations/002_media_status.ts +26 -0
- package/src/database/migrations/003_schema_registry.ts +79 -0
- package/src/database/migrations/004_plugins.ts +62 -0
- package/src/database/migrations/005_menus.ts +67 -0
- package/src/database/migrations/006_taxonomy_defs.ts +51 -0
- package/src/database/migrations/007_widgets.ts +42 -0
- package/src/database/migrations/008_auth.ts +194 -0
- package/src/database/migrations/009_user_disabled.ts +27 -0
- package/src/database/migrations/011_sections.ts +65 -0
- package/src/database/migrations/012_search.ts +25 -0
- package/src/database/migrations/013_scheduled_publishing.ts +51 -0
- package/src/database/migrations/014_draft_revisions.ts +72 -0
- package/src/database/migrations/015_indexes.ts +82 -0
- package/src/database/migrations/016_api_tokens.ts +89 -0
- package/src/database/migrations/017_authorization_codes.ts +45 -0
- package/src/database/migrations/018_seo.ts +56 -0
- package/src/database/migrations/019_i18n.ts +618 -0
- package/src/database/migrations/020_collection_url_pattern.ts +23 -0
- package/src/database/migrations/021_remove_section_categories.ts +43 -0
- package/src/database/migrations/022_marketplace_plugin_state.ts +46 -0
- package/src/database/migrations/023_plugin_metadata.ts +33 -0
- package/src/database/migrations/024_media_placeholders.ts +32 -0
- package/src/database/migrations/025_oauth_clients.ts +28 -0
- package/src/database/migrations/026_cron_tasks.ts +49 -0
- package/src/database/migrations/027_comments.ts +87 -0
- package/src/database/migrations/028_drop_author_url.ts +9 -0
- package/src/database/migrations/029_redirects.ts +67 -0
- package/src/database/migrations/030_widen_scheduled_index.ts +48 -0
- package/src/database/migrations/031_bylines.ts +90 -0
- package/src/database/migrations/032_rate_limits.ts +42 -0
- package/src/database/migrations/runner.ts +170 -0
- package/src/database/repositories/audit.ts +294 -0
- package/src/database/repositories/byline.ts +387 -0
- package/src/database/repositories/comment.ts +458 -0
- package/src/database/repositories/content.ts +1144 -0
- package/src/database/repositories/index.ts +30 -0
- package/src/database/repositories/media.ts +347 -0
- package/src/database/repositories/options.ts +150 -0
- package/src/database/repositories/plugin-storage.ts +373 -0
- package/src/database/repositories/redirect.ts +480 -0
- package/src/database/repositories/revision.ts +200 -0
- package/src/database/repositories/seo.ts +176 -0
- package/src/database/repositories/taxonomy.ts +294 -0
- package/src/database/repositories/types.ts +132 -0
- package/src/database/repositories/user.ts +258 -0
- package/src/database/transaction.ts +54 -0
- package/src/database/types.ts +501 -0
- package/src/database/validate.ts +138 -0
- package/src/db/adapters.ts +125 -0
- package/src/db/index.ts +37 -0
- package/src/db/libsql.ts +23 -0
- package/src/db/postgres.ts +30 -0
- package/src/db/sqlite.ts +27 -0
- package/src/emdash-runtime.ts +2096 -0
- package/src/fields/boolean.ts +34 -0
- package/src/fields/datetime.ts +44 -0
- package/src/fields/file.ts +41 -0
- package/src/fields/image.ts +34 -0
- package/src/fields/index.ts +42 -0
- package/src/fields/integer.ts +50 -0
- package/src/fields/json.ts +37 -0
- package/src/fields/multiselect.ts +48 -0
- package/src/fields/number.ts +52 -0
- package/src/fields/portable-text.ts +33 -0
- package/src/fields/reference.ts +29 -0
- package/src/fields/richtext.ts +31 -0
- package/src/fields/select.ts +46 -0
- package/src/fields/slug.ts +38 -0
- package/src/fields/text.ts +55 -0
- package/src/fields/textarea.ts +52 -0
- package/src/fields/types.ts +64 -0
- package/src/i18n/config.ts +68 -0
- package/src/import/index.ts +90 -0
- package/src/import/menus.ts +436 -0
- package/src/import/registry.ts +111 -0
- package/src/import/sections.ts +103 -0
- package/src/import/settings.ts +281 -0
- package/src/import/sources/wordpress-plugin.ts +641 -0
- package/src/import/sources/wordpress-rest.ts +191 -0
- package/src/import/sources/wxr.ts +330 -0
- package/src/import/ssrf.ts +260 -0
- package/src/import/types.ts +418 -0
- package/src/import/utils.ts +412 -0
- package/src/index.ts +481 -0
- package/src/loader.ts +770 -0
- package/src/mcp/server.ts +1463 -0
- package/src/media/index.ts +32 -0
- package/src/media/local-runtime.ts +213 -0
- package/src/media/local.ts +46 -0
- package/src/media/normalize.ts +190 -0
- package/src/media/placeholder.ts +150 -0
- package/src/media/provider-loader.ts +78 -0
- package/src/media/types.ts +279 -0
- package/src/menus/index.ts +324 -0
- package/src/menus/types.ts +112 -0
- package/src/page/context.ts +93 -0
- package/src/page/fragments.ts +89 -0
- package/src/page/index.ts +58 -0
- package/src/page/jsonld.ts +94 -0
- package/src/page/metadata.ts +185 -0
- package/src/page/seo-contributions.ts +136 -0
- package/src/plugin-utils.ts +80 -0
- package/src/plugins/adapt-sandbox-entry.ts +207 -0
- package/src/plugins/context.ts +833 -0
- package/src/plugins/cron.ts +361 -0
- package/src/plugins/define-plugin.ts +259 -0
- package/src/plugins/email-console.ts +73 -0
- package/src/plugins/email.ts +209 -0
- package/src/plugins/hooks.ts +1273 -0
- package/src/plugins/index.ts +193 -0
- package/src/plugins/manager.ts +595 -0
- package/src/plugins/manifest-schema.ts +230 -0
- package/src/plugins/marketplace.ts +460 -0
- package/src/plugins/request-meta.ts +139 -0
- package/src/plugins/routes.ts +302 -0
- package/src/plugins/sandbox/index.ts +18 -0
- package/src/plugins/sandbox/noop.ts +76 -0
- package/src/plugins/sandbox/types.ts +173 -0
- package/src/plugins/scheduler/node.ts +122 -0
- package/src/plugins/scheduler/piggyback.ts +71 -0
- package/src/plugins/scheduler/types.ts +27 -0
- package/src/plugins/state.ts +208 -0
- package/src/plugins/storage-indexes.ts +326 -0
- package/src/plugins/storage-query.ts +240 -0
- package/src/plugins/types.ts +1284 -0
- package/src/preview/helpers.ts +27 -0
- package/src/preview/index.ts +40 -0
- package/src/preview/tokens.ts +279 -0
- package/src/preview/urls.ts +118 -0
- package/src/query.ts +674 -0
- package/src/redirects/patterns.ts +224 -0
- package/src/request-context.ts +67 -0
- package/src/runtime.ts +21 -0
- package/src/schema/index.ts +29 -0
- package/src/schema/query.ts +44 -0
- package/src/schema/registry.ts +965 -0
- package/src/schema/types.ts +276 -0
- package/src/schema/zod-generator.ts +413 -0
- package/src/search/fts-manager.ts +452 -0
- package/src/search/index.ts +26 -0
- package/src/search/query.ts +396 -0
- package/src/search/text-extraction.ts +162 -0
- package/src/search/types.ts +114 -0
- package/src/sections/index.ts +226 -0
- package/src/sections/types.ts +86 -0
- package/src/seed/apply.ts +1141 -0
- package/src/seed/default.ts +86 -0
- package/src/seed/index.ts +28 -0
- package/src/seed/load.ts +35 -0
- package/src/seed/types.ts +341 -0
- package/src/seed/validate.ts +642 -0
- package/src/seo/index.ts +179 -0
- package/src/settings/index.ts +203 -0
- package/src/settings/types.ts +58 -0
- package/src/storage/index.ts +28 -0
- package/src/storage/local.ts +253 -0
- package/src/storage/s3.ts +271 -0
- package/src/storage/types.ts +204 -0
- package/src/taxonomies/index.ts +309 -0
- package/src/taxonomies/types.ts +61 -0
- package/src/ui.ts +75 -0
- package/src/utils/base64.ts +73 -0
- package/src/utils/hash.ts +36 -0
- package/src/utils/sanitize.ts +20 -0
- package/src/utils/slugify.ts +29 -0
- package/src/utils/url.ts +48 -0
- package/src/virtual-modules.d.ts +111 -0
- package/src/visual-editing/editable.ts +108 -0
- package/src/visual-editing/toolbar.ts +1229 -0
- package/src/widgets/components.ts +105 -0
- package/src/widgets/index.ts +131 -0
- package/src/widgets/types.ts +81 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EmDash middleware
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper that initializes EmDashRuntime and attaches it to locals.
|
|
5
|
+
* All heavy lifting happens in EmDashRuntime.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineMiddleware } from "astro:middleware";
|
|
9
|
+
import { Kysely } from "kysely";
|
|
10
|
+
// Import from virtual modules (populated by integration at build time)
|
|
11
|
+
// @ts-ignore - virtual module
|
|
12
|
+
import virtualConfig from "virtual:emdash/config";
|
|
13
|
+
// @ts-ignore - virtual module
|
|
14
|
+
import {
|
|
15
|
+
createDialect as virtualCreateDialect,
|
|
16
|
+
isSessionEnabled as virtualIsSessionEnabled,
|
|
17
|
+
getD1Binding as virtualGetD1Binding,
|
|
18
|
+
getDefaultConstraint as virtualGetDefaultConstraint,
|
|
19
|
+
getBookmarkCookieName as virtualGetBookmarkCookieName,
|
|
20
|
+
createSessionDialect as virtualCreateSessionDialect,
|
|
21
|
+
} from "virtual:emdash/dialect";
|
|
22
|
+
// @ts-ignore - virtual module
|
|
23
|
+
import { mediaProviders as virtualMediaProviders } from "virtual:emdash/media-providers";
|
|
24
|
+
// @ts-ignore - virtual module
|
|
25
|
+
import { plugins as virtualPlugins } from "virtual:emdash/plugins";
|
|
26
|
+
import {
|
|
27
|
+
createSandboxRunner as virtualCreateSandboxRunner,
|
|
28
|
+
sandboxEnabled as virtualSandboxEnabled,
|
|
29
|
+
// @ts-ignore - virtual module
|
|
30
|
+
} from "virtual:emdash/sandbox-runner";
|
|
31
|
+
// @ts-ignore - virtual module
|
|
32
|
+
import { sandboxedPlugins as virtualSandboxedPlugins } from "virtual:emdash/sandboxed-plugins";
|
|
33
|
+
// @ts-ignore - virtual module
|
|
34
|
+
import { createStorage as virtualCreateStorage } from "virtual:emdash/storage";
|
|
35
|
+
|
|
36
|
+
import {
|
|
37
|
+
EmDashRuntime,
|
|
38
|
+
type RuntimeDependencies,
|
|
39
|
+
type SandboxedPluginEntry,
|
|
40
|
+
type MediaProviderEntry,
|
|
41
|
+
} from "../emdash-runtime.js";
|
|
42
|
+
import { setI18nConfig } from "../i18n/config.js";
|
|
43
|
+
import type { Database, Storage } from "../index.js";
|
|
44
|
+
import type { SandboxRunner } from "../plugins/sandbox/types.js";
|
|
45
|
+
import type { ResolvedPlugin } from "../plugins/types.js";
|
|
46
|
+
import { runWithContext } from "../request-context.js";
|
|
47
|
+
import type { EmDashConfig } from "./integration/runtime.js";
|
|
48
|
+
|
|
49
|
+
// Cached runtime instance (persists across requests within worker)
|
|
50
|
+
let runtimeInstance: EmDashRuntime | null = null;
|
|
51
|
+
// Whether initialization is in progress (prevents concurrent init attempts)
|
|
52
|
+
let runtimeInitializing = false;
|
|
53
|
+
|
|
54
|
+
/** Whether i18n config has been initialized from the virtual module */
|
|
55
|
+
let i18nInitialized = false;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get EmDash configuration from virtual module
|
|
59
|
+
*/
|
|
60
|
+
function getConfig(): EmDashConfig | null {
|
|
61
|
+
if (virtualConfig && typeof virtualConfig === "object") {
|
|
62
|
+
// Initialize i18n config on first access (once per worker lifetime)
|
|
63
|
+
if (!i18nInitialized) {
|
|
64
|
+
i18nInitialized = true;
|
|
65
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module checked as object above
|
|
66
|
+
const config = virtualConfig as Record<string, unknown>;
|
|
67
|
+
if (config.i18n && typeof config.i18n === "object") {
|
|
68
|
+
setI18nConfig(
|
|
69
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- runtime-checked above
|
|
70
|
+
config.i18n as {
|
|
71
|
+
defaultLocale: string;
|
|
72
|
+
locales: string[];
|
|
73
|
+
fallback?: Record<string, string>;
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
} else {
|
|
77
|
+
setI18nConfig(null);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
82
|
+
return virtualConfig as EmDashConfig;
|
|
83
|
+
}
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get plugins from virtual module
|
|
89
|
+
*/
|
|
90
|
+
function getPlugins(): ResolvedPlugin[] {
|
|
91
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
92
|
+
return (virtualPlugins as ResolvedPlugin[]) || [];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Build runtime dependencies from virtual modules
|
|
97
|
+
*/
|
|
98
|
+
function buildDependencies(config: EmDashConfig): RuntimeDependencies {
|
|
99
|
+
return {
|
|
100
|
+
config,
|
|
101
|
+
plugins: getPlugins(),
|
|
102
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
103
|
+
createDialect: virtualCreateDialect as (config: Record<string, unknown>) => unknown,
|
|
104
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
105
|
+
createStorage: virtualCreateStorage as ((config: Record<string, unknown>) => Storage) | null,
|
|
106
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
107
|
+
sandboxEnabled: virtualSandboxEnabled as boolean,
|
|
108
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
109
|
+
sandboxedPluginEntries: (virtualSandboxedPlugins as SandboxedPluginEntry[]) || [],
|
|
110
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
111
|
+
createSandboxRunner: virtualCreateSandboxRunner as
|
|
112
|
+
| ((opts: { db: Kysely<Database> }) => SandboxRunner)
|
|
113
|
+
| null,
|
|
114
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module import is untyped (@ts-ignore above)
|
|
115
|
+
mediaProviderEntries: (virtualMediaProviders as MediaProviderEntry[]) || [],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get or create the runtime instance
|
|
121
|
+
*/
|
|
122
|
+
async function getRuntime(config: EmDashConfig): Promise<EmDashRuntime> {
|
|
123
|
+
// Return cached instance if available
|
|
124
|
+
if (runtimeInstance) {
|
|
125
|
+
return runtimeInstance;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// If another request is already initializing, wait and retry.
|
|
129
|
+
// We don't share the promise across requests because workerd flags
|
|
130
|
+
// cross-request promise resolution (causes warnings + potential hangs).
|
|
131
|
+
if (runtimeInitializing) {
|
|
132
|
+
// Poll until the initializing request finishes
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
134
|
+
return getRuntime(config);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
runtimeInitializing = true;
|
|
138
|
+
try {
|
|
139
|
+
const deps = buildDependencies(config);
|
|
140
|
+
const runtime = await EmDashRuntime.create(deps);
|
|
141
|
+
runtimeInstance = runtime;
|
|
142
|
+
return runtime;
|
|
143
|
+
} finally {
|
|
144
|
+
runtimeInitializing = false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Baseline security headers applied to all responses.
|
|
150
|
+
* Admin routes get additional headers (strict CSP) from auth middleware.
|
|
151
|
+
*/
|
|
152
|
+
function setBaselineSecurityHeaders(response: Response): void {
|
|
153
|
+
// Prevent MIME type sniffing
|
|
154
|
+
response.headers.set("X-Content-Type-Options", "nosniff");
|
|
155
|
+
// Control referrer information
|
|
156
|
+
response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
157
|
+
// Restrict access to sensitive browser APIs
|
|
158
|
+
response.headers.set(
|
|
159
|
+
"Permissions-Policy",
|
|
160
|
+
"camera=(), microphone=(), geolocation=(), payment=()",
|
|
161
|
+
);
|
|
162
|
+
// Prevent clickjacking (non-admin routes; admin CSP uses frame-ancestors)
|
|
163
|
+
if (!response.headers.has("Content-Security-Policy")) {
|
|
164
|
+
response.headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Public routes that require the runtime (sitemap, robots.txt, etc.) */
|
|
169
|
+
const PUBLIC_RUNTIME_ROUTES = new Set(["/sitemap.xml", "/robots.txt"]);
|
|
170
|
+
|
|
171
|
+
export const onRequest = defineMiddleware(async (context, next) => {
|
|
172
|
+
const { request, locals, cookies } = context;
|
|
173
|
+
const url = context.url;
|
|
174
|
+
|
|
175
|
+
// Process /_emdash routes and public routes with an active session
|
|
176
|
+
// (logged-in editors need the runtime for toolbar/visual editing on public pages)
|
|
177
|
+
const isEmDashRoute = url.pathname.startsWith("/_emdash");
|
|
178
|
+
const isPublicRuntimeRoute = PUBLIC_RUNTIME_ROUTES.has(url.pathname);
|
|
179
|
+
|
|
180
|
+
// Check for edit mode cookie - editors viewing public pages need the runtime
|
|
181
|
+
// so auth middleware can verify their session for visual editing
|
|
182
|
+
const hasEditCookie = cookies.get("emdash-edit-mode")?.value === "true";
|
|
183
|
+
const hasPreviewToken = url.searchParams.has("_preview");
|
|
184
|
+
|
|
185
|
+
// Playground mode: the playground middleware stashes the per-session DO database
|
|
186
|
+
// on locals.__playgroundDb. When present, use runWithContext() to make it
|
|
187
|
+
// available to getDb() and the runtime's db getter via the correct ALS instance.
|
|
188
|
+
const playgroundDb = locals.__playgroundDb;
|
|
189
|
+
|
|
190
|
+
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
|
191
|
+
const sessionUser = await context.session?.get("user");
|
|
192
|
+
if (!sessionUser && !playgroundDb) {
|
|
193
|
+
const response = await next();
|
|
194
|
+
setBaselineSecurityHeaders(response);
|
|
195
|
+
return response;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const config = getConfig();
|
|
200
|
+
if (!config) {
|
|
201
|
+
console.error("EmDash: No configuration found");
|
|
202
|
+
return next();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// In playground mode, wrap the entire runtime init + request handling in
|
|
206
|
+
// runWithContext so that getDatabase() and all init queries use the real
|
|
207
|
+
// DO database via the same AsyncLocalStorage instance as the loader.
|
|
208
|
+
const doInit = async () => {
|
|
209
|
+
try {
|
|
210
|
+
// Get or create runtime
|
|
211
|
+
const runtime = await getRuntime(config);
|
|
212
|
+
|
|
213
|
+
// Get manifest (cached after first call)
|
|
214
|
+
const manifest = await runtime.getManifest();
|
|
215
|
+
|
|
216
|
+
// Attach to locals for route handlers
|
|
217
|
+
locals.emdashManifest = manifest;
|
|
218
|
+
locals.emdash = {
|
|
219
|
+
// Content handlers
|
|
220
|
+
handleContentList: runtime.handleContentList.bind(runtime),
|
|
221
|
+
handleContentGet: runtime.handleContentGet.bind(runtime),
|
|
222
|
+
handleContentCreate: runtime.handleContentCreate.bind(runtime),
|
|
223
|
+
handleContentUpdate: runtime.handleContentUpdate.bind(runtime),
|
|
224
|
+
handleContentDelete: runtime.handleContentDelete.bind(runtime),
|
|
225
|
+
|
|
226
|
+
// Trash handlers
|
|
227
|
+
handleContentListTrashed: runtime.handleContentListTrashed.bind(runtime),
|
|
228
|
+
handleContentRestore: runtime.handleContentRestore.bind(runtime),
|
|
229
|
+
handleContentPermanentDelete: runtime.handleContentPermanentDelete.bind(runtime),
|
|
230
|
+
handleContentCountTrashed: runtime.handleContentCountTrashed.bind(runtime),
|
|
231
|
+
handleContentGetIncludingTrashed: runtime.handleContentGetIncludingTrashed.bind(runtime),
|
|
232
|
+
|
|
233
|
+
// Duplicate handler
|
|
234
|
+
handleContentDuplicate: runtime.handleContentDuplicate.bind(runtime),
|
|
235
|
+
|
|
236
|
+
// Publishing & Scheduling handlers
|
|
237
|
+
handleContentPublish: runtime.handleContentPublish.bind(runtime),
|
|
238
|
+
handleContentUnpublish: runtime.handleContentUnpublish.bind(runtime),
|
|
239
|
+
handleContentSchedule: runtime.handleContentSchedule.bind(runtime),
|
|
240
|
+
handleContentUnschedule: runtime.handleContentUnschedule.bind(runtime),
|
|
241
|
+
handleContentCountScheduled: runtime.handleContentCountScheduled.bind(runtime),
|
|
242
|
+
handleContentDiscardDraft: runtime.handleContentDiscardDraft.bind(runtime),
|
|
243
|
+
handleContentCompare: runtime.handleContentCompare.bind(runtime),
|
|
244
|
+
handleContentTranslations: runtime.handleContentTranslations.bind(runtime),
|
|
245
|
+
|
|
246
|
+
// Media handlers
|
|
247
|
+
handleMediaList: runtime.handleMediaList.bind(runtime),
|
|
248
|
+
handleMediaGet: runtime.handleMediaGet.bind(runtime),
|
|
249
|
+
handleMediaCreate: runtime.handleMediaCreate.bind(runtime),
|
|
250
|
+
handleMediaUpdate: runtime.handleMediaUpdate.bind(runtime),
|
|
251
|
+
handleMediaDelete: runtime.handleMediaDelete.bind(runtime),
|
|
252
|
+
|
|
253
|
+
// Revision handlers
|
|
254
|
+
handleRevisionList: runtime.handleRevisionList.bind(runtime),
|
|
255
|
+
handleRevisionGet: runtime.handleRevisionGet.bind(runtime),
|
|
256
|
+
handleRevisionRestore: runtime.handleRevisionRestore.bind(runtime),
|
|
257
|
+
|
|
258
|
+
// Plugin routes
|
|
259
|
+
handlePluginApiRoute: runtime.handlePluginApiRoute.bind(runtime),
|
|
260
|
+
getPluginRouteMeta: runtime.getPluginRouteMeta.bind(runtime),
|
|
261
|
+
|
|
262
|
+
// Media provider methods
|
|
263
|
+
getMediaProvider: runtime.getMediaProvider.bind(runtime),
|
|
264
|
+
getMediaProviderList: runtime.getMediaProviderList.bind(runtime),
|
|
265
|
+
|
|
266
|
+
// Direct access (for advanced use cases)
|
|
267
|
+
storage: runtime.storage,
|
|
268
|
+
db: runtime.db,
|
|
269
|
+
hooks: runtime.hooks,
|
|
270
|
+
email: runtime.email,
|
|
271
|
+
configuredPlugins: runtime.configuredPlugins,
|
|
272
|
+
|
|
273
|
+
// Configuration (for checking database type, auth mode, etc.)
|
|
274
|
+
config,
|
|
275
|
+
|
|
276
|
+
// Manifest invalidation (call after schema changes)
|
|
277
|
+
invalidateManifest: runtime.invalidateManifest.bind(runtime),
|
|
278
|
+
|
|
279
|
+
// Sandbox runner (for marketplace plugin install/update)
|
|
280
|
+
getSandboxRunner: runtime.getSandboxRunner.bind(runtime),
|
|
281
|
+
|
|
282
|
+
// Sync marketplace plugin states (after install/update/uninstall)
|
|
283
|
+
syncMarketplacePlugins: runtime.syncMarketplacePlugins.bind(runtime),
|
|
284
|
+
|
|
285
|
+
// Update plugin enabled/disabled status and rebuild hook pipeline
|
|
286
|
+
setPluginStatus: runtime.setPluginStatus.bind(runtime),
|
|
287
|
+
};
|
|
288
|
+
} catch (error) {
|
|
289
|
+
console.error("EmDash middleware error:", error);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// =========================================================================
|
|
293
|
+
// D1 Read Replica Session Management
|
|
294
|
+
//
|
|
295
|
+
// When D1 sessions are enabled, we create a per-request D1 session and
|
|
296
|
+
// Kysely instance. The session is wrapped in ALS so `runtime.db` (a getter)
|
|
297
|
+
// picks up the per-request instance instead of the singleton.
|
|
298
|
+
//
|
|
299
|
+
// After the response, we extract the bookmark from the session and set
|
|
300
|
+
// it as a cookie for authenticated users (read-your-writes consistency).
|
|
301
|
+
// =========================================================================
|
|
302
|
+
const dbConfig = config?.database?.config;
|
|
303
|
+
const sessionEnabled =
|
|
304
|
+
dbConfig &&
|
|
305
|
+
typeof virtualIsSessionEnabled === "function" &&
|
|
306
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module functions are untyped
|
|
307
|
+
(virtualIsSessionEnabled as (config: unknown) => boolean)(dbConfig);
|
|
308
|
+
|
|
309
|
+
if (
|
|
310
|
+
sessionEnabled &&
|
|
311
|
+
typeof virtualGetD1Binding === "function" &&
|
|
312
|
+
virtualCreateSessionDialect
|
|
313
|
+
) {
|
|
314
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module functions are untyped
|
|
315
|
+
const d1Binding = (virtualGetD1Binding as (config: unknown) => unknown)(dbConfig);
|
|
316
|
+
|
|
317
|
+
if (d1Binding && typeof d1Binding === "object" && "withSession" in d1Binding) {
|
|
318
|
+
const isAuthenticated = !!(await context.session?.get("user"));
|
|
319
|
+
const isWrite = request.method !== "GET" && request.method !== "HEAD";
|
|
320
|
+
|
|
321
|
+
// Determine session constraint:
|
|
322
|
+
// - Config says "primary-first" → always "first-primary"
|
|
323
|
+
// - Authenticated writes → "first-primary" (need to hit primary)
|
|
324
|
+
// - Authenticated reads with bookmark → resume from bookmark
|
|
325
|
+
// - Otherwise → "first-unconstrained" (nearest replica)
|
|
326
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module functions are untyped
|
|
327
|
+
const configConstraint = (virtualGetDefaultConstraint as (config: unknown) => string)(
|
|
328
|
+
dbConfig,
|
|
329
|
+
);
|
|
330
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module functions are untyped
|
|
331
|
+
const cookieName = (virtualGetBookmarkCookieName as (config: unknown) => string)(dbConfig);
|
|
332
|
+
|
|
333
|
+
let constraint: string = configConstraint;
|
|
334
|
+
if (isAuthenticated && isWrite) {
|
|
335
|
+
constraint = "first-primary";
|
|
336
|
+
} else if (isAuthenticated) {
|
|
337
|
+
const bookmarkCookie = context.cookies.get(cookieName);
|
|
338
|
+
if (bookmarkCookie?.value) {
|
|
339
|
+
constraint = bookmarkCookie.value;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Create the D1 session and per-request Kysely instance.
|
|
344
|
+
// D1DatabaseSession has the same prepare()/batch() interface as D1Database,
|
|
345
|
+
// so createSessionDialect passes it straight to D1Dialect.
|
|
346
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- D1 binding with Sessions API, checked via "withSession" in d1Binding above
|
|
347
|
+
const withSession = (d1Binding as { withSession: (c: string) => unknown }).withSession;
|
|
348
|
+
const session = withSession.call(d1Binding, constraint);
|
|
349
|
+
const sessionDialect =
|
|
350
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- virtual module functions are untyped
|
|
351
|
+
(virtualCreateSessionDialect as (db: unknown) => import("kysely").Dialect)(session);
|
|
352
|
+
const sessionDb = new Kysely<Database>({ dialect: sessionDialect });
|
|
353
|
+
|
|
354
|
+
// Wrap the request in ALS with the per-request db
|
|
355
|
+
return runWithContext({ editMode: false, db: sessionDb }, async () => {
|
|
356
|
+
const response = await next();
|
|
357
|
+
setBaselineSecurityHeaders(response);
|
|
358
|
+
|
|
359
|
+
// Set bookmark cookie for authenticated users only — they need
|
|
360
|
+
// read-your-writes consistency across requests. Anonymous visitors
|
|
361
|
+
// don't write, so they get "first-unconstrained" every time.
|
|
362
|
+
if (
|
|
363
|
+
isAuthenticated &&
|
|
364
|
+
session &&
|
|
365
|
+
typeof session === "object" &&
|
|
366
|
+
"getBookmark" in session
|
|
367
|
+
) {
|
|
368
|
+
// eslint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- D1DatabaseSession with getBookmark()
|
|
369
|
+
const getBookmark = (session as { getBookmark: () => string | null }).getBookmark;
|
|
370
|
+
const newBookmark = getBookmark.call(session);
|
|
371
|
+
if (newBookmark) {
|
|
372
|
+
response.headers.append(
|
|
373
|
+
"Set-Cookie",
|
|
374
|
+
`${cookieName}=${newBookmark}; Path=/; HttpOnly; SameSite=Lax; Secure`,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return response;
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const response = await next();
|
|
385
|
+
setBaselineSecurityHeaders(response);
|
|
386
|
+
return response;
|
|
387
|
+
}; // end doInit
|
|
388
|
+
|
|
389
|
+
if (playgroundDb) {
|
|
390
|
+
// Read the edit-mode cookie to determine if visual editing is active.
|
|
391
|
+
// Default to false -- editing is opt-in via the playground toolbar toggle.
|
|
392
|
+
const editMode = context.cookies.get("emdash-edit-mode")?.value === "true";
|
|
393
|
+
return runWithContext({ editMode, db: playgroundDb }, doInit);
|
|
394
|
+
}
|
|
395
|
+
return doInit();
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
export default onRequest;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Admin Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Imports plugin admin modules from the virtual module and passes them
|
|
5
|
+
* to AdminApp via props. This ensures plugin components are bundled
|
|
6
|
+
* together with the admin app and available via React context.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { AdminApp } from "@emdash-cms/admin";
|
|
10
|
+
// @ts-ignore - virtual module generated by integration
|
|
11
|
+
import { pluginAdmins } from "virtual:emdash/admin-registry";
|
|
12
|
+
|
|
13
|
+
export default function AdminWrapper() {
|
|
14
|
+
return <AdminApp pluginAdmins={pluginAdmins} />;
|
|
15
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Admin shell route - injected by EmDash integration
|
|
4
|
+
*
|
|
5
|
+
* This page serves the EmDash admin React SPA.
|
|
6
|
+
* AdminWrapper imports plugin admin modules and passes them to AdminApp.
|
|
7
|
+
*/
|
|
8
|
+
import "@emdash-cms/admin/styles.css";
|
|
9
|
+
// Use package-qualified import so Astro generates a proper module URL
|
|
10
|
+
// (relative imports resolve to absolute paths which break client hydration)
|
|
11
|
+
import AdminWrapper from "emdash/routes/PluginRegistry";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<!doctype html>
|
|
17
|
+
<html lang="en">
|
|
18
|
+
<head>
|
|
19
|
+
<meta charset="UTF-8" />
|
|
20
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
21
|
+
<link
|
|
22
|
+
rel="icon"
|
|
23
|
+
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ctext y='.9em' font-size='90'%3E%F0%9F%92%AB%3C/text%3E%3C/svg%3E"
|
|
24
|
+
/>
|
|
25
|
+
<title>EmDash Admin</title>
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<div id="admin-root" class="min-h-screen">
|
|
29
|
+
<div id="emdash-boot-loader">
|
|
30
|
+
<style>
|
|
31
|
+
#emdash-boot-loader {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
min-height: 100vh;
|
|
36
|
+
color-scheme: light dark;
|
|
37
|
+
background: light-dark(hsl(0 0% 100%), hsl(222.2 84% 4.9%));
|
|
38
|
+
}
|
|
39
|
+
#emdash-boot-loader .loader-inner {
|
|
40
|
+
text-align: center;
|
|
41
|
+
}
|
|
42
|
+
#emdash-boot-loader .spinner {
|
|
43
|
+
width: 24px;
|
|
44
|
+
height: 24px;
|
|
45
|
+
margin: 0 auto;
|
|
46
|
+
border: 2.5px solid
|
|
47
|
+
light-dark(
|
|
48
|
+
hsl(215.4 16.3% 46.9% / 0.3),
|
|
49
|
+
hsl(215 20.2% 65.1% / 0.3)
|
|
50
|
+
);
|
|
51
|
+
border-top-color: light-dark(
|
|
52
|
+
hsl(215.4 16.3% 46.9%),
|
|
53
|
+
hsl(215 20.2% 65.1%)
|
|
54
|
+
);
|
|
55
|
+
border-radius: 50%;
|
|
56
|
+
animation: emdash-spin 0.8s linear infinite;
|
|
57
|
+
}
|
|
58
|
+
#emdash-boot-loader p {
|
|
59
|
+
margin-top: 1rem;
|
|
60
|
+
font-family:
|
|
61
|
+
system-ui,
|
|
62
|
+
-apple-system,
|
|
63
|
+
sans-serif;
|
|
64
|
+
font-size: 0.875rem;
|
|
65
|
+
color: light-dark(hsl(215.4 16.3% 46.9%), hsl(215 20.2% 65.1%));
|
|
66
|
+
}
|
|
67
|
+
@keyframes emdash-spin {
|
|
68
|
+
to {
|
|
69
|
+
transform: rotate(360deg);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
73
|
+
<div class="loader-inner">
|
|
74
|
+
<div class="spinner"></div>
|
|
75
|
+
<p>Loading EmDash...</p>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
<AdminWrapper client:only="react" />
|
|
79
|
+
</div>
|
|
80
|
+
</body>
|
|
81
|
+
</html>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PATCH/DELETE /_emdash/api/admin/allowed-domains/[domain]
|
|
3
|
+
*
|
|
4
|
+
* Admin endpoints for managing a specific allowed domain.
|
|
5
|
+
* PATCH - Update domain settings (enabled, defaultRole)
|
|
6
|
+
* DELETE - Remove an allowed domain
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { APIRoute } from "astro";
|
|
10
|
+
|
|
11
|
+
export const prerender = false;
|
|
12
|
+
|
|
13
|
+
import { Role, roleFromLevel } from "@emdash-cms/auth";
|
|
14
|
+
import { createKyselyAdapter } from "@emdash-cms/auth/adapters/kysely";
|
|
15
|
+
|
|
16
|
+
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
17
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
18
|
+
import { allowedDomainUpdateBody } from "#api/schemas.js";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* PATCH - Update domain settings
|
|
22
|
+
*/
|
|
23
|
+
export const PATCH: APIRoute = async ({ params, request, locals }) => {
|
|
24
|
+
const { emdash, user } = locals;
|
|
25
|
+
const { domain } = params;
|
|
26
|
+
|
|
27
|
+
if (!emdash?.db) {
|
|
28
|
+
return apiError("NOT_CONFIGURED", "Database not configured", 500);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!domain) {
|
|
32
|
+
return apiError("VALIDATION_ERROR", "Domain is required", 400);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!user || user.role < Role.ADMIN) {
|
|
36
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const adapter = createKyselyAdapter(emdash.db);
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const body = await parseBody(request, allowedDomainUpdateBody);
|
|
43
|
+
if (isParseError(body)) return body;
|
|
44
|
+
|
|
45
|
+
// Check if domain exists
|
|
46
|
+
const existing = await adapter.getAllowedDomain(domain);
|
|
47
|
+
if (!existing) {
|
|
48
|
+
return apiError("NOT_FOUND", "Domain not found", 404);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Role is already validated as RoleLevel by Zod schema
|
|
52
|
+
const defaultRole = body.defaultRole;
|
|
53
|
+
|
|
54
|
+
// Update domain
|
|
55
|
+
const enabled = body.enabled ?? existing.enabled;
|
|
56
|
+
await adapter.updateAllowedDomain(domain, enabled, defaultRole);
|
|
57
|
+
|
|
58
|
+
// Fetch updated domain
|
|
59
|
+
const updated = await adapter.getAllowedDomain(domain);
|
|
60
|
+
|
|
61
|
+
return apiSuccess({
|
|
62
|
+
success: true,
|
|
63
|
+
domain: updated
|
|
64
|
+
? {
|
|
65
|
+
domain: updated.domain,
|
|
66
|
+
defaultRole: updated.defaultRole,
|
|
67
|
+
roleName: roleFromLevel(updated.defaultRole),
|
|
68
|
+
enabled: updated.enabled,
|
|
69
|
+
createdAt: updated.createdAt.toISOString(),
|
|
70
|
+
}
|
|
71
|
+
: null,
|
|
72
|
+
});
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return handleError(error, "Failed to update allowed domain", "DOMAIN_UPDATE_ERROR");
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* DELETE - Remove an allowed domain
|
|
80
|
+
*/
|
|
81
|
+
export const DELETE: APIRoute = async ({ params, locals }) => {
|
|
82
|
+
const { emdash, user } = locals;
|
|
83
|
+
const { domain } = params;
|
|
84
|
+
|
|
85
|
+
if (!emdash?.db) {
|
|
86
|
+
return apiError("NOT_CONFIGURED", "Database not configured", 500);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!domain) {
|
|
90
|
+
return apiError("VALIDATION_ERROR", "Domain is required", 400);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!user || user.role < Role.ADMIN) {
|
|
94
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const adapter = createKyselyAdapter(emdash.db);
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
// Check if domain exists (optional - delete is idempotent)
|
|
101
|
+
const existing = await adapter.getAllowedDomain(domain);
|
|
102
|
+
if (!existing) {
|
|
103
|
+
return apiError("NOT_FOUND", "Domain not found", 404);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
await adapter.deleteAllowedDomain(domain);
|
|
107
|
+
|
|
108
|
+
return apiSuccess({ success: true });
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return handleError(error, "Failed to delete allowed domain", "DOMAIN_DELETE_ERROR");
|
|
111
|
+
}
|
|
112
|
+
};
|