emdash 0.0.0-b → 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 -43
- 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,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exclusive hook selection endpoint
|
|
3
|
+
*
|
|
4
|
+
* PUT /_emdash/api/admin/hooks/exclusive/:hookName
|
|
5
|
+
*
|
|
6
|
+
* Sets or clears the selected provider for an exclusive hook.
|
|
7
|
+
* Body: { pluginId: string | null }
|
|
8
|
+
* Requires settings:manage permission.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { APIRoute } from "astro";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
import { requirePerm } from "#api/authorize.js";
|
|
15
|
+
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
16
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
17
|
+
import { OptionsRepository } from "#db/repositories/options.js";
|
|
18
|
+
|
|
19
|
+
export const prerender = false;
|
|
20
|
+
|
|
21
|
+
/** Hook name format: namespace:action (e.g., "content:beforeSave") */
|
|
22
|
+
const HOOK_NAME_RE = /^[a-z]+:[a-zA-Z]+$/;
|
|
23
|
+
|
|
24
|
+
const setSelectionSchema = z.object({
|
|
25
|
+
pluginId: z.string().min(1).nullable(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
29
|
+
const { emdash, user } = locals;
|
|
30
|
+
|
|
31
|
+
if (!emdash?.db) {
|
|
32
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const denied = requirePerm(user, "settings:manage");
|
|
36
|
+
if (denied) return denied;
|
|
37
|
+
|
|
38
|
+
const hookName = params.hookName;
|
|
39
|
+
if (!hookName) {
|
|
40
|
+
return apiError("VALIDATION_ERROR", "Hook name is required", 400);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Validate hook name format: must be namespace:action (e.g., "content:beforeSave")
|
|
44
|
+
if (!HOOK_NAME_RE.test(hookName)) {
|
|
45
|
+
return apiError("VALIDATION_ERROR", "Invalid hook name format", 400);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const pipeline = emdash.hooks;
|
|
50
|
+
|
|
51
|
+
// Verify this is actually an exclusive hook
|
|
52
|
+
if (!pipeline.isExclusiveHook(hookName)) {
|
|
53
|
+
return apiError("NOT_FOUND", `Hook '${hookName}' is not a registered exclusive hook`, 404);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const body = await parseBody(request, setSelectionSchema);
|
|
57
|
+
if (isParseError(body)) return body;
|
|
58
|
+
|
|
59
|
+
const optionsRepo = new OptionsRepository(emdash.db);
|
|
60
|
+
const optionKey = `emdash:exclusive_hook:${hookName}`;
|
|
61
|
+
|
|
62
|
+
if (body.pluginId === null) {
|
|
63
|
+
// Clear the selection
|
|
64
|
+
await optionsRepo.delete(optionKey);
|
|
65
|
+
pipeline.clearExclusiveSelection(hookName);
|
|
66
|
+
} else {
|
|
67
|
+
// Validate that the pluginId is an actual provider for this hook
|
|
68
|
+
const providers = pipeline.getExclusiveHookProviders(hookName);
|
|
69
|
+
const isValidProvider = providers.some(
|
|
70
|
+
(p: { pluginId: string }) => p.pluginId === body.pluginId,
|
|
71
|
+
);
|
|
72
|
+
if (!isValidProvider) {
|
|
73
|
+
return apiError(
|
|
74
|
+
"VALIDATION_ERROR",
|
|
75
|
+
`Plugin '${body.pluginId}' is not a provider for hook '${hookName}'`,
|
|
76
|
+
400,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await optionsRepo.set(optionKey, body.pluginId);
|
|
81
|
+
pipeline.setExclusiveSelection(hookName, body.pluginId);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return apiSuccess({
|
|
85
|
+
hookName,
|
|
86
|
+
selectedPluginId: body.pluginId,
|
|
87
|
+
});
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return handleError(error, "Failed to set exclusive hook selection", "EXCLUSIVE_HOOK_SET_ERROR");
|
|
90
|
+
}
|
|
91
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exclusive hooks list endpoint
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/hooks/exclusive
|
|
5
|
+
*
|
|
6
|
+
* Lists all exclusive hooks with their providers and current selections.
|
|
7
|
+
* Requires admin role.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { APIRoute } from "astro";
|
|
11
|
+
|
|
12
|
+
import { requirePerm } from "#api/authorize.js";
|
|
13
|
+
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
14
|
+
import { OptionsRepository } from "#db/repositories/options.js";
|
|
15
|
+
|
|
16
|
+
export const prerender = false;
|
|
17
|
+
|
|
18
|
+
export const GET: APIRoute = async ({ locals }) => {
|
|
19
|
+
const { emdash, user } = locals;
|
|
20
|
+
|
|
21
|
+
if (!emdash?.db) {
|
|
22
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const denied = requirePerm(user, "settings:manage");
|
|
26
|
+
if (denied) return denied;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const pipeline = emdash.hooks;
|
|
30
|
+
const exclusiveHookNames = pipeline.getRegisteredExclusiveHooks();
|
|
31
|
+
const optionsRepo = new OptionsRepository(emdash.db);
|
|
32
|
+
|
|
33
|
+
const hooks = [];
|
|
34
|
+
for (const hookName of exclusiveHookNames) {
|
|
35
|
+
const providers = pipeline.getExclusiveHookProviders(hookName);
|
|
36
|
+
const selection = await optionsRepo.get<string>(`emdash:exclusive_hook:${hookName}`);
|
|
37
|
+
|
|
38
|
+
hooks.push({
|
|
39
|
+
hookName,
|
|
40
|
+
providers: providers.map((provider: { pluginId: string }) => ({
|
|
41
|
+
pluginId: provider.pluginId,
|
|
42
|
+
})),
|
|
43
|
+
selectedPluginId: selection,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return apiSuccess({ items: hooks });
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return handleError(error, "Failed to list exclusive hooks", "EXCLUSIVE_HOOKS_LIST_ERROR");
|
|
50
|
+
}
|
|
51
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single OAuth client endpoints
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/oauth-clients/:id — Get a client
|
|
5
|
+
* PUT /_emdash/api/admin/oauth-clients/:id — Update a client
|
|
6
|
+
* DELETE /_emdash/api/admin/oauth-clients/:id — Delete a client
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Role } from "@emdash-cms/auth";
|
|
10
|
+
import type { APIRoute } from "astro";
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
import { apiError, handleError, unwrapResult } from "#api/error.js";
|
|
14
|
+
import {
|
|
15
|
+
handleOAuthClientDelete,
|
|
16
|
+
handleOAuthClientGet,
|
|
17
|
+
handleOAuthClientUpdate,
|
|
18
|
+
} from "#api/handlers/oauth-clients.js";
|
|
19
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
20
|
+
|
|
21
|
+
export const prerender = false;
|
|
22
|
+
|
|
23
|
+
const updateClientSchema = z.object({
|
|
24
|
+
name: z.string().min(1).max(255).optional(),
|
|
25
|
+
redirectUris: z
|
|
26
|
+
.array(z.string().url("Each redirect URI must be a valid URL"))
|
|
27
|
+
.min(1, "At least one redirect URI is required")
|
|
28
|
+
.optional(),
|
|
29
|
+
scopes: z.array(z.string()).nullable().optional(),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get a single OAuth client.
|
|
34
|
+
*/
|
|
35
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
36
|
+
const { emdash, user } = locals;
|
|
37
|
+
|
|
38
|
+
if (!emdash?.db) {
|
|
39
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!user || user.role < Role.ADMIN) {
|
|
43
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const clientId = params.id;
|
|
47
|
+
if (!clientId) {
|
|
48
|
+
return apiError("VALIDATION_ERROR", "Client ID is required", 400);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = await handleOAuthClientGet(emdash.db, clientId);
|
|
52
|
+
return unwrapResult(result);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Update an OAuth client.
|
|
57
|
+
*/
|
|
58
|
+
export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
59
|
+
const { emdash, user } = locals;
|
|
60
|
+
|
|
61
|
+
if (!emdash?.db) {
|
|
62
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!user || user.role < Role.ADMIN) {
|
|
66
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const clientId = params.id;
|
|
70
|
+
if (!clientId) {
|
|
71
|
+
return apiError("VALIDATION_ERROR", "Client ID is required", 400);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const body = await parseBody(request, updateClientSchema);
|
|
76
|
+
if (isParseError(body)) return body;
|
|
77
|
+
|
|
78
|
+
const result = await handleOAuthClientUpdate(emdash.db, clientId, body);
|
|
79
|
+
return unwrapResult(result);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
return handleError(error, "Failed to update OAuth client", "CLIENT_UPDATE_ERROR");
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Delete an OAuth client.
|
|
87
|
+
*/
|
|
88
|
+
export const DELETE: APIRoute = async ({ params, locals }) => {
|
|
89
|
+
const { emdash, user } = locals;
|
|
90
|
+
|
|
91
|
+
if (!emdash?.db) {
|
|
92
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!user || user.role < Role.ADMIN) {
|
|
96
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const clientId = params.id;
|
|
100
|
+
if (!clientId) {
|
|
101
|
+
return apiError("VALIDATION_ERROR", "Client ID is required", 400);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const result = await handleOAuthClientDelete(emdash.db, clientId);
|
|
106
|
+
return unwrapResult(result);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return handleError(error, "Failed to delete OAuth client", "CLIENT_DELETE_ERROR");
|
|
109
|
+
}
|
|
110
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth client management endpoints
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/oauth-clients — List all registered OAuth clients
|
|
5
|
+
* POST /_emdash/api/admin/oauth-clients — Register a new OAuth client
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Role } from "@emdash-cms/auth";
|
|
9
|
+
import type { APIRoute } from "astro";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
12
|
+
import { apiError, handleError, unwrapResult } from "#api/error.js";
|
|
13
|
+
import { handleOAuthClientCreate, handleOAuthClientList } from "#api/handlers/oauth-clients.js";
|
|
14
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
15
|
+
|
|
16
|
+
export const prerender = false;
|
|
17
|
+
|
|
18
|
+
const createClientSchema = z.object({
|
|
19
|
+
id: z
|
|
20
|
+
.string()
|
|
21
|
+
.min(1, "Client ID is required")
|
|
22
|
+
.max(255, "Client ID must be at most 255 characters"),
|
|
23
|
+
name: z.string().min(1, "Name is required").max(255, "Name must be at most 255 characters"),
|
|
24
|
+
redirectUris: z
|
|
25
|
+
.array(z.string().url("Each redirect URI must be a valid URL"))
|
|
26
|
+
.min(1, "At least one redirect URI is required"),
|
|
27
|
+
scopes: z.array(z.string()).optional(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* List all registered OAuth clients.
|
|
32
|
+
*/
|
|
33
|
+
export const GET: APIRoute = async ({ locals }) => {
|
|
34
|
+
const { emdash, user } = locals;
|
|
35
|
+
|
|
36
|
+
if (!emdash?.db) {
|
|
37
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!user || user.role < Role.ADMIN) {
|
|
41
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const result = await handleOAuthClientList(emdash.db);
|
|
45
|
+
return unwrapResult(result);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Register a new OAuth client.
|
|
50
|
+
*/
|
|
51
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
52
|
+
const { emdash, user } = locals;
|
|
53
|
+
|
|
54
|
+
if (!emdash?.db) {
|
|
55
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!user || user.role < Role.ADMIN) {
|
|
59
|
+
return apiError("FORBIDDEN", "Admin privileges required", 403);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const body = await parseBody(request, createClientSchema);
|
|
64
|
+
if (isParseError(body)) return body;
|
|
65
|
+
|
|
66
|
+
const result = await handleOAuthClientCreate(emdash.db, body);
|
|
67
|
+
return unwrapResult(result, 201);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return handleError(error, "Failed to create OAuth client", "CLIENT_CREATE_ERROR");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin disable endpoint
|
|
3
|
+
*
|
|
4
|
+
* POST /_emdash/api/admin/plugins/:id/disable - Disable a plugin
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
|
|
9
|
+
import { requirePerm } from "#api/authorize.js";
|
|
10
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
11
|
+
import { handlePluginDisable } from "#api/index.js";
|
|
12
|
+
import { setCronTasksEnabled } from "#plugins/cron.js";
|
|
13
|
+
|
|
14
|
+
export const prerender = false;
|
|
15
|
+
|
|
16
|
+
export const POST: APIRoute = async ({ params, locals }) => {
|
|
17
|
+
const { emdash, user } = locals;
|
|
18
|
+
const { id } = params;
|
|
19
|
+
|
|
20
|
+
if (!emdash?.db) {
|
|
21
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const denied = requirePerm(user, "plugins:manage");
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
|
|
27
|
+
if (!id) {
|
|
28
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const result = await handlePluginDisable(emdash.db, emdash.configuredPlugins, id);
|
|
32
|
+
|
|
33
|
+
if (!result.success) return unwrapResult(result);
|
|
34
|
+
|
|
35
|
+
await emdash.setPluginStatus(id, "inactive");
|
|
36
|
+
await setCronTasksEnabled(emdash.db, id, false);
|
|
37
|
+
|
|
38
|
+
return unwrapResult(result);
|
|
39
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin enable endpoint
|
|
3
|
+
*
|
|
4
|
+
* POST /_emdash/api/admin/plugins/:id/enable - Enable a plugin
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
|
|
9
|
+
import { requirePerm } from "#api/authorize.js";
|
|
10
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
11
|
+
import { handlePluginEnable } from "#api/index.js";
|
|
12
|
+
import { setCronTasksEnabled } from "#plugins/cron.js";
|
|
13
|
+
|
|
14
|
+
export const prerender = false;
|
|
15
|
+
|
|
16
|
+
export const POST: APIRoute = async ({ params, locals }) => {
|
|
17
|
+
const { emdash, user } = locals;
|
|
18
|
+
const { id } = params;
|
|
19
|
+
|
|
20
|
+
if (!emdash?.db) {
|
|
21
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const denied = requirePerm(user, "plugins:manage");
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
|
|
27
|
+
if (!id) {
|
|
28
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const result = await handlePluginEnable(emdash.db, emdash.configuredPlugins, id);
|
|
32
|
+
|
|
33
|
+
if (!result.success) return unwrapResult(result);
|
|
34
|
+
|
|
35
|
+
await emdash.setPluginStatus(id, "active");
|
|
36
|
+
await setCronTasksEnabled(emdash.db, id, true);
|
|
37
|
+
|
|
38
|
+
return unwrapResult(result);
|
|
39
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin management single plugin endpoint
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/plugins/:id - Get plugin details
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
|
|
9
|
+
import { requirePerm } from "#api/authorize.js";
|
|
10
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
11
|
+
import { handlePluginGet } from "#api/index.js";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
16
|
+
const { emdash, user } = locals;
|
|
17
|
+
const { id } = params;
|
|
18
|
+
|
|
19
|
+
if (!emdash?.db) {
|
|
20
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const denied = requirePerm(user, "plugins:read");
|
|
24
|
+
if (denied) return denied;
|
|
25
|
+
|
|
26
|
+
if (!id) {
|
|
27
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const result = await handlePluginGet(
|
|
31
|
+
emdash.db,
|
|
32
|
+
emdash.configuredPlugins,
|
|
33
|
+
id,
|
|
34
|
+
emdash.config.marketplace,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return unwrapResult(result);
|
|
38
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marketplace plugin uninstall endpoint
|
|
3
|
+
*
|
|
4
|
+
* POST /_emdash/api/admin/plugins/:id/uninstall - Uninstall a marketplace plugin
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { requirePerm } from "#api/authorize.js";
|
|
11
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
12
|
+
import { handleMarketplaceUninstall } from "#api/index.js";
|
|
13
|
+
import { isParseError, parseOptionalBody } from "#api/parse.js";
|
|
14
|
+
|
|
15
|
+
export const prerender = false;
|
|
16
|
+
|
|
17
|
+
const uninstallBodySchema = z.object({
|
|
18
|
+
deleteData: z.boolean().optional(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
22
|
+
const { emdash, user } = locals;
|
|
23
|
+
const { id } = params;
|
|
24
|
+
|
|
25
|
+
if (!emdash?.db) {
|
|
26
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const denied = requirePerm(user, "plugins:manage");
|
|
30
|
+
if (denied) return denied;
|
|
31
|
+
|
|
32
|
+
if (!id) {
|
|
33
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const body = await parseOptionalBody(request, uninstallBodySchema, {});
|
|
37
|
+
if (isParseError(body)) return body;
|
|
38
|
+
|
|
39
|
+
const result = await handleMarketplaceUninstall(emdash.db, emdash.storage, id, {
|
|
40
|
+
deleteData: body.deleteData ?? false,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
if (!result.success) return unwrapResult(result);
|
|
44
|
+
|
|
45
|
+
await emdash.syncMarketplacePlugins();
|
|
46
|
+
|
|
47
|
+
return unwrapResult(result);
|
|
48
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marketplace plugin update endpoint
|
|
3
|
+
*
|
|
4
|
+
* POST /_emdash/api/admin/plugins/:id/update - Update a marketplace plugin
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { requirePerm } from "#api/authorize.js";
|
|
11
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
12
|
+
import { handleMarketplaceUpdate } from "#api/index.js";
|
|
13
|
+
import { isParseError, parseOptionalBody } from "#api/parse.js";
|
|
14
|
+
|
|
15
|
+
export const prerender = false;
|
|
16
|
+
|
|
17
|
+
const updateBodySchema = z.object({
|
|
18
|
+
version: z.string().min(1).optional(),
|
|
19
|
+
confirmCapabilityChanges: z.boolean().optional(),
|
|
20
|
+
confirmRouteVisibilityChanges: z.boolean().optional(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
24
|
+
const { emdash, user } = locals;
|
|
25
|
+
const { id } = params;
|
|
26
|
+
|
|
27
|
+
if (!emdash?.db) {
|
|
28
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const denied = requirePerm(user, "plugins:manage");
|
|
32
|
+
if (denied) return denied;
|
|
33
|
+
|
|
34
|
+
if (!id) {
|
|
35
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const body = await parseOptionalBody(request, updateBodySchema, {});
|
|
39
|
+
if (isParseError(body)) return body;
|
|
40
|
+
|
|
41
|
+
const result = await handleMarketplaceUpdate(
|
|
42
|
+
emdash.db,
|
|
43
|
+
emdash.storage,
|
|
44
|
+
emdash.getSandboxRunner(),
|
|
45
|
+
emdash.config.marketplace,
|
|
46
|
+
id,
|
|
47
|
+
{
|
|
48
|
+
version: body.version,
|
|
49
|
+
confirmCapabilityChanges: body.confirmCapabilityChanges,
|
|
50
|
+
confirmRouteVisibilityChanges: body.confirmRouteVisibilityChanges,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (!result.success) return unwrapResult(result);
|
|
55
|
+
|
|
56
|
+
await emdash.syncMarketplacePlugins();
|
|
57
|
+
|
|
58
|
+
return unwrapResult(result);
|
|
59
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin management list endpoint
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/plugins - List all configured plugins with state
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
|
|
9
|
+
import { requirePerm } from "#api/authorize.js";
|
|
10
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
11
|
+
import { handlePluginList } from "#api/index.js";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
export const GET: APIRoute = async ({ locals }) => {
|
|
16
|
+
const { emdash, user } = locals;
|
|
17
|
+
|
|
18
|
+
if (!emdash?.db) {
|
|
19
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const denied = requirePerm(user, "plugins:read");
|
|
23
|
+
if (denied) return denied;
|
|
24
|
+
|
|
25
|
+
const result = await handlePluginList(
|
|
26
|
+
emdash.db,
|
|
27
|
+
emdash.configuredPlugins,
|
|
28
|
+
emdash.config.marketplace,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return unwrapResult(result);
|
|
32
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marketplace plugin icon proxy
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/plugins/marketplace/:id/icon - Proxy icon from marketplace
|
|
5
|
+
*
|
|
6
|
+
* Avoids CORS/auth issues when the marketplace Worker is behind Cloudflare Access
|
|
7
|
+
* or on a different origin. The admin UI uses this instead of linking directly.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { APIRoute } from "astro";
|
|
11
|
+
|
|
12
|
+
import { requirePerm } from "#api/authorize.js";
|
|
13
|
+
import { apiError } from "#api/error.js";
|
|
14
|
+
|
|
15
|
+
export const prerender = false;
|
|
16
|
+
|
|
17
|
+
export const GET: APIRoute = async ({ params, url, locals }) => {
|
|
18
|
+
const { emdash, user } = locals;
|
|
19
|
+
const { id } = params;
|
|
20
|
+
|
|
21
|
+
if (!emdash?.db) {
|
|
22
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const denied = requirePerm(user, "plugins:read");
|
|
26
|
+
if (denied) return denied;
|
|
27
|
+
|
|
28
|
+
const marketplaceUrl = emdash.config.marketplace;
|
|
29
|
+
if (!marketplaceUrl || !id) {
|
|
30
|
+
return apiError("NOT_CONFIGURED", "Marketplace not configured", 400);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const width = url.searchParams.get("w");
|
|
34
|
+
const target = new URL(`/api/v1/plugins/${encodeURIComponent(id)}/icon`, marketplaceUrl);
|
|
35
|
+
if (width) target.searchParams.set("w", width);
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const resp = await fetch(target.href);
|
|
39
|
+
if (!resp.ok) {
|
|
40
|
+
// Allowlist: only forward Content-Type from upstream.
|
|
41
|
+
// Never copy all upstream headers (denylist approach leaks
|
|
42
|
+
// headers we haven't anticipated).
|
|
43
|
+
return new Response(resp.body, {
|
|
44
|
+
status: resp.status,
|
|
45
|
+
headers: {
|
|
46
|
+
"Content-Type": resp.headers.get("Content-Type") ?? "application/octet-stream",
|
|
47
|
+
"Cache-Control": "private, no-store",
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return new Response(resp.body, {
|
|
53
|
+
headers: {
|
|
54
|
+
"Content-Type": resp.headers.get("Content-Type") ?? "image/png",
|
|
55
|
+
"Cache-Control": "private, no-store",
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
} catch {
|
|
59
|
+
return apiError("PROXY_ERROR", "Failed to fetch icon", 502);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marketplace plugin detail proxy endpoint
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/admin/plugins/marketplace/:id - Get plugin details
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { APIRoute } from "astro";
|
|
8
|
+
|
|
9
|
+
import { requirePerm } from "#api/authorize.js";
|
|
10
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
11
|
+
import { handleMarketplaceGetPlugin } from "#api/index.js";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
16
|
+
const { emdash, user } = locals;
|
|
17
|
+
const { id } = params;
|
|
18
|
+
|
|
19
|
+
if (!emdash?.db) {
|
|
20
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const denied = requirePerm(user, "plugins:read");
|
|
24
|
+
if (denied) return denied;
|
|
25
|
+
|
|
26
|
+
if (!id) {
|
|
27
|
+
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const result = await handleMarketplaceGetPlugin(emdash.config.marketplace, id);
|
|
31
|
+
|
|
32
|
+
return unwrapResult(result);
|
|
33
|
+
};
|