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 @@
|
|
|
1
|
+
export { generateOpenApiDocument } from "./document.js";
|
package/src/api/parse.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request body and query parameter parsing with Zod validation.
|
|
3
|
+
*
|
|
4
|
+
* All API routes should use these utilities instead of `request.json() as T`
|
|
5
|
+
* or raw `url.searchParams.get()` with manual coercion.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
|
|
10
|
+
import { apiError } from "./error.js";
|
|
11
|
+
|
|
12
|
+
/** Maximum allowed JSON request body size (10 MB). */
|
|
13
|
+
const MAX_BODY_SIZE = 10 * 1024 * 1024;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Result of parsing: either the validated data or an error Response.
|
|
17
|
+
* Routes should check `if (result instanceof Response) return result;`
|
|
18
|
+
*/
|
|
19
|
+
export type ParseResult<T> = T | Response;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Parse and validate a JSON request body against a Zod schema.
|
|
23
|
+
*
|
|
24
|
+
* Returns the validated data on success, or a 400 Response on failure.
|
|
25
|
+
* Replaces all `(await request.json()) as T` casts.
|
|
26
|
+
*/
|
|
27
|
+
export async function parseBody<T extends z.ZodType>(
|
|
28
|
+
request: Request,
|
|
29
|
+
schema: T,
|
|
30
|
+
): Promise<ParseResult<z.infer<T>>> {
|
|
31
|
+
// Best-effort size check via Content-Length (can be absent with chunked encoding)
|
|
32
|
+
const contentLength = request.headers.get("Content-Length");
|
|
33
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_BODY_SIZE) {
|
|
34
|
+
return apiError("PAYLOAD_TOO_LARGE", "Request body too large", 413);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let raw: unknown;
|
|
38
|
+
try {
|
|
39
|
+
raw = await request.json();
|
|
40
|
+
} catch {
|
|
41
|
+
return apiError("INVALID_JSON", "Request body must be valid JSON", 400);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return validate(schema, raw);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parse and validate an optional JSON request body.
|
|
49
|
+
*
|
|
50
|
+
* Returns `defaultValue` if the body is empty, or the validated data if present.
|
|
51
|
+
* For endpoints where the body is optional (e.g., preview-url, confirm).
|
|
52
|
+
*/
|
|
53
|
+
export async function parseOptionalBody<T extends z.ZodType>(
|
|
54
|
+
request: Request,
|
|
55
|
+
schema: T,
|
|
56
|
+
defaultValue: z.infer<T>,
|
|
57
|
+
): Promise<ParseResult<z.infer<T>>> {
|
|
58
|
+
// Best-effort size check via Content-Length (can be absent with chunked encoding)
|
|
59
|
+
const contentLength = request.headers.get("Content-Length");
|
|
60
|
+
if (contentLength && parseInt(contentLength, 10) > MAX_BODY_SIZE) {
|
|
61
|
+
return apiError("PAYLOAD_TOO_LARGE", "Request body too large", 413);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let text: string;
|
|
65
|
+
try {
|
|
66
|
+
text = await request.text();
|
|
67
|
+
} catch {
|
|
68
|
+
return defaultValue;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!text.trim()) {
|
|
72
|
+
return defaultValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let raw: unknown;
|
|
76
|
+
try {
|
|
77
|
+
raw = JSON.parse(text);
|
|
78
|
+
} catch {
|
|
79
|
+
return apiError("INVALID_JSON", "Request body must be valid JSON", 400);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return validate(schema, raw);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Parse and validate URL search params against a Zod schema.
|
|
87
|
+
*
|
|
88
|
+
* Converts searchParams to a plain object before validation.
|
|
89
|
+
* Zod coercion handles string -> number/boolean conversion.
|
|
90
|
+
* Replaces manual `url.searchParams.get()` + `parseInt()` patterns.
|
|
91
|
+
*/
|
|
92
|
+
export function parseQuery<T extends z.ZodType>(url: URL, schema: T): ParseResult<z.infer<T>> {
|
|
93
|
+
const raw: Record<string, string> = {};
|
|
94
|
+
for (const [key, value] of url.searchParams) {
|
|
95
|
+
raw[key] = value;
|
|
96
|
+
}
|
|
97
|
+
return validate(schema, raw);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Validate raw data against a schema. Returns data or error Response.
|
|
102
|
+
*/
|
|
103
|
+
function validate<T extends z.ZodType>(schema: T, data: unknown): ParseResult<z.infer<T>> {
|
|
104
|
+
const result = schema.safeParse(data);
|
|
105
|
+
|
|
106
|
+
if (result.success) {
|
|
107
|
+
return result.data as z.infer<T>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Format Zod errors into a readable structure
|
|
111
|
+
const issues = result.error.issues.map((issue: z.ZodIssue) => ({
|
|
112
|
+
path: issue.path.join("."),
|
|
113
|
+
message: issue.message,
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
return Response.json(
|
|
117
|
+
{
|
|
118
|
+
error: {
|
|
119
|
+
code: "VALIDATION_ERROR",
|
|
120
|
+
message: "Invalid request data",
|
|
121
|
+
details: { issues },
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
status: 400,
|
|
126
|
+
headers: {
|
|
127
|
+
"Cache-Control": "private, no-store",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Type guard to check if a ParseResult is an error Response.
|
|
135
|
+
* Usage: `if (isParseError(result)) return result;`
|
|
136
|
+
*/
|
|
137
|
+
export function isParseError<T>(result: ParseResult<T>): result is Response {
|
|
138
|
+
return result instanceof Response;
|
|
139
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate that a redirect URL is a safe local path.
|
|
3
|
+
*
|
|
4
|
+
* Rejects:
|
|
5
|
+
* - Protocol-relative URLs (`//evil.com`)
|
|
6
|
+
* - Backslash bypass (`/\evil.com` — browsers normalize `\` to `/` in Location headers)
|
|
7
|
+
* - Absolute URLs (`https://evil.com`)
|
|
8
|
+
* - Empty / nullish values
|
|
9
|
+
*/
|
|
10
|
+
export function isSafeRedirect(url: string | null | undefined): url is string {
|
|
11
|
+
return (
|
|
12
|
+
typeof url === "string" && url.startsWith("/") && !url.startsWith("//") && !url.includes("\\")
|
|
13
|
+
);
|
|
14
|
+
}
|
package/src/api/rev.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque _rev token generation and validation.
|
|
3
|
+
*
|
|
4
|
+
* Format: base64("version:updated_at")
|
|
5
|
+
* Stateless — server decodes and checks both components.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* - No _rev sent → blind write (backwards-compatible)
|
|
9
|
+
* - _rev matches → write proceeds, new _rev returned
|
|
10
|
+
* - _rev mismatch → 409 Conflict
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { ContentItem } from "../database/repositories/types.js";
|
|
14
|
+
import { encodeBase64, decodeBase64 } from "../utils/base64.js";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate a _rev token from a content item's version and updatedAt.
|
|
18
|
+
*/
|
|
19
|
+
export function encodeRev(item: ContentItem): string {
|
|
20
|
+
return encodeBase64(`${item.version}:${item.updatedAt}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Decode a _rev token into its components.
|
|
25
|
+
* Returns null if the token is malformed.
|
|
26
|
+
*/
|
|
27
|
+
export function decodeRev(rev: string): { version: number; updatedAt: string } | null {
|
|
28
|
+
try {
|
|
29
|
+
const decoded = decodeBase64(rev);
|
|
30
|
+
const colonIdx = decoded.indexOf(":");
|
|
31
|
+
if (colonIdx === -1) return null;
|
|
32
|
+
|
|
33
|
+
const version = parseInt(decoded.slice(0, colonIdx), 10);
|
|
34
|
+
const updatedAt = decoded.slice(colonIdx + 1);
|
|
35
|
+
|
|
36
|
+
if (isNaN(version) || !updatedAt) return null;
|
|
37
|
+
return { version, updatedAt };
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Validate a _rev token against a content item.
|
|
45
|
+
* Returns null if valid (or if no _rev provided), or an error message if invalid.
|
|
46
|
+
*/
|
|
47
|
+
export function validateRev(
|
|
48
|
+
rev: string | undefined,
|
|
49
|
+
item: ContentItem,
|
|
50
|
+
): { valid: true } | { valid: false; message: string } {
|
|
51
|
+
// No _rev = blind write (backwards-compatible)
|
|
52
|
+
if (!rev) return { valid: true };
|
|
53
|
+
|
|
54
|
+
const decoded = decodeRev(rev);
|
|
55
|
+
if (!decoded) {
|
|
56
|
+
return { valid: false, message: "Malformed _rev token" };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (decoded.version !== item.version || decoded.updatedAt !== item.updatedAt) {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
message: "Content has been modified since last read (version conflict)",
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { valid: true };
|
|
67
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { roleLevel } from "./common.js";
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// WebAuthn credential schemas (matching @emdash-cms/auth/passkey types)
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
const authenticatorTransport = z.enum(["usb", "nfc", "ble", "internal", "hybrid"]);
|
|
10
|
+
|
|
11
|
+
/** RegistrationResponse — sent by the browser after navigator.credentials.create() */
|
|
12
|
+
const registrationCredential = z.object({
|
|
13
|
+
id: z.string(),
|
|
14
|
+
rawId: z.string(),
|
|
15
|
+
type: z.literal("public-key"),
|
|
16
|
+
response: z.object({
|
|
17
|
+
clientDataJSON: z.string(),
|
|
18
|
+
attestationObject: z.string(),
|
|
19
|
+
transports: z.array(authenticatorTransport).optional(),
|
|
20
|
+
}),
|
|
21
|
+
authenticatorAttachment: z.enum(["platform", "cross-platform"]).optional(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/** AuthenticationResponse — sent by the browser after navigator.credentials.get() */
|
|
25
|
+
const authenticationCredential = z.object({
|
|
26
|
+
id: z.string(),
|
|
27
|
+
rawId: z.string(),
|
|
28
|
+
type: z.literal("public-key"),
|
|
29
|
+
response: z.object({
|
|
30
|
+
clientDataJSON: z.string(),
|
|
31
|
+
authenticatorData: z.string(),
|
|
32
|
+
signature: z.string(),
|
|
33
|
+
userHandle: z.string().optional(),
|
|
34
|
+
}),
|
|
35
|
+
authenticatorAttachment: z.enum(["platform", "cross-platform"]).optional(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Auth: Input schemas
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
export const signupRequestBody = z
|
|
43
|
+
.object({
|
|
44
|
+
email: z.string().email(),
|
|
45
|
+
})
|
|
46
|
+
.meta({ id: "SignupRequestBody" });
|
|
47
|
+
|
|
48
|
+
export const signupCompleteBody = z
|
|
49
|
+
.object({
|
|
50
|
+
token: z.string().min(1),
|
|
51
|
+
credential: registrationCredential,
|
|
52
|
+
name: z.string().optional(),
|
|
53
|
+
})
|
|
54
|
+
.meta({ id: "SignupCompleteBody" });
|
|
55
|
+
|
|
56
|
+
export const inviteCreateBody = z
|
|
57
|
+
.object({
|
|
58
|
+
email: z.string().email(),
|
|
59
|
+
role: roleLevel.optional(),
|
|
60
|
+
})
|
|
61
|
+
.meta({ id: "InviteCreateBody" });
|
|
62
|
+
|
|
63
|
+
export const inviteCompleteBody = z
|
|
64
|
+
.object({
|
|
65
|
+
token: z.string().min(1),
|
|
66
|
+
credential: registrationCredential,
|
|
67
|
+
name: z.string().optional(),
|
|
68
|
+
})
|
|
69
|
+
.meta({ id: "InviteCompleteBody" });
|
|
70
|
+
|
|
71
|
+
export const magicLinkSendBody = z
|
|
72
|
+
.object({
|
|
73
|
+
email: z.string().email(),
|
|
74
|
+
})
|
|
75
|
+
.meta({ id: "MagicLinkSendBody" });
|
|
76
|
+
|
|
77
|
+
export const passkeyOptionsBody = z
|
|
78
|
+
.object({
|
|
79
|
+
email: z.string().email().optional(),
|
|
80
|
+
})
|
|
81
|
+
.meta({ id: "PasskeyOptionsBody" });
|
|
82
|
+
|
|
83
|
+
export const passkeyVerifyBody = z
|
|
84
|
+
.object({
|
|
85
|
+
credential: authenticationCredential,
|
|
86
|
+
})
|
|
87
|
+
.meta({ id: "PasskeyVerifyBody" });
|
|
88
|
+
|
|
89
|
+
export const passkeyRegisterOptionsBody = z
|
|
90
|
+
.object({
|
|
91
|
+
name: z.string().optional(),
|
|
92
|
+
})
|
|
93
|
+
.meta({ id: "PasskeyRegisterOptionsBody" });
|
|
94
|
+
|
|
95
|
+
export const passkeyRegisterVerifyBody = z
|
|
96
|
+
.object({
|
|
97
|
+
credential: registrationCredential,
|
|
98
|
+
name: z.string().optional(),
|
|
99
|
+
})
|
|
100
|
+
.meta({ id: "PasskeyRegisterVerifyBody" });
|
|
101
|
+
|
|
102
|
+
export const passkeyRenameBody = z
|
|
103
|
+
.object({
|
|
104
|
+
name: z.string().min(1),
|
|
105
|
+
})
|
|
106
|
+
.meta({ id: "PasskeyRenameBody" });
|
|
107
|
+
|
|
108
|
+
export const authMeActionBody = z
|
|
109
|
+
.object({
|
|
110
|
+
action: z.string().min(1),
|
|
111
|
+
})
|
|
112
|
+
.meta({ id: "AuthMeActionBody" });
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { cursorPaginationQuery, httpUrl } from "./common.js";
|
|
4
|
+
|
|
5
|
+
/** Slug pattern: lowercase letters, digits, and hyphens; must start with a letter */
|
|
6
|
+
const bylineSlugPattern = /^[a-z][a-z0-9-]*$/;
|
|
7
|
+
|
|
8
|
+
export const bylineSummarySchema = z
|
|
9
|
+
.object({
|
|
10
|
+
id: z.string(),
|
|
11
|
+
slug: z.string(),
|
|
12
|
+
displayName: z.string(),
|
|
13
|
+
bio: z.string().nullable(),
|
|
14
|
+
avatarMediaId: z.string().nullable(),
|
|
15
|
+
websiteUrl: z.string().nullable(),
|
|
16
|
+
userId: z.string().nullable(),
|
|
17
|
+
isGuest: z.boolean(),
|
|
18
|
+
createdAt: z.string(),
|
|
19
|
+
updatedAt: z.string(),
|
|
20
|
+
})
|
|
21
|
+
.meta({ id: "BylineSummary" });
|
|
22
|
+
|
|
23
|
+
export const bylineCreditSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
byline: bylineSummarySchema,
|
|
26
|
+
sortOrder: z.number().int(),
|
|
27
|
+
roleLabel: z.string().nullable(),
|
|
28
|
+
source: z.enum(["explicit", "inferred"]).optional().meta({
|
|
29
|
+
description: "Whether this credit was explicitly assigned or inferred from authorId",
|
|
30
|
+
}),
|
|
31
|
+
})
|
|
32
|
+
.meta({ id: "BylineCredit" });
|
|
33
|
+
|
|
34
|
+
export const contentBylineInputSchema = z
|
|
35
|
+
.object({
|
|
36
|
+
bylineId: z.string().min(1),
|
|
37
|
+
roleLabel: z.string().nullish(),
|
|
38
|
+
})
|
|
39
|
+
.meta({ id: "ContentBylineInput" });
|
|
40
|
+
|
|
41
|
+
export const bylinesListQuery = cursorPaginationQuery
|
|
42
|
+
.extend({
|
|
43
|
+
search: z.string().optional(),
|
|
44
|
+
isGuest: z.coerce.boolean().optional(),
|
|
45
|
+
userId: z.string().optional(),
|
|
46
|
+
})
|
|
47
|
+
.meta({ id: "BylinesListQuery" });
|
|
48
|
+
|
|
49
|
+
export const bylineCreateBody = z
|
|
50
|
+
.object({
|
|
51
|
+
slug: z
|
|
52
|
+
.string()
|
|
53
|
+
.min(1)
|
|
54
|
+
.regex(bylineSlugPattern, "Slug must contain only lowercase letters, digits, and hyphens"),
|
|
55
|
+
displayName: z.string().min(1),
|
|
56
|
+
bio: z.string().nullish(),
|
|
57
|
+
avatarMediaId: z.string().nullish(),
|
|
58
|
+
websiteUrl: httpUrl.nullish(),
|
|
59
|
+
userId: z.string().nullish(),
|
|
60
|
+
isGuest: z.boolean().optional(),
|
|
61
|
+
})
|
|
62
|
+
.meta({ id: "BylineCreateBody" });
|
|
63
|
+
|
|
64
|
+
export const bylineUpdateBody = z
|
|
65
|
+
.object({
|
|
66
|
+
slug: z
|
|
67
|
+
.string()
|
|
68
|
+
.min(1)
|
|
69
|
+
.regex(bylineSlugPattern, "Slug must contain only lowercase letters, digits, and hyphens")
|
|
70
|
+
.optional(),
|
|
71
|
+
displayName: z.string().min(1).optional(),
|
|
72
|
+
bio: z.string().nullish(),
|
|
73
|
+
avatarMediaId: z.string().nullish(),
|
|
74
|
+
websiteUrl: httpUrl.nullish(),
|
|
75
|
+
userId: z.string().nullish(),
|
|
76
|
+
isGuest: z.boolean().optional(),
|
|
77
|
+
})
|
|
78
|
+
.meta({ id: "BylineUpdateBody" });
|
|
79
|
+
|
|
80
|
+
export const bylineListResponseSchema = z
|
|
81
|
+
.object({
|
|
82
|
+
items: z.array(bylineSummarySchema),
|
|
83
|
+
nextCursor: z.string().optional(),
|
|
84
|
+
})
|
|
85
|
+
.meta({ id: "BylineListResponse" });
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Comments: Input schemas
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
export const createCommentBody = z
|
|
8
|
+
.object({
|
|
9
|
+
authorName: z.string().min(1).max(100),
|
|
10
|
+
authorEmail: z.string().email(),
|
|
11
|
+
body: z.string().min(1).max(5000),
|
|
12
|
+
parentId: z.string().optional(),
|
|
13
|
+
/** Honeypot field — hidden in the form, filled only by bots */
|
|
14
|
+
website_url: z.string().optional(),
|
|
15
|
+
})
|
|
16
|
+
.meta({ id: "CreateCommentBody" });
|
|
17
|
+
|
|
18
|
+
export const commentStatusBody = z
|
|
19
|
+
.object({
|
|
20
|
+
status: z.enum(["approved", "pending", "spam", "trash"]),
|
|
21
|
+
})
|
|
22
|
+
.meta({ id: "CommentStatusBody" });
|
|
23
|
+
|
|
24
|
+
export const commentBulkBody = z
|
|
25
|
+
.object({
|
|
26
|
+
ids: z.array(z.string().min(1)).min(1).max(100),
|
|
27
|
+
action: z.enum(["approve", "spam", "trash", "delete"]),
|
|
28
|
+
})
|
|
29
|
+
.meta({ id: "CommentBulkBody" });
|
|
30
|
+
|
|
31
|
+
export const commentListQuery = z
|
|
32
|
+
.object({
|
|
33
|
+
status: z.enum(["pending", "approved", "spam", "trash"]).optional(),
|
|
34
|
+
collection: z.string().optional(),
|
|
35
|
+
search: z.string().optional(),
|
|
36
|
+
limit: z.coerce.number().int().min(1).max(100).optional(),
|
|
37
|
+
cursor: z.string().optional(),
|
|
38
|
+
})
|
|
39
|
+
.meta({ id: "CommentListQuery" });
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Comments: Response schemas
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
const commentStatusValues = z.enum(["pending", "approved", "spam", "trash"]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Public-facing comment (no email/IP).
|
|
49
|
+
*
|
|
50
|
+
* `replies` is recursive in practice (each reply can have replies), but we
|
|
51
|
+
* model it as a single level here to avoid circular type inference issues
|
|
52
|
+
* with tsgo. OpenAPI consumers should treat replies as the same shape.
|
|
53
|
+
*/
|
|
54
|
+
export const publicCommentSchema: z.ZodObject<{
|
|
55
|
+
id: z.ZodString;
|
|
56
|
+
authorName: z.ZodString;
|
|
57
|
+
isRegisteredUser: z.ZodBoolean;
|
|
58
|
+
body: z.ZodString;
|
|
59
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
60
|
+
createdAt: z.ZodString;
|
|
61
|
+
replies: z.ZodOptional<z.ZodArray<z.ZodAny>>;
|
|
62
|
+
}> = z
|
|
63
|
+
.object({
|
|
64
|
+
id: z.string(),
|
|
65
|
+
authorName: z.string(),
|
|
66
|
+
isRegisteredUser: z.boolean(),
|
|
67
|
+
body: z.string(),
|
|
68
|
+
parentId: z.string().nullable(),
|
|
69
|
+
createdAt: z.string(),
|
|
70
|
+
replies: z.array(z.any()).optional(),
|
|
71
|
+
})
|
|
72
|
+
.meta({ id: "PublicComment" });
|
|
73
|
+
|
|
74
|
+
/** Admin comment with full details */
|
|
75
|
+
export const commentSchema = z
|
|
76
|
+
.object({
|
|
77
|
+
id: z.string(),
|
|
78
|
+
collection: z.string(),
|
|
79
|
+
contentId: z.string(),
|
|
80
|
+
authorName: z.string(),
|
|
81
|
+
authorEmail: z.string(),
|
|
82
|
+
body: z.string(),
|
|
83
|
+
status: commentStatusValues,
|
|
84
|
+
parentId: z.string().nullable(),
|
|
85
|
+
ipHash: z.string().nullable(),
|
|
86
|
+
createdAt: z.string(),
|
|
87
|
+
updatedAt: z.string(),
|
|
88
|
+
})
|
|
89
|
+
.meta({ id: "Comment" });
|
|
90
|
+
|
|
91
|
+
export const publicCommentListResponseSchema = z
|
|
92
|
+
.object({
|
|
93
|
+
items: z.array(publicCommentSchema),
|
|
94
|
+
nextCursor: z.string().optional(),
|
|
95
|
+
total: z.number().int(),
|
|
96
|
+
})
|
|
97
|
+
.meta({ id: "PublicCommentListResponse" });
|
|
98
|
+
|
|
99
|
+
export const adminCommentListResponseSchema = z
|
|
100
|
+
.object({
|
|
101
|
+
items: z.array(commentSchema),
|
|
102
|
+
nextCursor: z.string().optional(),
|
|
103
|
+
})
|
|
104
|
+
.meta({ id: "AdminCommentListResponse" });
|
|
105
|
+
|
|
106
|
+
export const commentCountsResponseSchema = z
|
|
107
|
+
.object({
|
|
108
|
+
pending: z.number().int(),
|
|
109
|
+
approved: z.number().int(),
|
|
110
|
+
spam: z.number().int(),
|
|
111
|
+
trash: z.number().int(),
|
|
112
|
+
})
|
|
113
|
+
.meta({ id: "CommentCountsResponse" });
|
|
114
|
+
|
|
115
|
+
export const commentBulkResponseSchema = z
|
|
116
|
+
.object({ affected: z.number().int() })
|
|
117
|
+
.meta({ id: "CommentBulkResponse" });
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Role level
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
/** Valid role level values */
|
|
8
|
+
export const VALID_ROLE_LEVELS = new Set([10, 20, 30, 40, 50]);
|
|
9
|
+
|
|
10
|
+
/** Role level — coerces string/number to valid RoleLevel (10|20|30|40|50) */
|
|
11
|
+
export const roleLevel = z.coerce
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.refine((n): n is 10 | 20 | 30 | 40 | 50 => VALID_ROLE_LEVELS.has(n), {
|
|
15
|
+
message: "Invalid role level. Must be 10, 20, 30, 40, or 50",
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Pagination
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
/** Pagination query params — cursor-based */
|
|
23
|
+
export const cursorPaginationQuery = z
|
|
24
|
+
.object({
|
|
25
|
+
cursor: z.string().optional().meta({ description: "Opaque cursor for pagination" }),
|
|
26
|
+
limit: z.coerce.number().int().min(1).max(100).optional().default(50).meta({
|
|
27
|
+
description: "Maximum number of items to return (1-100, default 50)",
|
|
28
|
+
}),
|
|
29
|
+
})
|
|
30
|
+
.meta({ id: "CursorPaginationQuery" });
|
|
31
|
+
|
|
32
|
+
/** Pagination query params — offset-based */
|
|
33
|
+
export const offsetPaginationQuery = z
|
|
34
|
+
.object({
|
|
35
|
+
limit: z.coerce.number().int().min(1).max(100).optional().default(50),
|
|
36
|
+
offset: z.coerce.number().int().min(0).optional().default(0),
|
|
37
|
+
})
|
|
38
|
+
.meta({ id: "OffsetPaginationQuery" });
|
|
39
|
+
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Shared primitives
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
/** Slug pattern: lowercase letters, digits, underscores; starts with letter */
|
|
45
|
+
export const slugPattern = /^[a-z][a-z0-9_]*$/;
|
|
46
|
+
|
|
47
|
+
/** Matches http(s) scheme at start of URL */
|
|
48
|
+
const HTTP_SCHEME_RE = /^https?:\/\//i;
|
|
49
|
+
|
|
50
|
+
/** Validates that a URL string uses http or https scheme. Rejects javascript:/data: URI XSS vectors. */
|
|
51
|
+
export const httpUrl = z
|
|
52
|
+
.string()
|
|
53
|
+
.url()
|
|
54
|
+
.refine((url) => HTTP_SCHEME_RE.test(url), "URL must use http or https");
|
|
55
|
+
|
|
56
|
+
/** BCP 47 locale code — language with optional script/region subtags (e.g. en, en-US, pt-BR, es-419, zh-Hant) */
|
|
57
|
+
export const localeCode = z
|
|
58
|
+
.string()
|
|
59
|
+
.regex(/^[a-z]{2,3}(-[a-z0-9]{2,8})*$/i, "Invalid locale code")
|
|
60
|
+
.transform((v) => v.toLowerCase());
|
|
61
|
+
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// OpenAPI: Shared response schemas
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
/** Standard API error response */
|
|
67
|
+
export const apiErrorSchema = z
|
|
68
|
+
.object({
|
|
69
|
+
error: z.object({
|
|
70
|
+
code: z.string().meta({ description: "Machine-readable error code", example: "NOT_FOUND" }),
|
|
71
|
+
message: z.string().meta({ description: "Human-readable error message" }),
|
|
72
|
+
}),
|
|
73
|
+
})
|
|
74
|
+
.meta({ id: "ApiError" });
|
|
75
|
+
|
|
76
|
+
/** Wrap a data schema in the standard success envelope: { data: T } */
|
|
77
|
+
export function successEnvelope<T extends z.ZodType>(dataSchema: T) {
|
|
78
|
+
return z.object({ data: dataSchema });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Standard delete response */
|
|
82
|
+
export const deleteResponseSchema = z.object({ deleted: z.literal(true) }).meta({
|
|
83
|
+
id: "DeleteResponse",
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/** Standard count response */
|
|
87
|
+
export const countResponseSchema = z
|
|
88
|
+
.object({ count: z.number().int().min(0) })
|
|
89
|
+
.meta({ id: "CountResponse" });
|