emdash 0.0.0-b → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -43
- package/dist/adapters-BLMa4JGD.d.mts +106 -0
- package/dist/adapters-BLMa4JGD.d.mts.map +1 -0
- package/dist/apply-Bjfq_b4-.mjs +1293 -0
- package/dist/apply-Bjfq_b4-.mjs.map +1 -0
- package/dist/astro/index.d.mts +51 -0
- package/dist/astro/index.d.mts.map +1 -0
- package/dist/astro/index.mjs +1336 -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-C0hCbYnD.mjs +1412 -0
- package/dist/runner-C0hCbYnD.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 +684 -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 +349 -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 +335 -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 +116 -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 +115 -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 +101 -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 +58 -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 +68 -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 +697 -0
- package/src/cli/commands/schema.ts +233 -0
- package/src/cli/commands/search-cmd.ts +54 -0
- package/src/cli/commands/seed.ts +286 -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 +170 -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 +39 -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 +249 -0
- package/src/storage/s3.ts +263 -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,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSRF protection for import URLs.
|
|
3
|
+
*
|
|
4
|
+
* Validates that URLs don't target internal/private network addresses.
|
|
5
|
+
* Applied before any fetch() call in the import pipeline.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const IPV4_MAPPED_IPV6_DOTTED_PATTERN = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i;
|
|
9
|
+
const IPV4_MAPPED_IPV6_HEX_PATTERN = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
10
|
+
const IPV4_TRANSLATED_HEX_PATTERN = /^::ffff:0:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
11
|
+
const IPV6_EXPANDED_MAPPED_PATTERN =
|
|
12
|
+
/^0{0,4}:0{0,4}:0{0,4}:0{0,4}:0{0,4}:ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* IPv4-compatible (deprecated) addresses: ::XXXX:XXXX
|
|
16
|
+
*
|
|
17
|
+
* The WHATWG URL parser normalizes [::127.0.0.1] to [::7f00:1] (no ffff prefix).
|
|
18
|
+
* These are deprecated but still parsed, and bypass the ffff-based checks.
|
|
19
|
+
*/
|
|
20
|
+
const IPV4_COMPATIBLE_HEX_PATTERN = /^::([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* NAT64 prefix (RFC 6052): 64:ff9b::XXXX:XXXX
|
|
24
|
+
*
|
|
25
|
+
* Used by NAT64 gateways to embed IPv4 addresses in IPv6.
|
|
26
|
+
* [64:ff9b::127.0.0.1] normalizes to [64:ff9b::7f00:1].
|
|
27
|
+
*/
|
|
28
|
+
const NAT64_HEX_PATTERN = /^64:ff9b::([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
|
|
29
|
+
|
|
30
|
+
const IPV6_BRACKET_PATTERN = /^\[|\]$/g;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Private and reserved IP ranges that should never be fetched.
|
|
34
|
+
*
|
|
35
|
+
* Includes:
|
|
36
|
+
* - Loopback (127.0.0.0/8)
|
|
37
|
+
* - Private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
|
|
38
|
+
* - Link-local (169.254.0.0/16)
|
|
39
|
+
* - Cloud metadata (169.254.169.254 — AWS/GCP/Azure)
|
|
40
|
+
* - IPv6 loopback and link-local
|
|
41
|
+
*/
|
|
42
|
+
const BLOCKED_PATTERNS: Array<{ start: number; end: number }> = [
|
|
43
|
+
// 127.0.0.0/8 — loopback
|
|
44
|
+
{ start: ip4ToNum(127, 0, 0, 0), end: ip4ToNum(127, 255, 255, 255) },
|
|
45
|
+
// 10.0.0.0/8 — private
|
|
46
|
+
{ start: ip4ToNum(10, 0, 0, 0), end: ip4ToNum(10, 255, 255, 255) },
|
|
47
|
+
// 172.16.0.0/12 — private
|
|
48
|
+
{ start: ip4ToNum(172, 16, 0, 0), end: ip4ToNum(172, 31, 255, 255) },
|
|
49
|
+
// 192.168.0.0/16 — private
|
|
50
|
+
{ start: ip4ToNum(192, 168, 0, 0), end: ip4ToNum(192, 168, 255, 255) },
|
|
51
|
+
// 169.254.0.0/16 — link-local (includes cloud metadata endpoint)
|
|
52
|
+
{ start: ip4ToNum(169, 254, 0, 0), end: ip4ToNum(169, 254, 255, 255) },
|
|
53
|
+
// 0.0.0.0/8 — current network
|
|
54
|
+
{ start: ip4ToNum(0, 0, 0, 0), end: ip4ToNum(0, 255, 255, 255) },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
const BLOCKED_HOSTNAMES = new Set([
|
|
58
|
+
"localhost",
|
|
59
|
+
"metadata.google.internal",
|
|
60
|
+
"metadata.google",
|
|
61
|
+
"[::1]",
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
/** Blocked URL schemes */
|
|
65
|
+
const ALLOWED_SCHEMES = new Set(["http:", "https:"]);
|
|
66
|
+
|
|
67
|
+
function ip4ToNum(a: number, b: number, c: number, d: number): number {
|
|
68
|
+
return ((a << 24) | (b << 16) | (c << 8) | d) >>> 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function parseIpv4(ip: string): number | null {
|
|
72
|
+
const parts = ip.split(".");
|
|
73
|
+
if (parts.length !== 4) return null;
|
|
74
|
+
|
|
75
|
+
const nums = parts.map(Number);
|
|
76
|
+
if (nums.some((n) => isNaN(n) || n < 0 || n > 255)) return null;
|
|
77
|
+
|
|
78
|
+
return ip4ToNum(nums[0], nums[1], nums[2], nums[3]);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Convert IPv4-mapped/translated IPv6 addresses from hex form back to IPv4.
|
|
83
|
+
*
|
|
84
|
+
* The WHATWG URL parser normalizes dotted-decimal to hex:
|
|
85
|
+
* [::ffff:127.0.0.1] -> [::ffff:7f00:1]
|
|
86
|
+
* [::ffff:169.254.169.254] -> [::ffff:a9fe:a9fe]
|
|
87
|
+
*
|
|
88
|
+
* Without this conversion, the hex forms bypass isPrivateIp() regex checks.
|
|
89
|
+
*/
|
|
90
|
+
export function normalizeIPv6MappedToIPv4(ip: string): string | null {
|
|
91
|
+
// Match hex-form IPv4-mapped IPv6: ::ffff:XXXX:XXXX
|
|
92
|
+
let match = ip.match(IPV4_MAPPED_IPV6_HEX_PATTERN);
|
|
93
|
+
if (!match) {
|
|
94
|
+
// Match IPv4-translated (RFC 6052): ::ffff:0:XXXX:XXXX
|
|
95
|
+
match = ip.match(IPV4_TRANSLATED_HEX_PATTERN);
|
|
96
|
+
}
|
|
97
|
+
if (!match) {
|
|
98
|
+
// Match fully expanded form: 0000:0000:0000:0000:0000:ffff:XXXX:XXXX
|
|
99
|
+
match = ip.match(IPV6_EXPANDED_MAPPED_PATTERN);
|
|
100
|
+
}
|
|
101
|
+
if (!match) {
|
|
102
|
+
// Match IPv4-compatible (deprecated) form: ::XXXX:XXXX (no ffff prefix)
|
|
103
|
+
match = ip.match(IPV4_COMPATIBLE_HEX_PATTERN);
|
|
104
|
+
}
|
|
105
|
+
if (!match) {
|
|
106
|
+
// Match NAT64 prefix (RFC 6052): 64:ff9b::XXXX:XXXX
|
|
107
|
+
match = ip.match(NAT64_HEX_PATTERN);
|
|
108
|
+
}
|
|
109
|
+
if (match) {
|
|
110
|
+
const high = parseInt(match[1] ?? "", 16);
|
|
111
|
+
const low = parseInt(match[2] ?? "", 16);
|
|
112
|
+
return `${(high >> 8) & 0xff}.${high & 0xff}.${(low >> 8) & 0xff}.${low & 0xff}`;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isPrivateIp(ip: string): boolean {
|
|
118
|
+
// Handle IPv6 loopback
|
|
119
|
+
if (ip === "::1" || ip === "::ffff:127.0.0.1") return true;
|
|
120
|
+
|
|
121
|
+
// Handle IPv4-mapped IPv6 in hex form (WHATWG URL parser normalizes to this)
|
|
122
|
+
// e.g. ::ffff:7f00:1 -> 127.0.0.1, ::ffff:a9fe:a9fe -> 169.254.169.254
|
|
123
|
+
const hexIpv4 = normalizeIPv6MappedToIPv4(ip);
|
|
124
|
+
if (hexIpv4) return isPrivateIp(hexIpv4);
|
|
125
|
+
|
|
126
|
+
// Handle IPv4-mapped IPv6 in dotted-decimal form
|
|
127
|
+
const v4Match = ip.match(IPV4_MAPPED_IPV6_DOTTED_PATTERN);
|
|
128
|
+
const ipv4 = v4Match ? v4Match[1] : ip;
|
|
129
|
+
|
|
130
|
+
const num = parseIpv4(ipv4);
|
|
131
|
+
if (num === null) {
|
|
132
|
+
// If we can't parse it, block IPv6 addresses that look internal
|
|
133
|
+
return ip.startsWith("fe80:") || ip.startsWith("fc") || ip.startsWith("fd");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return BLOCKED_PATTERNS.some((range) => num >= range.start && num <= range.end);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Error thrown when SSRF protection blocks a URL.
|
|
141
|
+
*/
|
|
142
|
+
export class SsrfError extends Error {
|
|
143
|
+
code = "SSRF_BLOCKED" as const;
|
|
144
|
+
|
|
145
|
+
constructor(message: string) {
|
|
146
|
+
super(message);
|
|
147
|
+
this.name = "SsrfError";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Validate that a URL is safe to fetch (not targeting internal networks).
|
|
153
|
+
*
|
|
154
|
+
* Checks:
|
|
155
|
+
* 1. URL is well-formed with http/https scheme
|
|
156
|
+
* 2. Hostname is not a known internal name (localhost, metadata endpoints)
|
|
157
|
+
* 3. If hostname is an IP literal, it's not in a private range
|
|
158
|
+
*
|
|
159
|
+
* Note: DNS rebinding attacks are not fully mitigated (hostname could resolve
|
|
160
|
+
* to a private IP). Full protection requires resolving DNS and checking the IP
|
|
161
|
+
* before connecting, which needs a custom fetch implementation. This covers
|
|
162
|
+
* the most common SSRF vectors.
|
|
163
|
+
*
|
|
164
|
+
* @throws SsrfError if the URL targets an internal address
|
|
165
|
+
*/
|
|
166
|
+
/** Maximum number of redirects to follow in ssrfSafeFetch */
|
|
167
|
+
const MAX_REDIRECTS = 5;
|
|
168
|
+
|
|
169
|
+
export function validateExternalUrl(url: string): URL {
|
|
170
|
+
let parsed: URL;
|
|
171
|
+
try {
|
|
172
|
+
parsed = new URL(url);
|
|
173
|
+
} catch {
|
|
174
|
+
throw new SsrfError("Invalid URL");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Only allow http/https
|
|
178
|
+
if (!ALLOWED_SCHEMES.has(parsed.protocol)) {
|
|
179
|
+
throw new SsrfError(`Scheme '${parsed.protocol}' is not allowed`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Strip brackets from IPv6 hostname
|
|
183
|
+
const hostname = parsed.hostname.replace(IPV6_BRACKET_PATTERN, "");
|
|
184
|
+
|
|
185
|
+
// Check against known internal hostnames
|
|
186
|
+
if (BLOCKED_HOSTNAMES.has(hostname.toLowerCase())) {
|
|
187
|
+
throw new SsrfError("URLs targeting internal hosts are not allowed");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Check if hostname is an IP address in a private range
|
|
191
|
+
if (isPrivateIp(hostname)) {
|
|
192
|
+
throw new SsrfError("URLs targeting private IP addresses are not allowed");
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return parsed;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Fetch a URL with SSRF protection on redirects.
|
|
200
|
+
*
|
|
201
|
+
* Uses `redirect: "manual"` to intercept redirects and re-validate each
|
|
202
|
+
* redirect target against SSRF rules before following it. This prevents
|
|
203
|
+
* an attacker from setting up an allowed external URL that redirects to
|
|
204
|
+
* an internal IP (e.g. 169.254.169.254 for cloud metadata).
|
|
205
|
+
*
|
|
206
|
+
* @throws SsrfError if the initial URL or any redirect target is internal
|
|
207
|
+
*/
|
|
208
|
+
/** Headers that must be stripped when a redirect crosses origins */
|
|
209
|
+
const CREDENTIAL_HEADERS = ["authorization", "cookie", "proxy-authorization"];
|
|
210
|
+
|
|
211
|
+
export async function ssrfSafeFetch(url: string, init?: RequestInit): Promise<Response> {
|
|
212
|
+
let currentUrl = url;
|
|
213
|
+
let currentInit = init;
|
|
214
|
+
|
|
215
|
+
for (let i = 0; i <= MAX_REDIRECTS; i++) {
|
|
216
|
+
validateExternalUrl(currentUrl);
|
|
217
|
+
|
|
218
|
+
const response = await globalThis.fetch(currentUrl, {
|
|
219
|
+
...currentInit,
|
|
220
|
+
redirect: "manual",
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Not a redirect -- return directly
|
|
224
|
+
if (response.status < 300 || response.status >= 400) {
|
|
225
|
+
return response;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Extract redirect target
|
|
229
|
+
const location = response.headers.get("Location");
|
|
230
|
+
if (!location) {
|
|
231
|
+
return response;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Resolve relative redirects against the current URL
|
|
235
|
+
const previousOrigin = new URL(currentUrl).origin;
|
|
236
|
+
currentUrl = new URL(location, currentUrl).href;
|
|
237
|
+
const nextOrigin = new URL(currentUrl).origin;
|
|
238
|
+
|
|
239
|
+
// Strip credential headers on cross-origin redirects
|
|
240
|
+
if (previousOrigin !== nextOrigin && currentInit) {
|
|
241
|
+
currentInit = stripCredentialHeaders(currentInit);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
throw new SsrfError(`Too many redirects (max ${MAX_REDIRECTS})`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Return a copy of init with credential headers removed.
|
|
250
|
+
*/
|
|
251
|
+
export function stripCredentialHeaders(init: RequestInit): RequestInit {
|
|
252
|
+
if (!init.headers) return init;
|
|
253
|
+
|
|
254
|
+
const headers = new Headers(init.headers);
|
|
255
|
+
for (const name of CREDENTIAL_HEADERS) {
|
|
256
|
+
headers.delete(name);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return { ...init, headers };
|
|
260
|
+
}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import source abstraction
|
|
3
|
+
*
|
|
4
|
+
* Allows different import sources (WXR file, WordPress.com API, REST API, plugin)
|
|
5
|
+
* to all produce the same normalized format for the import flow.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PortableTextBlock } from "@emdash-cms/gutenberg-to-portable-text";
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Author Types
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/** Author info from WordPress */
|
|
15
|
+
export interface WpAuthorInfo {
|
|
16
|
+
id?: number;
|
|
17
|
+
login?: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
displayName?: string;
|
|
20
|
+
postCount: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Source Input Types
|
|
25
|
+
// =============================================================================
|
|
26
|
+
|
|
27
|
+
/** File-based input (WXR upload) */
|
|
28
|
+
export interface FileInput {
|
|
29
|
+
type: "file";
|
|
30
|
+
file: File;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** URL-based input (REST API probe) */
|
|
34
|
+
export interface UrlInput {
|
|
35
|
+
type: "url";
|
|
36
|
+
url: string;
|
|
37
|
+
/** Optional auth token for authenticated requests */
|
|
38
|
+
token?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** OAuth-based input (WordPress.com) */
|
|
42
|
+
export interface OAuthInput {
|
|
43
|
+
type: "oauth";
|
|
44
|
+
url: string;
|
|
45
|
+
accessToken: string;
|
|
46
|
+
/** Site ID for WordPress.com */
|
|
47
|
+
siteId?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type SourceInput = FileInput | UrlInput | OAuthInput;
|
|
51
|
+
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Probe Result Types
|
|
54
|
+
// =============================================================================
|
|
55
|
+
|
|
56
|
+
/** Auth requirements for an import source */
|
|
57
|
+
export interface SourceAuth {
|
|
58
|
+
type: "oauth" | "token" | "password" | "none";
|
|
59
|
+
/** OAuth provider identifier */
|
|
60
|
+
provider?: string;
|
|
61
|
+
/** OAuth authorization URL */
|
|
62
|
+
oauthUrl?: string;
|
|
63
|
+
/** Human-readable instructions */
|
|
64
|
+
instructions?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** What the source can provide */
|
|
68
|
+
export interface SourceCapabilities {
|
|
69
|
+
/** Can fetch published content without auth */
|
|
70
|
+
publicContent: boolean;
|
|
71
|
+
/** Can fetch drafts/private (may need auth) */
|
|
72
|
+
privateContent: boolean;
|
|
73
|
+
/** Can fetch all custom post types */
|
|
74
|
+
customPostTypes: boolean;
|
|
75
|
+
/** Can fetch all meta fields */
|
|
76
|
+
allMeta: boolean;
|
|
77
|
+
/** Can stream media directly */
|
|
78
|
+
mediaStream: boolean;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Suggested next action after probe */
|
|
82
|
+
export type SuggestedAction =
|
|
83
|
+
| { type: "proceed" }
|
|
84
|
+
| { type: "oauth"; url: string; provider: string }
|
|
85
|
+
| { type: "upload"; instructions: string }
|
|
86
|
+
| { type: "install-plugin"; instructions: string };
|
|
87
|
+
|
|
88
|
+
/** Detected i18n/multilingual plugin info */
|
|
89
|
+
export interface I18nDetection {
|
|
90
|
+
/** Multilingual plugin name (e.g. "wpml", "polylang") */
|
|
91
|
+
plugin: string;
|
|
92
|
+
/** BCP 47 default locale */
|
|
93
|
+
defaultLocale: string;
|
|
94
|
+
/** All configured locales */
|
|
95
|
+
locales: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Result of probing a URL for a specific source */
|
|
99
|
+
export interface SourceProbeResult {
|
|
100
|
+
/** Which source can handle this */
|
|
101
|
+
sourceId: string;
|
|
102
|
+
|
|
103
|
+
/** Confidence level */
|
|
104
|
+
confidence: "definite" | "likely" | "possible";
|
|
105
|
+
|
|
106
|
+
/** What we detected */
|
|
107
|
+
detected: {
|
|
108
|
+
platform: string;
|
|
109
|
+
version?: string;
|
|
110
|
+
siteTitle?: string;
|
|
111
|
+
siteUrl?: string;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** What capabilities are available */
|
|
115
|
+
capabilities: SourceCapabilities;
|
|
116
|
+
|
|
117
|
+
/** What auth is needed, if any */
|
|
118
|
+
auth?: SourceAuth;
|
|
119
|
+
|
|
120
|
+
/** Suggested next step */
|
|
121
|
+
suggestedAction: SuggestedAction;
|
|
122
|
+
|
|
123
|
+
/** Preview data if available (e.g., post counts from REST API) */
|
|
124
|
+
preview?: {
|
|
125
|
+
posts?: number;
|
|
126
|
+
pages?: number;
|
|
127
|
+
media?: number;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/** Detected multilingual plugin. Absent when none detected. */
|
|
131
|
+
i18n?: I18nDetection;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Combined probe result from all sources */
|
|
135
|
+
export interface ProbeResult {
|
|
136
|
+
url: string;
|
|
137
|
+
isWordPress: boolean;
|
|
138
|
+
/** Best matching source (highest confidence) */
|
|
139
|
+
bestMatch: SourceProbeResult | null;
|
|
140
|
+
/** All matching sources */
|
|
141
|
+
allMatches: SourceProbeResult[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// =============================================================================
|
|
145
|
+
// Analysis Types (normalized from all sources)
|
|
146
|
+
// =============================================================================
|
|
147
|
+
|
|
148
|
+
/** Field definition for import */
|
|
149
|
+
export interface ImportFieldDef {
|
|
150
|
+
slug: string;
|
|
151
|
+
label: string;
|
|
152
|
+
type: string;
|
|
153
|
+
required: boolean;
|
|
154
|
+
searchable?: boolean;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Field compatibility with existing schema */
|
|
158
|
+
export type FieldCompatibility = "compatible" | "type_mismatch" | "missing";
|
|
159
|
+
|
|
160
|
+
/** Schema status for a collection */
|
|
161
|
+
export interface CollectionSchemaStatus {
|
|
162
|
+
exists: boolean;
|
|
163
|
+
fieldStatus: Record<
|
|
164
|
+
string,
|
|
165
|
+
{
|
|
166
|
+
status: FieldCompatibility;
|
|
167
|
+
existingType?: string;
|
|
168
|
+
requiredType: string;
|
|
169
|
+
}
|
|
170
|
+
>;
|
|
171
|
+
canImport: boolean;
|
|
172
|
+
reason?: string;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Analysis of a single post type */
|
|
176
|
+
export interface PostTypeAnalysis {
|
|
177
|
+
name: string;
|
|
178
|
+
count: number;
|
|
179
|
+
suggestedCollection: string;
|
|
180
|
+
requiredFields: ImportFieldDef[];
|
|
181
|
+
schemaStatus: CollectionSchemaStatus;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Attachment/media info */
|
|
185
|
+
export interface AttachmentInfo {
|
|
186
|
+
id?: number;
|
|
187
|
+
title?: string;
|
|
188
|
+
url?: string;
|
|
189
|
+
filename?: string;
|
|
190
|
+
mimeType?: string;
|
|
191
|
+
alt?: string;
|
|
192
|
+
caption?: string;
|
|
193
|
+
width?: number;
|
|
194
|
+
height?: number;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Navigation menu analysis */
|
|
198
|
+
export interface NavMenuAnalysis {
|
|
199
|
+
/** Menu name/slug */
|
|
200
|
+
name: string;
|
|
201
|
+
/** Menu display label */
|
|
202
|
+
label: string;
|
|
203
|
+
/** Number of items in this menu */
|
|
204
|
+
itemCount: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Custom taxonomy analysis */
|
|
208
|
+
export interface TaxonomyAnalysis {
|
|
209
|
+
/** Taxonomy slug (e.g., 'genre', 'portfolio_category') */
|
|
210
|
+
slug: string;
|
|
211
|
+
/** Number of terms in this taxonomy */
|
|
212
|
+
termCount: number;
|
|
213
|
+
/** Sample term names */
|
|
214
|
+
sampleTerms: string[];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Reusable block analysis (wp_block post type) */
|
|
218
|
+
export interface ReusableBlockAnalysis {
|
|
219
|
+
/** Original WP ID */
|
|
220
|
+
id: number;
|
|
221
|
+
/** Block title */
|
|
222
|
+
title: string;
|
|
223
|
+
/** Block slug */
|
|
224
|
+
slug: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Normalized analysis result - same format for all sources */
|
|
228
|
+
export interface ImportAnalysis {
|
|
229
|
+
/** Source that produced this analysis */
|
|
230
|
+
sourceId: string;
|
|
231
|
+
|
|
232
|
+
site: {
|
|
233
|
+
title: string;
|
|
234
|
+
url: string;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
postTypes: PostTypeAnalysis[];
|
|
238
|
+
|
|
239
|
+
attachments: {
|
|
240
|
+
count: number;
|
|
241
|
+
items: AttachmentInfo[];
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
categories: number;
|
|
245
|
+
tags: number;
|
|
246
|
+
authors: WpAuthorInfo[];
|
|
247
|
+
|
|
248
|
+
/** Navigation menus found in the export */
|
|
249
|
+
navMenus?: NavMenuAnalysis[];
|
|
250
|
+
|
|
251
|
+
/** Custom taxonomies (beyond categories/tags) */
|
|
252
|
+
customTaxonomies?: TaxonomyAnalysis[];
|
|
253
|
+
|
|
254
|
+
/** Reusable blocks (wp_block post type) - will be imported as sections */
|
|
255
|
+
reusableBlocks?: ReusableBlockAnalysis[];
|
|
256
|
+
|
|
257
|
+
/** Source-specific custom fields analysis */
|
|
258
|
+
customFields?: Array<{
|
|
259
|
+
key: string;
|
|
260
|
+
count: number;
|
|
261
|
+
samples: string[];
|
|
262
|
+
suggestedField: string;
|
|
263
|
+
suggestedType: "string" | "number" | "boolean" | "date" | "json";
|
|
264
|
+
isInternal: boolean;
|
|
265
|
+
}>;
|
|
266
|
+
|
|
267
|
+
/** Detected multilingual plugin. Absent when none detected. */
|
|
268
|
+
i18n?: I18nDetection;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// =============================================================================
|
|
272
|
+
// Normalized Content Types
|
|
273
|
+
// =============================================================================
|
|
274
|
+
|
|
275
|
+
/** Normalized content item - produced by all sources */
|
|
276
|
+
export interface NormalizedItem {
|
|
277
|
+
/** Original ID from source */
|
|
278
|
+
sourceId: string | number;
|
|
279
|
+
/** WordPress post type */
|
|
280
|
+
postType: string;
|
|
281
|
+
/** Content status */
|
|
282
|
+
status: "publish" | "draft" | "pending" | "private" | "future";
|
|
283
|
+
/** URL slug */
|
|
284
|
+
slug: string;
|
|
285
|
+
/** Title */
|
|
286
|
+
title: string;
|
|
287
|
+
/** Content as Portable Text (already converted) */
|
|
288
|
+
content: PortableTextBlock[];
|
|
289
|
+
/** Excerpt/summary */
|
|
290
|
+
excerpt?: string;
|
|
291
|
+
/** Publication date */
|
|
292
|
+
date: Date;
|
|
293
|
+
/** Last modified date */
|
|
294
|
+
modified?: Date;
|
|
295
|
+
/** Author identifier */
|
|
296
|
+
author?: string;
|
|
297
|
+
/** Category slugs */
|
|
298
|
+
categories?: string[];
|
|
299
|
+
/** Tag slugs */
|
|
300
|
+
tags?: string[];
|
|
301
|
+
/** Custom meta fields */
|
|
302
|
+
meta?: Record<string, unknown>;
|
|
303
|
+
/** Featured image URL */
|
|
304
|
+
featuredImage?: string;
|
|
305
|
+
/** Parent post ID (for hierarchical content like pages) */
|
|
306
|
+
parentId?: string | number;
|
|
307
|
+
/** Menu order for sorting */
|
|
308
|
+
menuOrder?: number;
|
|
309
|
+
/** Custom taxonomy assignments beyond categories/tags */
|
|
310
|
+
customTaxonomies?: Record<string, string[]>;
|
|
311
|
+
|
|
312
|
+
/** BCP 47 locale code. When omitted, defaults to defaultLocale. */
|
|
313
|
+
locale?: string;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Source-side translation group ID (opaque string from the origin system).
|
|
317
|
+
* Items sharing the same translationGroup are linked as translations.
|
|
318
|
+
* Resolved to an EmDash translation_group ULID during execute.
|
|
319
|
+
*/
|
|
320
|
+
translationGroup?: string;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// =============================================================================
|
|
324
|
+
// Import Configuration & Results
|
|
325
|
+
// =============================================================================
|
|
326
|
+
|
|
327
|
+
/** Post type mapping configuration */
|
|
328
|
+
export interface PostTypeMapping {
|
|
329
|
+
enabled: boolean;
|
|
330
|
+
collection: string;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Import configuration */
|
|
334
|
+
export interface ImportConfig {
|
|
335
|
+
postTypeMappings: Record<string, PostTypeMapping>;
|
|
336
|
+
skipExisting?: boolean;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Options for fetching content */
|
|
340
|
+
export interface FetchOptions {
|
|
341
|
+
/** Post types to fetch */
|
|
342
|
+
postTypes: string[];
|
|
343
|
+
/** Whether to include drafts */
|
|
344
|
+
includeDrafts?: boolean;
|
|
345
|
+
/** Limit number of items (for testing) */
|
|
346
|
+
limit?: number;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** Import result */
|
|
350
|
+
export interface ImportResult {
|
|
351
|
+
success: boolean;
|
|
352
|
+
imported: number;
|
|
353
|
+
skipped: number;
|
|
354
|
+
errors: Array<{ title: string; error: string }>;
|
|
355
|
+
byCollection: Record<string, number>;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// =============================================================================
|
|
359
|
+
// Import Source Interface
|
|
360
|
+
// =============================================================================
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* An import source provides content from an external system.
|
|
364
|
+
* All sources produce the same normalized analysis and content format.
|
|
365
|
+
*/
|
|
366
|
+
export interface ImportSource {
|
|
367
|
+
/** Unique identifier */
|
|
368
|
+
id: string;
|
|
369
|
+
|
|
370
|
+
/** Display name */
|
|
371
|
+
name: string;
|
|
372
|
+
|
|
373
|
+
/** Description for UI */
|
|
374
|
+
description: string;
|
|
375
|
+
|
|
376
|
+
/** Icon identifier */
|
|
377
|
+
icon: "upload" | "globe" | "wordpress" | "plug";
|
|
378
|
+
|
|
379
|
+
/** Whether this source requires a file upload */
|
|
380
|
+
requiresFile?: boolean;
|
|
381
|
+
|
|
382
|
+
/** Whether this source can probe URLs */
|
|
383
|
+
canProbe?: boolean;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Probe a URL to see if this source can handle it.
|
|
387
|
+
* Returns null if not applicable.
|
|
388
|
+
*/
|
|
389
|
+
probe?(url: string): Promise<SourceProbeResult | null>;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Analyze content from this source.
|
|
393
|
+
* Returns normalized ImportAnalysis.
|
|
394
|
+
*/
|
|
395
|
+
analyze(input: SourceInput, context: ImportContext): Promise<ImportAnalysis>;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Stream content items for import.
|
|
399
|
+
* Yields normalized content items.
|
|
400
|
+
*/
|
|
401
|
+
fetchContent(input: SourceInput, options: FetchOptions): AsyncGenerator<NormalizedItem>;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Fetch a media item's data.
|
|
405
|
+
* Used for media import.
|
|
406
|
+
*/
|
|
407
|
+
fetchMedia?(url: string, input: SourceInput): Promise<Blob>;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Context passed to import sources */
|
|
411
|
+
export interface ImportContext {
|
|
412
|
+
/** Database connection for schema checks */
|
|
413
|
+
db?: unknown;
|
|
414
|
+
/** Function to check existing collections */
|
|
415
|
+
getExistingCollections?: () => Promise<
|
|
416
|
+
Map<string, { slug: string; fields: Map<string, { type: string }> }>
|
|
417
|
+
>;
|
|
418
|
+
}
|