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,547 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login/logout/whoami CLI commands
|
|
3
|
+
*
|
|
4
|
+
* Login uses the OAuth Device Flow (RFC 8628):
|
|
5
|
+
* 1. POST /oauth/device/code → get device_code + user_code
|
|
6
|
+
* 2. Display URL + code to user
|
|
7
|
+
* 3. Poll POST /oauth/device/token until authorized
|
|
8
|
+
* 4. Save tokens to ~/.config/emdash/auth.json
|
|
9
|
+
*
|
|
10
|
+
* Custom headers (--header / EMDASH_HEADERS) are sent with every request
|
|
11
|
+
* and persisted to credentials so subsequent commands inherit them.
|
|
12
|
+
* This supports sites behind reverse proxies like Cloudflare Access.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { defineCommand } from "citty";
|
|
16
|
+
import { consola } from "consola";
|
|
17
|
+
import pc from "picocolors";
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
createHeaderAwareFetch,
|
|
21
|
+
getCachedAccessToken,
|
|
22
|
+
isAccessRedirect,
|
|
23
|
+
resolveCustomHeaders,
|
|
24
|
+
runCloudflaredLogin,
|
|
25
|
+
} from "../../client/cf-access.js";
|
|
26
|
+
import {
|
|
27
|
+
getCredentials,
|
|
28
|
+
removeCredentials,
|
|
29
|
+
resolveCredentialKey,
|
|
30
|
+
saveCredentials,
|
|
31
|
+
} from "../credentials.js";
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Types for discovery + device flow responses
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
interface DiscoveryResponse {
|
|
38
|
+
instance?: { name?: string };
|
|
39
|
+
auth?: {
|
|
40
|
+
mode?: string;
|
|
41
|
+
methods?: {
|
|
42
|
+
device_flow?: {
|
|
43
|
+
device_authorization_endpoint: string;
|
|
44
|
+
token_endpoint: string;
|
|
45
|
+
};
|
|
46
|
+
api_tokens?: boolean;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface DeviceCodeResponse {
|
|
52
|
+
device_code: string;
|
|
53
|
+
user_code: string;
|
|
54
|
+
verification_uri: string;
|
|
55
|
+
expires_in: number;
|
|
56
|
+
interval: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface TokenResponse {
|
|
60
|
+
access_token: string;
|
|
61
|
+
refresh_token: string;
|
|
62
|
+
token_type: string;
|
|
63
|
+
expires_in: number;
|
|
64
|
+
scope: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Device Flow polling
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
async function pollForToken(
|
|
72
|
+
tokenEndpoint: string,
|
|
73
|
+
deviceCode: string,
|
|
74
|
+
interval: number,
|
|
75
|
+
expiresIn: number,
|
|
76
|
+
fetchFn: typeof fetch,
|
|
77
|
+
): Promise<TokenResponse> {
|
|
78
|
+
const deadline = Date.now() + expiresIn * 1000;
|
|
79
|
+
let currentInterval = interval;
|
|
80
|
+
|
|
81
|
+
while (Date.now() < deadline) {
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, currentInterval * 1000));
|
|
83
|
+
|
|
84
|
+
const res = await fetchFn(tokenEndpoint, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: { "Content-Type": "application/json" },
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
device_code: deviceCode,
|
|
89
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
90
|
+
}),
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (res.ok) {
|
|
94
|
+
return (await res.json()) as TokenResponse;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const body = (await res.json()) as { error?: string; interval?: number };
|
|
98
|
+
|
|
99
|
+
if (body.error === "authorization_pending") {
|
|
100
|
+
// Keep polling
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (body.error === "slow_down") {
|
|
105
|
+
// Use server-provided interval, or fall back to incrementing by 5s
|
|
106
|
+
currentInterval = body.interval ?? currentInterval + 5;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (body.error === "expired_token") {
|
|
111
|
+
throw new Error("Device code expired. Please try again.");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (body.error === "access_denied") {
|
|
115
|
+
throw new Error("Authorization was denied.");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Unknown error
|
|
119
|
+
throw new Error(`Token exchange failed: ${body.error || res.statusText}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw new Error("Device code expired (timeout). Please try again.");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Cloudflare Access handling
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Handle a Cloudflare Access redirect during login.
|
|
131
|
+
*
|
|
132
|
+
* 1. Try `cloudflared access token` for a cached JWT
|
|
133
|
+
* 2. Try `cloudflared access login` to do the browser flow
|
|
134
|
+
* 3. If cloudflared isn't available, print instructions for service tokens
|
|
135
|
+
*
|
|
136
|
+
* Returns the Access JWT, or null if auth couldn't be resolved.
|
|
137
|
+
*/
|
|
138
|
+
async function handleAccessRedirect(baseUrl: string): Promise<string | null> {
|
|
139
|
+
consola.info("This site is behind Cloudflare Access.");
|
|
140
|
+
|
|
141
|
+
// Try cached token first
|
|
142
|
+
const cached = await getCachedAccessToken(baseUrl);
|
|
143
|
+
if (cached) {
|
|
144
|
+
consola.success("Using cached Cloudflare Access token from cloudflared.");
|
|
145
|
+
return cached;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Try interactive login via cloudflared
|
|
149
|
+
consola.info("Launching browser for Cloudflare Access login...");
|
|
150
|
+
const loginOk = await runCloudflaredLogin(baseUrl);
|
|
151
|
+
|
|
152
|
+
if (loginOk) {
|
|
153
|
+
const token = await getCachedAccessToken(baseUrl);
|
|
154
|
+
if (token) {
|
|
155
|
+
consola.success("Cloudflare Access authentication successful.");
|
|
156
|
+
return token;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// cloudflared not available or login failed — guide the user
|
|
161
|
+
console.log();
|
|
162
|
+
consola.info("Could not authenticate with Cloudflare Access automatically.");
|
|
163
|
+
consola.info("You have two options:");
|
|
164
|
+
console.log();
|
|
165
|
+
consola.info(` ${pc.bold("Option 1:")} Install cloudflared and run:`);
|
|
166
|
+
console.log(` ${pc.cyan(`cloudflared access login ${baseUrl}`)}`);
|
|
167
|
+
console.log(` ${pc.cyan(`emdash login --url ${baseUrl}`)}`);
|
|
168
|
+
console.log();
|
|
169
|
+
consola.info(` ${pc.bold("Option 2:")} Use a service token:`);
|
|
170
|
+
console.log(
|
|
171
|
+
` ${pc.cyan(`emdash login --url ${baseUrl} -H "CF-Access-Client-Id: <id>" -H "CF-Access-Client-Secret: <secret>"`)}`,
|
|
172
|
+
);
|
|
173
|
+
console.log();
|
|
174
|
+
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// Commands
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
export const loginCommand = defineCommand({
|
|
183
|
+
meta: { name: "login", description: "Log in to an EmDash instance" },
|
|
184
|
+
args: {
|
|
185
|
+
url: {
|
|
186
|
+
type: "string",
|
|
187
|
+
alias: "u",
|
|
188
|
+
description: "EmDash instance URL",
|
|
189
|
+
default: "http://localhost:4321",
|
|
190
|
+
},
|
|
191
|
+
header: {
|
|
192
|
+
type: "string",
|
|
193
|
+
alias: "H",
|
|
194
|
+
description: 'Custom header "Name: Value" (repeatable, or use EMDASH_HEADERS env)',
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
async run({ args }) {
|
|
198
|
+
const baseUrl = args.url || "http://localhost:4321";
|
|
199
|
+
consola.start(`Connecting to ${baseUrl}...`);
|
|
200
|
+
|
|
201
|
+
// Resolve custom headers from --header flags and EMDASH_HEADERS env
|
|
202
|
+
const customHeaders = resolveCustomHeaders();
|
|
203
|
+
let headerFetch = createHeaderAwareFetch(customHeaders);
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
// Step 1: Fetch auth discovery.
|
|
207
|
+
// Use redirect: "manual" to detect Cloudflare Access.
|
|
208
|
+
const discoveryUrl = new URL("/_emdash/.well-known/auth", baseUrl);
|
|
209
|
+
let res = await headerFetch(discoveryUrl, { redirect: "manual" });
|
|
210
|
+
|
|
211
|
+
// Handle Cloudflare Access
|
|
212
|
+
if (isAccessRedirect(res)) {
|
|
213
|
+
const accessToken = await handleAccessRedirect(baseUrl);
|
|
214
|
+
if (!accessToken) {
|
|
215
|
+
return; // handleAccessRedirect printed instructions
|
|
216
|
+
}
|
|
217
|
+
// Add the Access token to our custom headers and rebuild the fetch wrapper
|
|
218
|
+
customHeaders["cf-access-token"] = accessToken;
|
|
219
|
+
headerFetch = createHeaderAwareFetch(customHeaders);
|
|
220
|
+
res = await headerFetch(discoveryUrl);
|
|
221
|
+
} else if (res.status === 301 || res.status === 302) {
|
|
222
|
+
// Non-Access redirect — follow it normally
|
|
223
|
+
res = await headerFetch(discoveryUrl);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (!res.ok) {
|
|
227
|
+
if (res.status === 404) {
|
|
228
|
+
const isLocal = baseUrl.includes("localhost") || baseUrl.includes("127.0.0.1");
|
|
229
|
+
if (isLocal) {
|
|
230
|
+
consola.info("Auth discovery not available. Trying dev bypass...");
|
|
231
|
+
const bypassRes = await fetch(new URL("/_emdash/api/auth/dev-bypass", baseUrl), {
|
|
232
|
+
redirect: "manual",
|
|
233
|
+
});
|
|
234
|
+
if (bypassRes.status === 302 || bypassRes.ok) {
|
|
235
|
+
consola.success("Dev bypass available. Client will authenticate automatically.");
|
|
236
|
+
} else {
|
|
237
|
+
consola.error("Could not authenticate. Is the dev server running?");
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
consola.error("Auth discovery endpoint not found. Is this an EmDash instance?");
|
|
241
|
+
}
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
consola.error(`Discovery failed: ${res.status} ${res.statusText}`);
|
|
245
|
+
process.exit(2);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const discovery = (await res.json()) as DiscoveryResponse;
|
|
249
|
+
consola.success(`Connected to ${discovery.instance?.name || "EmDash"}`);
|
|
250
|
+
|
|
251
|
+
const deviceFlow = discovery.auth?.methods?.device_flow;
|
|
252
|
+
|
|
253
|
+
if (!deviceFlow) {
|
|
254
|
+
// No device flow available (external auth mode)
|
|
255
|
+
consola.info("Device Flow is not available for this instance.");
|
|
256
|
+
consola.info("Generate an API token in Settings > API Tokens");
|
|
257
|
+
consola.info(`Then run: ${pc.cyan(`emdash --token <token> --url ${baseUrl}`)}`);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Step 2: Request device code
|
|
262
|
+
const codeUrl = new URL(deviceFlow.device_authorization_endpoint, baseUrl);
|
|
263
|
+
const codeRes = await headerFetch(codeUrl, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: {
|
|
266
|
+
"Content-Type": "application/json",
|
|
267
|
+
"X-EmDash-Request": "1",
|
|
268
|
+
},
|
|
269
|
+
body: JSON.stringify({
|
|
270
|
+
client_id: "emdash-cli",
|
|
271
|
+
}),
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (!codeRes.ok) {
|
|
275
|
+
consola.error(`Failed to request device code: ${codeRes.status}`);
|
|
276
|
+
process.exit(2);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const deviceCode = (await codeRes.json()) as DeviceCodeResponse;
|
|
280
|
+
|
|
281
|
+
// Step 3: Display instructions
|
|
282
|
+
console.log();
|
|
283
|
+
consola.info(`Open your browser to:`);
|
|
284
|
+
console.log(` ${pc.cyan(pc.bold(deviceCode.verification_uri))}`);
|
|
285
|
+
console.log();
|
|
286
|
+
consola.info(`Enter code: ${pc.yellow(pc.bold(deviceCode.user_code))}`);
|
|
287
|
+
console.log();
|
|
288
|
+
|
|
289
|
+
// Try to open browser (best-effort)
|
|
290
|
+
try {
|
|
291
|
+
const { execFile } = await import("node:child_process");
|
|
292
|
+
if (process.platform === "darwin") {
|
|
293
|
+
execFile("open", [deviceCode.verification_uri]);
|
|
294
|
+
} else if (process.platform === "win32") {
|
|
295
|
+
execFile("cmd", ["/c", "start", "", deviceCode.verification_uri]);
|
|
296
|
+
} else {
|
|
297
|
+
execFile("xdg-open", [deviceCode.verification_uri]);
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
// Ignore — user can open manually
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Step 4: Poll for token
|
|
304
|
+
consola.start("Waiting for authorization...");
|
|
305
|
+
|
|
306
|
+
const tokenUrl = new URL(deviceFlow.token_endpoint, baseUrl);
|
|
307
|
+
const tokenResult = await pollForToken(
|
|
308
|
+
tokenUrl.toString(),
|
|
309
|
+
deviceCode.device_code,
|
|
310
|
+
deviceCode.interval,
|
|
311
|
+
deviceCode.expires_in,
|
|
312
|
+
headerFetch,
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
// Step 5: Fetch user info
|
|
316
|
+
let userEmail = "unknown";
|
|
317
|
+
let userRole = "unknown";
|
|
318
|
+
try {
|
|
319
|
+
const meRes = await headerFetch(new URL("/_emdash/api/auth/me", baseUrl), {
|
|
320
|
+
headers: { Authorization: `Bearer ${tokenResult.access_token}` },
|
|
321
|
+
});
|
|
322
|
+
if (meRes.ok) {
|
|
323
|
+
const meJson = (await meRes.json()) as {
|
|
324
|
+
data: { email?: string; role?: number };
|
|
325
|
+
};
|
|
326
|
+
const me = meJson.data;
|
|
327
|
+
userEmail = me.email || "unknown";
|
|
328
|
+
// Map role number to name
|
|
329
|
+
const roleNames: Record<number, string> = {
|
|
330
|
+
10: "subscriber",
|
|
331
|
+
20: "contributor",
|
|
332
|
+
30: "author",
|
|
333
|
+
40: "editor",
|
|
334
|
+
50: "admin",
|
|
335
|
+
};
|
|
336
|
+
userRole = (me.role ? roleNames[me.role] : undefined) || "unknown";
|
|
337
|
+
}
|
|
338
|
+
} catch {
|
|
339
|
+
// Non-critical
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Step 6: Save credentials (persist custom headers so subsequent commands inherit them)
|
|
343
|
+
const expiresAt = new Date(Date.now() + tokenResult.expires_in * 1000).toISOString();
|
|
344
|
+
const hasCustomHeaders = Object.keys(customHeaders).length > 0;
|
|
345
|
+
saveCredentials(baseUrl, {
|
|
346
|
+
accessToken: tokenResult.access_token,
|
|
347
|
+
refreshToken: tokenResult.refresh_token,
|
|
348
|
+
expiresAt,
|
|
349
|
+
...(hasCustomHeaders ? { customHeaders } : {}),
|
|
350
|
+
user: { email: userEmail, role: userRole },
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
consola.success(`Logged in as ${pc.bold(userEmail)} (${userRole})`);
|
|
354
|
+
consola.info(`Token saved to ${pc.dim(resolveCredentialKey(baseUrl))}`);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
consola.error(error instanceof Error ? error.message : "Login failed");
|
|
357
|
+
process.exit(2);
|
|
358
|
+
}
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
export const logoutCommand = defineCommand({
|
|
363
|
+
meta: { name: "logout", description: "Log out of an EmDash instance" },
|
|
364
|
+
args: {
|
|
365
|
+
url: {
|
|
366
|
+
type: "string",
|
|
367
|
+
alias: "u",
|
|
368
|
+
description: "EmDash instance URL",
|
|
369
|
+
default: "http://localhost:4321",
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
async run({ args }) {
|
|
373
|
+
const baseUrl = args.url || "http://localhost:4321";
|
|
374
|
+
|
|
375
|
+
// Get stored credentials
|
|
376
|
+
const cred = getCredentials(baseUrl);
|
|
377
|
+
|
|
378
|
+
if (!cred) {
|
|
379
|
+
consola.info("No stored credentials found for this instance.");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const headerFetch = createHeaderAwareFetch(cred.customHeaders ?? {});
|
|
384
|
+
|
|
385
|
+
// Revoke tokens server-side (best-effort)
|
|
386
|
+
try {
|
|
387
|
+
// Revoke the refresh token (which also revokes associated access tokens)
|
|
388
|
+
await headerFetch(new URL("/_emdash/api/oauth/token/revoke", baseUrl), {
|
|
389
|
+
method: "POST",
|
|
390
|
+
headers: { "Content-Type": "application/json" },
|
|
391
|
+
body: JSON.stringify({ token: cred.refreshToken }),
|
|
392
|
+
});
|
|
393
|
+
} catch {
|
|
394
|
+
// Non-critical — the local removal still works
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Remove local credentials
|
|
398
|
+
removeCredentials(baseUrl);
|
|
399
|
+
consola.success("Logged out successfully.");
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
export const whoamiCommand = defineCommand({
|
|
404
|
+
meta: {
|
|
405
|
+
name: "whoami",
|
|
406
|
+
description: "Show current user and auth method",
|
|
407
|
+
},
|
|
408
|
+
args: {
|
|
409
|
+
url: {
|
|
410
|
+
type: "string",
|
|
411
|
+
alias: "u",
|
|
412
|
+
description: "EmDash instance URL",
|
|
413
|
+
default: "http://localhost:4321",
|
|
414
|
+
},
|
|
415
|
+
token: {
|
|
416
|
+
type: "string",
|
|
417
|
+
alias: "t",
|
|
418
|
+
description: "Auth token",
|
|
419
|
+
},
|
|
420
|
+
json: {
|
|
421
|
+
type: "boolean",
|
|
422
|
+
description: "Output as JSON",
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
async run({ args }) {
|
|
426
|
+
const baseUrl = args.url || "http://localhost:4321";
|
|
427
|
+
|
|
428
|
+
// Resolve token: --token flag > EMDASH_TOKEN env > stored credentials
|
|
429
|
+
let token = args.token || process.env["EMDASH_TOKEN"];
|
|
430
|
+
let authMethod = token ? "token" : "none";
|
|
431
|
+
let storedHeaders: Record<string, string> = {};
|
|
432
|
+
|
|
433
|
+
if (!token) {
|
|
434
|
+
const cred = getCredentials(baseUrl);
|
|
435
|
+
if (cred) {
|
|
436
|
+
token = cred.accessToken;
|
|
437
|
+
authMethod = "stored";
|
|
438
|
+
storedHeaders = cred.customHeaders ?? {};
|
|
439
|
+
|
|
440
|
+
// Check if expired
|
|
441
|
+
if (new Date(cred.expiresAt) < new Date()) {
|
|
442
|
+
const headerFetch = createHeaderAwareFetch(storedHeaders);
|
|
443
|
+
// Try to refresh
|
|
444
|
+
try {
|
|
445
|
+
const refreshRes = await headerFetch(
|
|
446
|
+
new URL("/_emdash/api/oauth/token/refresh", baseUrl),
|
|
447
|
+
{
|
|
448
|
+
method: "POST",
|
|
449
|
+
headers: { "Content-Type": "application/json" },
|
|
450
|
+
body: JSON.stringify({
|
|
451
|
+
refresh_token: cred.refreshToken,
|
|
452
|
+
grant_type: "refresh_token",
|
|
453
|
+
}),
|
|
454
|
+
},
|
|
455
|
+
);
|
|
456
|
+
if (refreshRes.ok) {
|
|
457
|
+
const refreshed = (await refreshRes.json()) as TokenResponse;
|
|
458
|
+
token = refreshed.access_token;
|
|
459
|
+
saveCredentials(baseUrl, {
|
|
460
|
+
...cred,
|
|
461
|
+
accessToken: refreshed.access_token,
|
|
462
|
+
expiresAt: new Date(Date.now() + refreshed.expires_in * 1000).toISOString(),
|
|
463
|
+
});
|
|
464
|
+
} else {
|
|
465
|
+
consola.warn("Stored token expired and refresh failed. Run: emdash login");
|
|
466
|
+
process.exit(2);
|
|
467
|
+
}
|
|
468
|
+
} catch {
|
|
469
|
+
consola.warn("Stored token expired. Run: emdash login");
|
|
470
|
+
process.exit(2);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (!token) {
|
|
477
|
+
// Try dev bypass for local
|
|
478
|
+
const isLocal = baseUrl.includes("localhost") || baseUrl.includes("127.0.0.1");
|
|
479
|
+
if (isLocal) {
|
|
480
|
+
authMethod = "dev-bypass";
|
|
481
|
+
consola.info(`Auth method: ${pc.cyan("dev-bypass")}`);
|
|
482
|
+
consola.info("No stored credentials. Client will use dev bypass for localhost.");
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
consola.error("Not logged in. Run: emdash login");
|
|
487
|
+
process.exit(2);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const headerFetch = createHeaderAwareFetch(storedHeaders);
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
const meRes = await headerFetch(new URL("/_emdash/api/auth/me", baseUrl), {
|
|
494
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
if (!meRes.ok) {
|
|
498
|
+
if (meRes.status === 401) {
|
|
499
|
+
consola.error("Token is invalid or expired. Run: emdash login");
|
|
500
|
+
process.exit(1);
|
|
501
|
+
}
|
|
502
|
+
consola.error(`Failed to fetch user info: ${meRes.status}`);
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const raw = (await meRes.json()) as {
|
|
507
|
+
data: {
|
|
508
|
+
id: string;
|
|
509
|
+
email: string;
|
|
510
|
+
name: string | null;
|
|
511
|
+
role: number;
|
|
512
|
+
};
|
|
513
|
+
};
|
|
514
|
+
const me = raw.data;
|
|
515
|
+
|
|
516
|
+
const roleNames: Record<number, string> = {
|
|
517
|
+
10: "subscriber",
|
|
518
|
+
20: "contributor",
|
|
519
|
+
30: "author",
|
|
520
|
+
40: "editor",
|
|
521
|
+
50: "admin",
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
if (args.json) {
|
|
525
|
+
console.log(
|
|
526
|
+
JSON.stringify({
|
|
527
|
+
id: me.id,
|
|
528
|
+
email: me.email,
|
|
529
|
+
name: me.name,
|
|
530
|
+
role: roleNames[me.role] || `unknown (${me.role})`,
|
|
531
|
+
authMethod,
|
|
532
|
+
url: baseUrl,
|
|
533
|
+
}),
|
|
534
|
+
);
|
|
535
|
+
} else {
|
|
536
|
+
consola.info(`Email: ${pc.bold(me.email)}`);
|
|
537
|
+
if (me.name) consola.info(`Name: ${me.name}`);
|
|
538
|
+
consola.info(`Role: ${pc.cyan(roleNames[me.role] || `unknown (${me.role})`)}`);
|
|
539
|
+
consola.info(`Auth: ${pc.dim(authMethod)}`);
|
|
540
|
+
consola.info(`URL: ${pc.dim(baseUrl)}`);
|
|
541
|
+
}
|
|
542
|
+
} catch (error) {
|
|
543
|
+
consola.error(error instanceof Error ? error.message : "Unknown error");
|
|
544
|
+
process.exit(1);
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
});
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* emdash media
|
|
3
|
+
*
|
|
4
|
+
* Manage media items via the EmDash API
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
8
|
+
import { basename } from "node:path";
|
|
9
|
+
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
import { consola } from "consola";
|
|
12
|
+
|
|
13
|
+
import { connectionArgs, createClientFromArgs } from "../client-factory.js";
|
|
14
|
+
import { output } from "../output.js";
|
|
15
|
+
|
|
16
|
+
const listCommand = defineCommand({
|
|
17
|
+
meta: {
|
|
18
|
+
name: "list",
|
|
19
|
+
description: "List media items",
|
|
20
|
+
},
|
|
21
|
+
args: {
|
|
22
|
+
...connectionArgs,
|
|
23
|
+
mime: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "Filter by MIME type (e.g., image/png)",
|
|
26
|
+
},
|
|
27
|
+
limit: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Number of items to return",
|
|
30
|
+
},
|
|
31
|
+
cursor: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Pagination cursor",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
async run({ args }) {
|
|
37
|
+
const client = createClientFromArgs(args);
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const result = await client.mediaList({
|
|
41
|
+
mimeType: args.mime,
|
|
42
|
+
limit: args.limit ? Number(args.limit) : undefined,
|
|
43
|
+
cursor: args.cursor,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
output(result, args);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
consola.error("Failed to list media:", error instanceof Error ? error.message : error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const uploadCommand = defineCommand({
|
|
55
|
+
meta: {
|
|
56
|
+
name: "upload",
|
|
57
|
+
description: "Upload a media file",
|
|
58
|
+
},
|
|
59
|
+
args: {
|
|
60
|
+
file: {
|
|
61
|
+
type: "positional",
|
|
62
|
+
description: "Path to the file to upload",
|
|
63
|
+
required: true,
|
|
64
|
+
},
|
|
65
|
+
...connectionArgs,
|
|
66
|
+
alt: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "Alt text for the media item",
|
|
69
|
+
},
|
|
70
|
+
caption: {
|
|
71
|
+
type: "string",
|
|
72
|
+
description: "Caption for the media item",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
async run({ args }) {
|
|
76
|
+
const client = createClientFromArgs(args);
|
|
77
|
+
const filename = basename(args.file);
|
|
78
|
+
|
|
79
|
+
consola.start(`Uploading ${filename}...`);
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const buffer = await readFile(args.file);
|
|
83
|
+
const result = await client.mediaUpload(buffer, filename, {
|
|
84
|
+
alt: args.alt,
|
|
85
|
+
caption: args.caption,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
consola.success(`Uploaded ${filename}`);
|
|
89
|
+
output(result, args);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
consola.error("Failed to upload:", error instanceof Error ? error.message : error);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const getCommand = defineCommand({
|
|
98
|
+
meta: {
|
|
99
|
+
name: "get",
|
|
100
|
+
description: "Get a media item",
|
|
101
|
+
},
|
|
102
|
+
args: {
|
|
103
|
+
id: {
|
|
104
|
+
type: "positional",
|
|
105
|
+
description: "Media item ID",
|
|
106
|
+
required: true,
|
|
107
|
+
},
|
|
108
|
+
...connectionArgs,
|
|
109
|
+
},
|
|
110
|
+
async run({ args }) {
|
|
111
|
+
const client = createClientFromArgs(args);
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const result = await client.mediaGet(args.id);
|
|
115
|
+
output(result, args);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
consola.error("Failed to get media:", error instanceof Error ? error.message : error);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const deleteCommand = defineCommand({
|
|
124
|
+
meta: {
|
|
125
|
+
name: "delete",
|
|
126
|
+
description: "Delete a media item",
|
|
127
|
+
},
|
|
128
|
+
args: {
|
|
129
|
+
id: {
|
|
130
|
+
type: "positional",
|
|
131
|
+
description: "Media item ID",
|
|
132
|
+
required: true,
|
|
133
|
+
},
|
|
134
|
+
...connectionArgs,
|
|
135
|
+
},
|
|
136
|
+
async run({ args }) {
|
|
137
|
+
const client = createClientFromArgs(args);
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
await client.mediaDelete(args.id);
|
|
141
|
+
|
|
142
|
+
if (args.json) {
|
|
143
|
+
output({ deleted: true }, args);
|
|
144
|
+
} else {
|
|
145
|
+
consola.success(`Deleted media item ${args.id}`);
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
consola.error("Failed to delete media:", error instanceof Error ? error.message : error);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
export const mediaCommand = defineCommand({
|
|
155
|
+
meta: {
|
|
156
|
+
name: "media",
|
|
157
|
+
description: "Manage media items",
|
|
158
|
+
},
|
|
159
|
+
subCommands: {
|
|
160
|
+
list: listCommand,
|
|
161
|
+
upload: uploadCommand,
|
|
162
|
+
get: getCommand,
|
|
163
|
+
delete: deleteCommand,
|
|
164
|
+
},
|
|
165
|
+
});
|