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,595 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Manager v2
|
|
3
|
+
*
|
|
4
|
+
* Central orchestrator for the plugin system:
|
|
5
|
+
* - Loads and resolves plugins
|
|
6
|
+
* - Manages plugin lifecycle (install, activate, deactivate, uninstall)
|
|
7
|
+
* - Dispatches hooks across all plugins
|
|
8
|
+
* - Routes API requests to plugins
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { Kysely } from "kysely";
|
|
13
|
+
import { sql } from "kysely";
|
|
14
|
+
|
|
15
|
+
import { OptionsRepository } from "../database/repositories/options.js";
|
|
16
|
+
import type { Database } from "../database/types.js";
|
|
17
|
+
import type { Storage } from "../storage/types.js";
|
|
18
|
+
import type { PluginContextFactoryOptions } from "./context.js";
|
|
19
|
+
import { setCronTasksEnabled } from "./cron.js";
|
|
20
|
+
import { definePlugin } from "./define-plugin.js";
|
|
21
|
+
import {
|
|
22
|
+
HookPipeline,
|
|
23
|
+
type HookResult,
|
|
24
|
+
resolveExclusiveHooks as resolveExclusiveHooksShared,
|
|
25
|
+
} from "./hooks.js";
|
|
26
|
+
import { PluginRouteRegistry, type RouteResult, type InvokeRouteOptions } from "./routes.js";
|
|
27
|
+
import type {
|
|
28
|
+
PluginDefinition,
|
|
29
|
+
ResolvedPlugin,
|
|
30
|
+
PluginStorageConfig,
|
|
31
|
+
MediaItem,
|
|
32
|
+
CronEvent,
|
|
33
|
+
} from "./types.js";
|
|
34
|
+
|
|
35
|
+
/** Options table key prefix for exclusive hook DB reads via PluginManager */
|
|
36
|
+
const EXCLUSIVE_HOOK_KEY_PREFIX = "emdash:exclusive_hook:";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Plugin state in the manager
|
|
40
|
+
*/
|
|
41
|
+
export type PluginState = "registered" | "installed" | "active" | "inactive";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Plugin entry in the manager
|
|
45
|
+
*/
|
|
46
|
+
interface PluginEntry {
|
|
47
|
+
plugin: ResolvedPlugin;
|
|
48
|
+
state: PluginState;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Plugin manager options
|
|
53
|
+
*/
|
|
54
|
+
export interface PluginManagerOptions {
|
|
55
|
+
/** Database instance */
|
|
56
|
+
db: Kysely<Database>;
|
|
57
|
+
/** Storage backend for direct media uploads */
|
|
58
|
+
storage?: Storage;
|
|
59
|
+
/** Function to generate upload URLs for media */
|
|
60
|
+
getUploadUrl?: (
|
|
61
|
+
filename: string,
|
|
62
|
+
contentType: string,
|
|
63
|
+
) => Promise<{ uploadUrl: string; mediaId: string }>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Plugin Manager v2
|
|
68
|
+
*
|
|
69
|
+
* Manages the full lifecycle of plugins and coordinates hooks/routes.
|
|
70
|
+
*/
|
|
71
|
+
export class PluginManager {
|
|
72
|
+
private plugins: Map<string, PluginEntry> = new Map();
|
|
73
|
+
private hookPipeline: HookPipeline | null = null;
|
|
74
|
+
private routeRegistry: PluginRouteRegistry | null = null;
|
|
75
|
+
private factoryOptions: PluginContextFactoryOptions;
|
|
76
|
+
private initialized = false;
|
|
77
|
+
|
|
78
|
+
constructor(private options: PluginManagerOptions) {
|
|
79
|
+
this.factoryOptions = {
|
|
80
|
+
db: options.db,
|
|
81
|
+
storage: options.storage,
|
|
82
|
+
getUploadUrl: options.getUploadUrl,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// =========================================================================
|
|
87
|
+
// Plugin Registration
|
|
88
|
+
// =========================================================================
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Register a plugin definition
|
|
92
|
+
* This resolves the definition and adds it to the manager, but doesn't install it
|
|
93
|
+
*/
|
|
94
|
+
register<TStorage extends PluginStorageConfig>(
|
|
95
|
+
definition: PluginDefinition<TStorage>,
|
|
96
|
+
): ResolvedPlugin<TStorage> {
|
|
97
|
+
const resolved = definePlugin(definition);
|
|
98
|
+
|
|
99
|
+
if (this.plugins.has(resolved.id)) {
|
|
100
|
+
throw new Error(`Plugin "${resolved.id}" is already registered`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.plugins.set(resolved.id, {
|
|
104
|
+
plugin: resolved,
|
|
105
|
+
state: "registered",
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Mark as needing reinitialization
|
|
109
|
+
this.initialized = false;
|
|
110
|
+
|
|
111
|
+
return resolved;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Register multiple plugins
|
|
116
|
+
*/
|
|
117
|
+
registerAll(definitions: PluginDefinition[]): void {
|
|
118
|
+
for (const def of definitions) {
|
|
119
|
+
this.register(def);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Unregister a plugin
|
|
125
|
+
* Plugin must be inactive or just registered
|
|
126
|
+
*/
|
|
127
|
+
unregister(pluginId: string): boolean {
|
|
128
|
+
const entry = this.plugins.get(pluginId);
|
|
129
|
+
if (!entry) return false;
|
|
130
|
+
|
|
131
|
+
if (entry.state === "active") {
|
|
132
|
+
throw new Error(`Cannot unregister active plugin "${pluginId}". Deactivate it first.`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.plugins.delete(pluginId);
|
|
136
|
+
this.initialized = false;
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// =========================================================================
|
|
141
|
+
// Plugin Lifecycle
|
|
142
|
+
// =========================================================================
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Install a plugin (run install hooks, set up storage)
|
|
146
|
+
*/
|
|
147
|
+
async install(pluginId: string): Promise<HookResult<void>[]> {
|
|
148
|
+
const entry = this.plugins.get(pluginId);
|
|
149
|
+
if (!entry) {
|
|
150
|
+
throw new Error(`Plugin "${pluginId}" not found`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (entry.state !== "registered") {
|
|
154
|
+
throw new Error(`Plugin "${pluginId}" is already installed (state: ${entry.state})`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.ensureInitialized();
|
|
158
|
+
|
|
159
|
+
// Run install hooks
|
|
160
|
+
const results = await this.hookPipeline!.runPluginInstall(pluginId);
|
|
161
|
+
|
|
162
|
+
// Check for errors
|
|
163
|
+
const failed = results.find((r) => !r.success);
|
|
164
|
+
if (failed) {
|
|
165
|
+
throw new Error(`Plugin install failed: ${failed.error?.message ?? "Unknown error"}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
entry.state = "installed";
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Activate a plugin (run activate hooks, enable hooks/routes)
|
|
174
|
+
*/
|
|
175
|
+
async activate(pluginId: string): Promise<HookResult<void>[]> {
|
|
176
|
+
const entry = this.plugins.get(pluginId);
|
|
177
|
+
if (!entry) {
|
|
178
|
+
throw new Error(`Plugin "${pluginId}" not found`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (entry.state === "active") {
|
|
182
|
+
return []; // Already active
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (entry.state === "registered") {
|
|
186
|
+
// Auto-install if not installed
|
|
187
|
+
await this.install(pluginId);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.ensureInitialized();
|
|
191
|
+
|
|
192
|
+
// Run activate hooks
|
|
193
|
+
const results = await this.hookPipeline!.runPluginActivate(pluginId);
|
|
194
|
+
|
|
195
|
+
// Check for errors
|
|
196
|
+
const failed = results.find((r) => !r.success);
|
|
197
|
+
if (failed) {
|
|
198
|
+
throw new Error(`Plugin activation failed: ${failed.error?.message ?? "Unknown error"}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
entry.state = "active";
|
|
202
|
+
|
|
203
|
+
// Re-enable cron tasks for the activated plugin
|
|
204
|
+
await setCronTasksEnabled(this.options.db, pluginId, true);
|
|
205
|
+
|
|
206
|
+
// Reinitialize pipeline so the newly active plugin's hooks are registered
|
|
207
|
+
this.reinitialize();
|
|
208
|
+
|
|
209
|
+
// Resolve exclusive hooks (new provider may need auto-selection)
|
|
210
|
+
await this.resolveExclusiveHooks();
|
|
211
|
+
|
|
212
|
+
return results;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Deactivate a plugin (run deactivate hooks, disable hooks/routes)
|
|
217
|
+
*/
|
|
218
|
+
async deactivate(pluginId: string): Promise<HookResult<void>[]> {
|
|
219
|
+
const entry = this.plugins.get(pluginId);
|
|
220
|
+
if (!entry) {
|
|
221
|
+
throw new Error(`Plugin "${pluginId}" not found`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (entry.state !== "active") {
|
|
225
|
+
return []; // Not active
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this.ensureInitialized();
|
|
229
|
+
|
|
230
|
+
// Run deactivate hooks
|
|
231
|
+
const results = await this.hookPipeline!.runPluginDeactivate(pluginId);
|
|
232
|
+
|
|
233
|
+
// Disable cron tasks for the deactivated plugin
|
|
234
|
+
await setCronTasksEnabled(this.options.db, pluginId, false);
|
|
235
|
+
|
|
236
|
+
entry.state = "inactive";
|
|
237
|
+
|
|
238
|
+
// Reinitialize pipeline so the deactivated plugin's hooks are removed
|
|
239
|
+
this.reinitialize();
|
|
240
|
+
|
|
241
|
+
// Resolve exclusive hooks (deactivated provider may need clearing)
|
|
242
|
+
await this.resolveExclusiveHooks();
|
|
243
|
+
|
|
244
|
+
return results;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Uninstall a plugin (run uninstall hooks, optionally delete data)
|
|
249
|
+
*/
|
|
250
|
+
async uninstall(pluginId: string, deleteData: boolean = false): Promise<HookResult<void>[]> {
|
|
251
|
+
const entry = this.plugins.get(pluginId);
|
|
252
|
+
if (!entry) {
|
|
253
|
+
throw new Error(`Plugin "${pluginId}" not found`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Deactivate first if active (this also resolves exclusive hooks)
|
|
257
|
+
if (entry.state === "active") {
|
|
258
|
+
await this.deactivate(pluginId);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
this.ensureInitialized();
|
|
262
|
+
|
|
263
|
+
// Run uninstall hooks
|
|
264
|
+
const results = await this.hookPipeline!.runPluginUninstall(pluginId, deleteData);
|
|
265
|
+
|
|
266
|
+
// Delete all cron tasks for the uninstalled plugin
|
|
267
|
+
await this.deleteCronTasks(pluginId);
|
|
268
|
+
|
|
269
|
+
// Remove from manager
|
|
270
|
+
this.plugins.delete(pluginId);
|
|
271
|
+
this.initialized = false;
|
|
272
|
+
|
|
273
|
+
// Resolve exclusive hooks after removal
|
|
274
|
+
await this.resolveExclusiveHooks();
|
|
275
|
+
|
|
276
|
+
return results;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// =========================================================================
|
|
280
|
+
// Hook Dispatch
|
|
281
|
+
// =========================================================================
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Run content:beforeSave hooks across all active plugins
|
|
285
|
+
*/
|
|
286
|
+
async runContentBeforeSave(
|
|
287
|
+
content: Record<string, unknown>,
|
|
288
|
+
collection: string,
|
|
289
|
+
isNew: boolean,
|
|
290
|
+
): Promise<{
|
|
291
|
+
content: Record<string, unknown>;
|
|
292
|
+
results: HookResult<Record<string, unknown>>[];
|
|
293
|
+
}> {
|
|
294
|
+
this.ensureInitialized();
|
|
295
|
+
return this.hookPipeline!.runContentBeforeSave(content, collection, isNew);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Run content:afterSave hooks across all active plugins
|
|
300
|
+
*/
|
|
301
|
+
async runContentAfterSave(
|
|
302
|
+
content: Record<string, unknown>,
|
|
303
|
+
collection: string,
|
|
304
|
+
isNew: boolean,
|
|
305
|
+
): Promise<HookResult<void>[]> {
|
|
306
|
+
this.ensureInitialized();
|
|
307
|
+
return this.hookPipeline!.runContentAfterSave(content, collection, isNew);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Run content:beforeDelete hooks across all active plugins
|
|
312
|
+
*/
|
|
313
|
+
async runContentBeforeDelete(
|
|
314
|
+
id: string,
|
|
315
|
+
collection: string,
|
|
316
|
+
): Promise<{ allowed: boolean; results: HookResult<boolean>[] }> {
|
|
317
|
+
this.ensureInitialized();
|
|
318
|
+
return this.hookPipeline!.runContentBeforeDelete(id, collection);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Run content:afterDelete hooks across all active plugins
|
|
323
|
+
*/
|
|
324
|
+
async runContentAfterDelete(id: string, collection: string): Promise<HookResult<void>[]> {
|
|
325
|
+
this.ensureInitialized();
|
|
326
|
+
return this.hookPipeline!.runContentAfterDelete(id, collection);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Run media:beforeUpload hooks across all active plugins
|
|
331
|
+
*/
|
|
332
|
+
async runMediaBeforeUpload(file: { name: string; type: string; size: number }): Promise<{
|
|
333
|
+
file: { name: string; type: string; size: number };
|
|
334
|
+
results: HookResult<{ name: string; type: string; size: number }>[];
|
|
335
|
+
}> {
|
|
336
|
+
this.ensureInitialized();
|
|
337
|
+
return this.hookPipeline!.runMediaBeforeUpload(file);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Run media:afterUpload hooks across all active plugins
|
|
342
|
+
*/
|
|
343
|
+
async runMediaAfterUpload(media: MediaItem): Promise<HookResult<void>[]> {
|
|
344
|
+
this.ensureInitialized();
|
|
345
|
+
return this.hookPipeline!.runMediaAfterUpload(media);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Invoke the cron hook for a specific plugin (per-plugin dispatch).
|
|
350
|
+
* Used as the InvokeCronHookFn callback for CronExecutor.
|
|
351
|
+
*/
|
|
352
|
+
async invokeCronHook(pluginId: string, event: CronEvent): Promise<void> {
|
|
353
|
+
this.ensureInitialized();
|
|
354
|
+
const result = await this.hookPipeline!.invokeCronHook(pluginId, event);
|
|
355
|
+
if (!result.success && result.error) {
|
|
356
|
+
throw result.error;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// =========================================================================
|
|
361
|
+
// Route Dispatch
|
|
362
|
+
// =========================================================================
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Invoke a plugin route
|
|
366
|
+
*/
|
|
367
|
+
async invokeRoute(
|
|
368
|
+
pluginId: string,
|
|
369
|
+
routeName: string,
|
|
370
|
+
options: InvokeRouteOptions,
|
|
371
|
+
): Promise<RouteResult> {
|
|
372
|
+
this.ensureInitialized();
|
|
373
|
+
return this.routeRegistry!.invoke(pluginId, routeName, options);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Get all routes for a plugin
|
|
378
|
+
*/
|
|
379
|
+
getPluginRoutes(pluginId: string): string[] {
|
|
380
|
+
this.ensureInitialized();
|
|
381
|
+
return this.routeRegistry!.getRoutes(pluginId);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// =========================================================================
|
|
385
|
+
// Query Methods
|
|
386
|
+
// =========================================================================
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Get a plugin by ID
|
|
390
|
+
*/
|
|
391
|
+
getPlugin(pluginId: string): ResolvedPlugin | undefined {
|
|
392
|
+
return this.plugins.get(pluginId)?.plugin;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get plugin state
|
|
397
|
+
*/
|
|
398
|
+
getPluginState(pluginId: string): PluginState | undefined {
|
|
399
|
+
return this.plugins.get(pluginId)?.state;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Get all registered plugins
|
|
404
|
+
*/
|
|
405
|
+
getAllPlugins(): Array<{ plugin: ResolvedPlugin; state: PluginState }> {
|
|
406
|
+
return Array.from(this.plugins.values(), (entry) => ({
|
|
407
|
+
plugin: entry.plugin,
|
|
408
|
+
state: entry.state,
|
|
409
|
+
}));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Get all active plugins
|
|
414
|
+
*/
|
|
415
|
+
getActivePlugins(): ResolvedPlugin[] {
|
|
416
|
+
return [...this.plugins.values()]
|
|
417
|
+
.filter((entry) => entry.state === "active")
|
|
418
|
+
.map((entry) => entry.plugin);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Check if a plugin exists
|
|
423
|
+
*/
|
|
424
|
+
hasPlugin(pluginId: string): boolean {
|
|
425
|
+
return this.plugins.has(pluginId);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Check if a plugin is active
|
|
430
|
+
*/
|
|
431
|
+
isActive(pluginId: string): boolean {
|
|
432
|
+
return this.plugins.get(pluginId)?.state === "active";
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// =========================================================================
|
|
436
|
+
// Exclusive Hooks
|
|
437
|
+
// =========================================================================
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Get all plugins that registered a handler for an exclusive hook.
|
|
441
|
+
*/
|
|
442
|
+
getExclusiveHookProviders(hookName: string): Array<{ pluginId: string; pluginName: string }> {
|
|
443
|
+
this.ensureInitialized();
|
|
444
|
+
return this.hookPipeline!.getExclusiveHookProviders(hookName).map((p) => {
|
|
445
|
+
const plugin = this.plugins.get(p.pluginId);
|
|
446
|
+
return {
|
|
447
|
+
pluginId: p.pluginId,
|
|
448
|
+
pluginName: plugin?.plugin.id ?? p.pluginId,
|
|
449
|
+
};
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Read the selected provider for an exclusive hook from the options table.
|
|
455
|
+
*/
|
|
456
|
+
async getExclusiveHookSelection(hookName: string): Promise<string | null> {
|
|
457
|
+
const optionsRepo = new OptionsRepository(this.options.db);
|
|
458
|
+
return optionsRepo.get<string>(`${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Set the selected provider for an exclusive hook in the options table.
|
|
463
|
+
* Pass null to clear the selection.
|
|
464
|
+
*/
|
|
465
|
+
async setExclusiveHookSelection(hookName: string, pluginId: string | null): Promise<void> {
|
|
466
|
+
const optionsRepo = new OptionsRepository(this.options.db);
|
|
467
|
+
const key = `${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`;
|
|
468
|
+
|
|
469
|
+
if (pluginId === null) {
|
|
470
|
+
await optionsRepo.delete(key);
|
|
471
|
+
this.hookPipeline?.clearExclusiveSelection(hookName);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Validate plugin exists and is active
|
|
476
|
+
const entry = this.plugins.get(pluginId);
|
|
477
|
+
if (!entry) {
|
|
478
|
+
throw new Error(`Plugin "${pluginId}" not found`);
|
|
479
|
+
}
|
|
480
|
+
if (entry.state !== "active") {
|
|
481
|
+
throw new Error(`Plugin "${pluginId}" is not active`);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
await optionsRepo.set(key, pluginId);
|
|
485
|
+
this.hookPipeline?.setExclusiveSelection(hookName, pluginId);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Resolution algorithm for exclusive hooks.
|
|
490
|
+
*
|
|
491
|
+
* Delegates to the shared resolveExclusiveHooks() function.
|
|
492
|
+
* See hooks.ts for the full algorithm description.
|
|
493
|
+
*/
|
|
494
|
+
async resolveExclusiveHooks(preferredHints?: Map<string, string[]>): Promise<void> {
|
|
495
|
+
this.ensureInitialized();
|
|
496
|
+
|
|
497
|
+
const optionsRepo = new OptionsRepository(this.options.db);
|
|
498
|
+
|
|
499
|
+
await resolveExclusiveHooksShared({
|
|
500
|
+
pipeline: this.hookPipeline!,
|
|
501
|
+
isActive: (pluginId) => this.isActive(pluginId),
|
|
502
|
+
getOption: (key) => optionsRepo.get<string>(key),
|
|
503
|
+
setOption: (key, value) => optionsRepo.set(key, value),
|
|
504
|
+
deleteOption: async (key) => {
|
|
505
|
+
await optionsRepo.delete(key);
|
|
506
|
+
},
|
|
507
|
+
preferredHints,
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Get all exclusive hooks with their providers and current selections.
|
|
513
|
+
* Used by the admin API.
|
|
514
|
+
*/
|
|
515
|
+
async getExclusiveHooksInfo(): Promise<
|
|
516
|
+
Array<{
|
|
517
|
+
hookName: string;
|
|
518
|
+
providers: Array<{ pluginId: string }>;
|
|
519
|
+
selectedPluginId: string | null;
|
|
520
|
+
}>
|
|
521
|
+
> {
|
|
522
|
+
this.ensureInitialized();
|
|
523
|
+
const exclusiveHookNames = this.hookPipeline!.getRegisteredExclusiveHooks();
|
|
524
|
+
const result = [];
|
|
525
|
+
|
|
526
|
+
for (const hookName of exclusiveHookNames) {
|
|
527
|
+
const providers = this.hookPipeline!.getExclusiveHookProviders(hookName);
|
|
528
|
+
const selection = await this.getExclusiveHookSelection(hookName);
|
|
529
|
+
result.push({
|
|
530
|
+
hookName,
|
|
531
|
+
providers,
|
|
532
|
+
selectedPluginId: selection,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return result;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// =========================================================================
|
|
540
|
+
// Internal Methods
|
|
541
|
+
// =========================================================================
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Initialize or reinitialize the hook pipeline and route registry
|
|
545
|
+
*/
|
|
546
|
+
private ensureInitialized(): void {
|
|
547
|
+
if (this.initialized) return;
|
|
548
|
+
|
|
549
|
+
// Get all active plugins for hooks
|
|
550
|
+
const activePlugins = this.getActivePlugins();
|
|
551
|
+
|
|
552
|
+
// Create hook pipeline with active plugins
|
|
553
|
+
this.hookPipeline = new HookPipeline(activePlugins, this.factoryOptions);
|
|
554
|
+
|
|
555
|
+
// Create route registry
|
|
556
|
+
this.routeRegistry = new PluginRouteRegistry(this.factoryOptions);
|
|
557
|
+
|
|
558
|
+
// Register routes for active plugins
|
|
559
|
+
for (const plugin of activePlugins) {
|
|
560
|
+
this.routeRegistry.register(plugin);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
this.initialized = true;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Force reinitialization (useful after plugin state changes)
|
|
568
|
+
*/
|
|
569
|
+
reinitialize(): void {
|
|
570
|
+
this.initialized = false;
|
|
571
|
+
this.ensureInitialized();
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Delete all cron tasks for a plugin.
|
|
576
|
+
* Used during uninstall.
|
|
577
|
+
*/
|
|
578
|
+
private async deleteCronTasks(pluginId: string): Promise<void> {
|
|
579
|
+
try {
|
|
580
|
+
await sql`
|
|
581
|
+
DELETE FROM _emdash_cron_tasks
|
|
582
|
+
WHERE plugin_id = ${pluginId}
|
|
583
|
+
`.execute(this.options.db);
|
|
584
|
+
} catch {
|
|
585
|
+
// Cron table may not exist yet (pre-migration). Non-fatal.
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Create a plugin manager
|
|
592
|
+
*/
|
|
593
|
+
export function createPluginManager(options: PluginManagerOptions): PluginManager {
|
|
594
|
+
return new PluginManager(options);
|
|
595
|
+
}
|