emdash 0.7.0 → 0.9.0
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/dist/{adapters-Di31kZ28.d.mts → adapters-DoNJiveC.d.mts} +1 -1
- package/dist/{adapters-Di31kZ28.d.mts.map → adapters-DoNJiveC.d.mts.map} +1 -1
- package/dist/{apply-5uslYdUu.mjs → apply-BzltprvY.mjs} +90 -139
- package/dist/apply-BzltprvY.mjs.map +1 -0
- package/dist/astro/index.d.mts +6 -6
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +194 -17
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +6 -7
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +34 -57
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +17 -12
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +9 -6
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +301 -165
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/types.d.mts +34 -10
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/{base64-MBPo9ozB.mjs → base64-BRICGH2l.mjs} +1 -1
- package/dist/{base64-MBPo9ozB.mjs.map → base64-BRICGH2l.mjs.map} +1 -1
- package/dist/{byline-C4OVd8b3.mjs → byline-BSaNL1w7.mjs} +5 -5
- package/dist/byline-BSaNL1w7.mjs.map +1 -0
- package/dist/bylines-CvJ3PYz2.mjs +113 -0
- package/dist/bylines-CvJ3PYz2.mjs.map +1 -0
- package/dist/cache-C6N_hhN7.mjs +65 -0
- package/dist/cache-C6N_hhN7.mjs.map +1 -0
- package/dist/{chunks-HGz06Soa.mjs → chunks-NBQVDOci.mjs} +8 -2
- package/dist/{chunks-HGz06Soa.mjs.map → chunks-NBQVDOci.mjs.map} +1 -1
- package/dist/cli/index.mjs +229 -31
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +3 -3
- package/dist/client/index.mjs.map +1 -1
- package/dist/{config-BXwuX8Bx.mjs → config-BI0V3ICQ.mjs} +1 -1
- package/dist/{config-BXwuX8Bx.mjs.map → config-BI0V3ICQ.mjs.map} +1 -1
- package/dist/{content-D7J5y73J.mjs → content-8lOYF0pr.mjs} +43 -28
- package/dist/content-8lOYF0pr.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/libsql.d.mts.map +1 -1
- package/dist/db/libsql.mjs +7 -2
- package/dist/db/libsql.mjs.map +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.d.mts.map +1 -1
- package/dist/db/sqlite.mjs +8 -3
- package/dist/db/sqlite.mjs.map +1 -1
- package/dist/{db-errors-D0UT85nC.mjs → db-errors-WRezodiz.mjs} +1 -1
- package/dist/{db-errors-D0UT85nC.mjs.map → db-errors-WRezodiz.mjs.map} +1 -1
- package/dist/{default-CME5YdZ3.mjs → default-D8ksjWhO.mjs} +1 -1
- package/dist/{default-CME5YdZ3.mjs.map → default-D8ksjWhO.mjs.map} +1 -1
- package/dist/{dialect-helpers-DhTzaUxP.mjs → dialect-helpers-BKCvISIQ.mjs} +19 -2
- package/dist/dialect-helpers-BKCvISIQ.mjs.map +1 -0
- package/dist/{error-CiYn9yDu.mjs → error-D_-tqP-I.mjs} +1 -1
- package/dist/error-D_-tqP-I.mjs.map +1 -0
- package/dist/{index-De6_Xv3v.d.mts → index-BFRaVcD6.d.mts} +243 -40
- package/dist/index-BFRaVcD6.d.mts.map +1 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +29 -25
- package/dist/{load-CBcmDIot.mjs → load-DDqMMvZL.mjs} +2 -2
- package/dist/{load-CBcmDIot.mjs.map → load-DDqMMvZL.mjs.map} +1 -1
- package/dist/{loader-DeiBJEMe.mjs → loader-CKLbBnhK.mjs} +32 -10
- package/dist/loader-CKLbBnhK.mjs.map +1 -0
- package/dist/{manifest-schema-V30qsMft.mjs → manifest-schema-DqWNC3lM.mjs} +45 -3
- package/dist/manifest-schema-DqWNC3lM.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +1 -1
- package/dist/media/local-runtime.d.mts +7 -7
- package/dist/media/local-runtime.mjs +3 -3
- package/dist/{media-DqHVh136.mjs → media-BW32b4gi.mjs} +4 -7
- package/dist/media-BW32b4gi.mjs.map +1 -0
- package/dist/{mode-CpNnGkPz.mjs → mode-ier8jbBk.mjs} +1 -1
- package/dist/mode-ier8jbBk.mjs.map +1 -0
- package/dist/options-BVp3UsTS.mjs +117 -0
- package/dist/options-BVp3UsTS.mjs.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{placeholder-tzpqGWII.d.mts → placeholder-BE4o_2dc.d.mts} +1 -1
- package/dist/{placeholder-tzpqGWII.d.mts.map → placeholder-BE4o_2dc.d.mts.map} +1 -1
- package/dist/{placeholder-C-fk5hYI.mjs → placeholder-CIJejMlK.mjs} +1 -1
- package/dist/placeholder-CIJejMlK.mjs.map +1 -0
- package/dist/plugins/adapt-sandbox-entry.d.mts +5 -5
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +6 -5
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/public-url-DByxYjUw.mjs +51 -0
- package/dist/public-url-DByxYjUw.mjs.map +1 -0
- package/dist/{query-g4Ug-9j9.mjs → query-Cg9ZKRQ0.mjs} +114 -16
- package/dist/query-Cg9ZKRQ0.mjs.map +1 -0
- package/dist/{redirect-CN0Rt9Ob.mjs → redirect-BhUBKRc1.mjs} +13 -8
- package/dist/redirect-BhUBKRc1.mjs.map +1 -0
- package/dist/{registry-Ci3WxVAr.mjs → registry-Dw70ChxB.mjs} +69 -11
- package/dist/registry-Dw70ChxB.mjs.map +1 -0
- package/dist/{request-cache-DiR961CV.mjs → request-cache-B-bmkipQ.mjs} +1 -1
- package/dist/request-cache-B-bmkipQ.mjs.map +1 -0
- package/dist/runner-Bnoj7vjK.d.mts +44 -0
- package/dist/runner-Bnoj7vjK.d.mts.map +1 -0
- package/dist/{runner-tQ7BJ4T7.mjs → runner-C7ADox5q.mjs} +185 -55
- package/dist/{runner-tQ7BJ4T7.mjs.map → runner-C7ADox5q.mjs.map} +1 -1
- package/dist/runtime.d.mts +6 -6
- package/dist/runtime.mjs +4 -4
- package/dist/{search-B0effn3j.mjs → search-dOGEccMa.mjs} +341 -152
- package/dist/search-dOGEccMa.mjs.map +1 -0
- package/dist/secrets-CW3reAnU.mjs +314 -0
- package/dist/secrets-CW3reAnU.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +15 -14
- package/dist/seo/index.d.mts +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.d.mts.map +1 -1
- package/dist/storage/s3.mjs +4 -4
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{taxonomies-K2z0Uhnj.mjs → taxonomies-ZlRtD6AG.mjs} +14 -7
- package/dist/taxonomies-ZlRtD6AG.mjs.map +1 -0
- package/dist/{tokens-BFPFx3CA.mjs → tokens-D7zMmWi2.mjs} +2 -2
- package/dist/{tokens-BFPFx3CA.mjs.map → tokens-D7zMmWi2.mjs.map} +1 -1
- package/dist/{transport-BykRfpyy.mjs → transport-BeMCmin1.mjs} +6 -5
- package/dist/{transport-BykRfpyy.mjs.map → transport-BeMCmin1.mjs.map} +1 -1
- package/dist/{transport-H4Iwx7tC.d.mts → transport-DNEfeMaU.d.mts} +1 -1
- package/dist/{transport-H4Iwx7tC.d.mts.map → transport-DNEfeMaU.d.mts.map} +1 -1
- package/dist/types-4fVtCIm0.mjs +68 -0
- package/dist/types-4fVtCIm0.mjs.map +1 -0
- package/dist/{types-CnZYHyLW.d.mts → types-BSyXeCFW.d.mts} +24 -2
- package/dist/{types-CnZYHyLW.d.mts.map → types-BSyXeCFW.d.mts.map} +1 -1
- package/dist/{types-DgrIP0tF.d.mts → types-BuBIptGk.d.mts} +80 -106
- package/dist/types-BuBIptGk.d.mts.map +1 -0
- package/dist/{types-BH2L167P.mjs → types-CDbKp7ND.mjs} +1 -1
- package/dist/{types-BH2L167P.mjs.map → types-CDbKp7ND.mjs.map} +1 -1
- package/dist/{types-DDS4MxsT.mjs → types-CIOg5AR8.mjs} +1 -1
- package/dist/{types-DDS4MxsT.mjs.map → types-CIOg5AR8.mjs.map} +1 -1
- package/dist/{types-6CUZRrZP.d.mts → types-CJsYGpco.d.mts} +24 -2
- package/dist/{types-6CUZRrZP.d.mts.map → types-CJsYGpco.d.mts.map} +1 -1
- package/dist/types-CRxNbK-Z.mjs +68 -0
- package/dist/types-CRxNbK-Z.mjs.map +1 -0
- package/dist/{types-C2v0c34j.d.mts → types-CrtWgIvl.d.mts} +1 -1
- package/dist/{types-C2v0c34j.d.mts.map → types-CrtWgIvl.d.mts.map} +1 -1
- package/dist/{types-CFWjXmus.d.mts → types-M78DQ1lx.d.mts} +1 -1
- package/dist/{types-CFWjXmus.d.mts.map → types-M78DQ1lx.d.mts.map} +1 -1
- package/dist/{validate-CqsNItbt.mjs → validate-Baqf0slj.mjs} +3 -3
- package/dist/{validate-CqsNItbt.mjs.map → validate-Baqf0slj.mjs.map} +1 -1
- package/dist/{validate-kM8Pjuf7.d.mts → validate-BfQh_C_y.d.mts} +4 -4
- package/dist/{validate-kM8Pjuf7.d.mts.map → validate-BfQh_C_y.d.mts.map} +1 -1
- package/dist/validation-BfEI7tNe.mjs +144 -0
- package/dist/validation-BfEI7tNe.mjs.map +1 -0
- package/dist/version-DoxrVdYf.mjs +7 -0
- package/dist/{version-BnTKdfam.mjs.map → version-DoxrVdYf.mjs.map} +1 -1
- package/dist/zod-generator-CC0xNe_K.mjs +132 -0
- package/dist/zod-generator-CC0xNe_K.mjs.map +1 -0
- package/locals.d.ts +1 -6
- package/package.json +21 -7
- package/src/api/auth-storage.ts +37 -0
- package/src/api/error.ts +6 -0
- package/src/api/errors.ts +8 -0
- package/src/api/handlers/comments.ts +19 -4
- package/src/api/handlers/content.ts +151 -4
- package/src/api/handlers/device-flow.ts +5 -0
- package/src/api/handlers/index.ts +2 -0
- package/src/api/handlers/marketplace.ts +11 -4
- package/src/api/handlers/media.ts +8 -1
- package/src/api/handlers/menus.ts +160 -21
- package/src/api/handlers/oauth-authorization.ts +72 -33
- package/src/api/handlers/redirects.ts +16 -3
- package/src/api/handlers/revision.ts +23 -14
- package/src/api/handlers/sections.ts +8 -1
- package/src/api/handlers/taxonomies.ts +131 -22
- package/src/api/handlers/validation.ts +212 -0
- package/src/api/openapi/document.ts +4 -1
- package/src/api/public-url.ts +54 -5
- package/src/api/route-utils.ts +14 -0
- package/src/api/schemas/comments.ts +2 -2
- package/src/api/schemas/common.ts +1 -1
- package/src/api/schemas/content.ts +17 -0
- package/src/api/schemas/sections.ts +3 -3
- package/src/api/schemas/setup.ts +8 -0
- package/src/api/schemas/users.ts +1 -1
- package/src/api/schemas/widgets.ts +12 -10
- package/src/api/setup-complete.ts +40 -0
- package/src/api/types.ts +5 -1
- package/src/astro/integration/index.ts +30 -2
- package/src/astro/integration/routes.ts +28 -0
- package/src/astro/integration/runtime.ts +49 -1
- package/src/astro/integration/virtual-modules.ts +73 -2
- package/src/astro/integration/vite-config.ts +49 -13
- package/src/astro/middleware/auth.ts +34 -6
- package/src/astro/middleware/redirect.ts +29 -16
- package/src/astro/middleware/request-context.ts +15 -5
- package/src/astro/middleware.ts +41 -10
- package/src/astro/routes/PluginRegistry.tsx +10 -1
- package/src/astro/routes/api/auth/invite/complete.ts +6 -1
- package/src/astro/routes/api/auth/mode.ts +57 -0
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +23 -3
- package/src/astro/routes/api/auth/oauth/[provider].ts +10 -4
- package/src/astro/routes/api/auth/passkey/register/verify.ts +6 -1
- package/src/astro/routes/api/auth/passkey/verify.ts +6 -1
- package/src/astro/routes/api/auth/signup/complete.ts +6 -1
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +34 -12
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +32 -2
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -2
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +8 -4
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id].ts +12 -0
- package/src/astro/routes/api/content/[collection]/index.ts +1 -9
- package/src/astro/routes/api/import/wordpress/execute.ts +3 -1
- package/src/astro/routes/api/import/wordpress/media.ts +2 -7
- package/src/astro/routes/api/import/wordpress/prepare.ts +9 -0
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +3 -1
- package/src/astro/routes/api/manifest.ts +62 -45
- package/src/astro/routes/api/media/[id]/confirm.ts +10 -1
- package/src/astro/routes/api/media/providers/[providerId]/index.ts +12 -3
- package/src/astro/routes/api/openapi.json.ts +27 -10
- package/src/astro/routes/api/redirects/404s/index.ts +10 -4
- package/src/astro/routes/api/redirects/404s/summary.ts +4 -2
- package/src/astro/routes/api/redirects/[id].ts +10 -4
- package/src/astro/routes/api/redirects/index.ts +7 -3
- package/src/astro/routes/api/revisions/[revisionId]/index.ts +1 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +0 -2
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +0 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +2 -2
- package/src/astro/routes/api/schema/collections/index.ts +1 -1
- package/src/astro/routes/api/search/index.ts +10 -2
- package/src/astro/routes/api/sections/[slug].ts +10 -4
- package/src/astro/routes/api/sections/index.ts +7 -3
- package/src/astro/routes/api/settings/email.ts +4 -9
- package/src/astro/routes/api/setup/admin-verify.ts +6 -1
- package/src/astro/routes/api/setup/admin.ts +8 -2
- package/src/astro/routes/api/setup/index.ts +2 -2
- package/src/astro/routes/api/setup/status.ts +3 -1
- package/src/astro/routes/api/snapshot.ts +44 -18
- package/src/astro/routes/api/taxonomies/index.ts +0 -1
- package/src/astro/routes/api/themes/preview.ts +11 -5
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +4 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +4 -1
- package/src/astro/routes/api/widget-areas/[name].ts +4 -1
- package/src/astro/routes/api/widget-areas/index.ts +4 -1
- package/src/astro/types.ts +32 -3
- package/src/auth/allowed-origins.ts +168 -0
- package/src/auth/mode.ts +15 -3
- package/src/auth/passkey-config.ts +35 -13
- package/src/auth/providers/github-admin.tsx +29 -0
- package/src/auth/providers/github.ts +31 -0
- package/src/auth/providers/google-admin.tsx +44 -0
- package/src/auth/providers/google.ts +31 -0
- package/src/auth/types.ts +114 -4
- package/src/bylines/index.ts +37 -88
- package/src/cli/commands/auth.ts +28 -6
- package/src/cli/commands/bundle-utils.ts +11 -2
- package/src/cli/commands/bundle.ts +31 -9
- package/src/cli/commands/content.ts +13 -0
- package/src/cli/commands/login.ts +8 -1
- package/src/cli/commands/publish.ts +24 -0
- package/src/cli/commands/secrets.ts +183 -0
- package/src/cli/credentials.ts +1 -1
- package/src/cli/index.ts +5 -1
- package/src/client/index.ts +4 -4
- package/src/client/transport.ts +17 -7
- package/src/components/Break.astro +2 -2
- package/src/components/EmDashHead.astro +18 -13
- package/src/components/EmDashImage.astro +7 -6
- package/src/components/Embed.astro +1 -1
- package/src/components/Gallery.astro +6 -4
- package/src/components/Image.astro +9 -4
- package/src/components/InlinePortableTextEditor.tsx +106 -19
- package/src/components/LiveSearch.astro +5 -14
- package/src/config/secrets.ts +528 -0
- package/src/database/dialect-helpers.ts +50 -0
- package/src/database/migrations/034_published_at_index.ts +1 -1
- package/src/database/migrations/035_bounded_404_log.ts +56 -39
- package/src/database/migrations/runner.ts +156 -23
- package/src/database/repositories/audit.ts +6 -8
- package/src/database/repositories/byline.ts +6 -8
- package/src/database/repositories/comment.ts +12 -16
- package/src/database/repositories/content.ts +76 -52
- package/src/database/repositories/index.ts +1 -1
- package/src/database/repositories/media.ts +10 -13
- package/src/database/repositories/plugin-storage.ts +4 -6
- package/src/database/repositories/redirect.ts +26 -19
- package/src/database/repositories/taxonomy.ts +40 -3
- package/src/database/repositories/types.ts +57 -8
- package/src/database/repositories/user.ts +6 -8
- package/src/db/libsql.ts +1 -3
- package/src/db/sqlite.ts +2 -5
- package/src/emdash-runtime.ts +388 -247
- package/src/index.ts +14 -1
- package/src/loader.ts +30 -6
- package/src/mcp/server.ts +781 -141
- package/src/media/normalize.ts +1 -1
- package/src/media/url.ts +78 -0
- package/src/page/site-identity.ts +58 -0
- package/src/plugins/adapt-sandbox-entry.ts +22 -10
- package/src/plugins/context.ts +13 -10
- package/src/plugins/define-plugin.ts +40 -12
- package/src/plugins/email-console.ts +10 -3
- package/src/plugins/hooks.ts +34 -19
- package/src/plugins/index.ts +9 -0
- package/src/plugins/manifest-schema.ts +49 -2
- package/src/plugins/types.ts +174 -13
- package/src/preview/urls.ts +23 -3
- package/src/query.ts +149 -6
- package/src/redirects/cache.ts +38 -18
- package/src/request-cache.ts +3 -0
- package/src/schema/registry.ts +97 -5
- package/src/schema/zod-generator.ts +27 -5
- package/src/search/fts-manager.ts +0 -2
- package/src/search/query.ts +111 -26
- package/src/search/types.ts +8 -1
- package/src/sections/index.ts +7 -9
- package/src/seed/apply.ts +2 -0
- package/src/settings/index.ts +80 -6
- package/src/settings/types.ts +23 -1
- package/src/storage/s3.ts +12 -6
- package/src/taxonomies/index.ts +11 -1
- package/src/virtual-modules.d.ts +21 -1
- package/src/widgets/index.ts +1 -1
- package/dist/apply-5uslYdUu.mjs.map +0 -1
- package/dist/byline-C4OVd8b3.mjs.map +0 -1
- package/dist/bylines-hPTW79hw.mjs +0 -157
- package/dist/bylines-hPTW79hw.mjs.map +0 -1
- package/dist/cache-BkKBuIvS.mjs +0 -56
- package/dist/cache-BkKBuIvS.mjs.map +0 -1
- package/dist/chunk-ClPoSABd.mjs +0 -21
- package/dist/content-D7J5y73J.mjs.map +0 -1
- package/dist/dialect-helpers-DhTzaUxP.mjs.map +0 -1
- package/dist/error-CiYn9yDu.mjs.map +0 -1
- package/dist/index-De6_Xv3v.d.mts.map +0 -1
- package/dist/loader-DeiBJEMe.mjs.map +0 -1
- package/dist/manifest-schema-V30qsMft.mjs.map +0 -1
- package/dist/media-DqHVh136.mjs.map +0 -1
- package/dist/mode-CpNnGkPz.mjs.map +0 -1
- package/dist/placeholder-C-fk5hYI.mjs.map +0 -1
- package/dist/query-g4Ug-9j9.mjs.map +0 -1
- package/dist/redirect-CN0Rt9Ob.mjs.map +0 -1
- package/dist/registry-Ci3WxVAr.mjs.map +0 -1
- package/dist/request-cache-DiR961CV.mjs.map +0 -1
- package/dist/runner-BR2xKwhn.d.mts +0 -34
- package/dist/runner-BR2xKwhn.d.mts.map +0 -1
- package/dist/search-B0effn3j.mjs.map +0 -1
- package/dist/taxonomies-K2z0Uhnj.mjs.map +0 -1
- package/dist/types-CMMN0pNg.mjs +0 -31
- package/dist/types-CMMN0pNg.mjs.map +0 -1
- package/dist/types-DgrIP0tF.d.mts.map +0 -1
- package/dist/version-BnTKdfam.mjs +0 -7
package/dist/db/sqlite.mjs
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BetterSqlite3 from "better-sqlite3";
|
|
2
|
+
import { SqliteDialect } from "kysely";
|
|
2
3
|
|
|
3
4
|
//#region src/db/sqlite.ts
|
|
4
5
|
/**
|
|
6
|
+
* SQLite runtime adapter
|
|
7
|
+
*
|
|
8
|
+
* Creates a Kysely dialect for better-sqlite3.
|
|
9
|
+
* Loaded at runtime via virtual module.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
5
12
|
* Create a SQLite dialect from config
|
|
6
13
|
*/
|
|
7
14
|
function createDialect(config) {
|
|
8
|
-
const BetterSqlite3 = __require("better-sqlite3");
|
|
9
|
-
const { SqliteDialect } = __require("kysely");
|
|
10
15
|
const url = config.url;
|
|
11
16
|
return new SqliteDialect({ database: new BetterSqlite3(url.startsWith("file:") ? url.slice(5) : url) });
|
|
12
17
|
}
|
package/dist/db/sqlite.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.mjs","names":[],"sources":["../../src/db/sqlite.ts"],"sourcesContent":["/**\n * SQLite runtime adapter\n *\n * Creates a Kysely dialect for better-sqlite3.\n * Loaded at runtime via virtual module.\n */\n\nimport
|
|
1
|
+
{"version":3,"file":"sqlite.mjs","names":[],"sources":["../../src/db/sqlite.ts"],"sourcesContent":["/**\n * SQLite runtime adapter\n *\n * Creates a Kysely dialect for better-sqlite3.\n * Loaded at runtime via virtual module.\n */\n\nimport BetterSqlite3 from \"better-sqlite3\";\nimport { type Dialect, SqliteDialect } from \"kysely\";\n\nimport type { SqliteConfig } from \"./adapters.js\";\n\n/**\n * Create a SQLite dialect from config\n */\nexport function createDialect(config: SqliteConfig): Dialect {\n\t// Parse URL to get file path\n\tconst url = config.url;\n\tconst filePath = url.startsWith(\"file:\") ? url.slice(5) : url;\n\n\tconst database = new BetterSqlite3(filePath);\n\n\treturn new SqliteDialect({ database });\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,SAAgB,cAAc,QAA+B;CAE5D,MAAM,MAAM,OAAO;AAKnB,QAAO,IAAI,cAAc,EAAE,UAFV,IAAI,cAFJ,IAAI,WAAW,QAAQ,GAAG,IAAI,MAAM,EAAE,GAAG,IAEd,EAEP,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db-errors-
|
|
1
|
+
{"version":3,"file":"db-errors-WRezodiz.mjs","names":[],"sources":["../src/utils/db-errors.ts"],"sourcesContent":["/**\n * Shared detection helpers for database-layer error messages.\n *\n * Different SQL dialects phrase \"table or relation does not exist\" differently:\n *\n * - SQLite / D1: \"no such table: foo\"\n * - PostgreSQL: 'relation \"foo\" does not exist'\n * 'table \"foo\" does not exist'\n * - MySQL (future): \"Table 'db.foo' doesn't exist\"\n *\n * Runtime code paths that short-circuit on missing tables (pre-migration\n * probes, optional feature tables, etc.) should use these helpers rather\n * than hand-rolling string matches per call-site.\n */\n\n/**\n * Extract a lowercase error message from any unknown value, safely.\n */\nfunction messageOf(error: unknown): string {\n\tif (error instanceof Error) return error.message.toLowerCase();\n\tif (typeof error === \"string\") return error.toLowerCase();\n\treturn \"\";\n}\n\n/**\n * Returns true when `error` is a \"table does not exist\" error across the\n * dialects EmDash supports (D1/SQLite and PostgreSQL). Used by runtime\n * probes to treat pre-migration databases as empty without logging a scary\n * warning, while still propagating unrelated errors (permissions, connection\n * loss, syntax issues) to callers.\n */\nexport function isMissingTableError(error: unknown): boolean {\n\tconst message = messageOf(error);\n\tif (!message) return false;\n\n\t// SQLite / D1\n\tif (message.includes(\"no such table\")) return true;\n\n\t// PostgreSQL (and some MySQL variants): \"relation ... does not exist\" /\n\t// \"table ... does not exist\" / \"doesn't exist\".\n\tif (message.includes(\"does not exist\") || message.includes(\"doesn't exist\")) {\n\t\treturn message.includes(\"relation\") || message.includes(\"table\");\n\t}\n\n\treturn false;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,SAAS,UAAU,OAAwB;AAC1C,KAAI,iBAAiB,MAAO,QAAO,MAAM,QAAQ,aAAa;AAC9D,KAAI,OAAO,UAAU,SAAU,QAAO,MAAM,aAAa;AACzD,QAAO;;;;;;;;;AAUR,SAAgB,oBAAoB,OAAyB;CAC5D,MAAM,UAAU,UAAU,MAAM;AAChC,KAAI,CAAC,QAAS,QAAO;AAGrB,KAAI,QAAQ,SAAS,gBAAgB,CAAE,QAAO;AAI9C,KAAI,QAAQ,SAAS,iBAAiB,IAAI,QAAQ,SAAS,gBAAgB,CAC1E,QAAO,QAAQ,SAAS,WAAW,IAAI,QAAQ,SAAS,QAAQ;AAGjE,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-
|
|
1
|
+
{"version":3,"file":"default-D8ksjWhO.mjs","names":[],"sources":["../src/seed/default.ts"],"sourcesContent":["/**\n * Default seed applied when no user seed file exists.\n *\n * Provides the baseline schema every EmDash site needs:\n * posts, pages, categories, and tags.\n */\n\nimport type { SeedFile } from \"./types.js\";\n\nexport const defaultSeed: SeedFile = {\n\tversion: \"1\",\n\tmeta: {\n\t\tname: \"Default\",\n\t\tdescription: \"Posts and pages with categories and tags\",\n\t},\n\tcollections: [\n\t\t{\n\t\t\tslug: \"posts\",\n\t\t\tlabel: \"Posts\",\n\t\t\tlabelSingular: \"Post\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"featured_image\",\n\t\t\t\t\tlabel: \"Featured Image\",\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"excerpt\",\n\t\t\t\t\tlabel: \"Excerpt\",\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tslug: \"pages\",\n\t\t\tlabel: \"Pages\",\n\t\t\tlabelSingular: \"Page\",\n\t\t\tsupports: [\"drafts\", \"revisions\", \"search\"],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tslug: \"title\",\n\t\t\t\t\tlabel: \"Title\",\n\t\t\t\t\ttype: \"string\",\n\t\t\t\t\trequired: true,\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tslug: \"content\",\n\t\t\t\t\tlabel: \"Content\",\n\t\t\t\t\ttype: \"portableText\",\n\t\t\t\t\tsearchable: true,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n\ttaxonomies: [\n\t\t{\n\t\t\tname: \"category\",\n\t\t\tlabel: \"Categories\",\n\t\t\tlabelSingular: \"Category\",\n\t\t\thierarchical: true,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t\t{\n\t\t\tname: \"tag\",\n\t\t\tlabel: \"Tags\",\n\t\t\tlabelSingular: \"Tag\",\n\t\t\thierarchical: false,\n\t\t\tcollections: [\"posts\"],\n\t\t},\n\t],\n};\n"],"mappings":";AASA,MAAa,cAAwB;CACpC,SAAS;CACT,MAAM;EACL,MAAM;EACN,aAAa;EACb;CACD,aAAa,CACZ;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ;GACP;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,UAAU;IACV,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN,YAAY;IACZ;GACD;IACC,MAAM;IACN,OAAO;IACP,MAAM;IACN;GACD;EACD,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,UAAU;GAAC;GAAU;GAAa;GAAS;EAC3C,QAAQ,CACP;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY;GACZ,EACD;GACC,MAAM;GACN,OAAO;GACP,MAAM;GACN,YAAY;GACZ,CACD;EACD,CACD;CACD,YAAY,CACX;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,EACD;EACC,MAAM;EACN,OAAO;EACP,eAAe;EACf,cAAc;EACd,aAAa,CAAC,QAAQ;EACtB,CACD;CACD"}
|
|
@@ -53,6 +53,23 @@ async function tableExists(db, tableName) {
|
|
|
53
53
|
`.execute(db)).rows.length > 0;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
+
* Check if a column exists in the database.
|
|
57
|
+
*/
|
|
58
|
+
async function columnExists(db, tableName, columnName) {
|
|
59
|
+
if (isPostgres(db)) return (await sql`
|
|
60
|
+
SELECT EXISTS(
|
|
61
|
+
SELECT 1 FROM information_schema.columns
|
|
62
|
+
WHERE table_schema = current_schema()
|
|
63
|
+
AND table_name = ${tableName}
|
|
64
|
+
AND column_name = ${columnName}
|
|
65
|
+
) as exists
|
|
66
|
+
`.execute(db)).rows[0]?.exists === true;
|
|
67
|
+
return (await sql`
|
|
68
|
+
SELECT name FROM pragma_table_info(${tableName})
|
|
69
|
+
WHERE name = ${columnName}
|
|
70
|
+
`.execute(db)).rows.length > 0;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
56
73
|
* List tables matching a LIKE pattern.
|
|
57
74
|
*/
|
|
58
75
|
async function listTablesLike(db, pattern) {
|
|
@@ -89,5 +106,5 @@ function jsonExtractExpr(db, column, path) {
|
|
|
89
106
|
}
|
|
90
107
|
|
|
91
108
|
//#endregion
|
|
92
|
-
export {
|
|
93
|
-
//# sourceMappingURL=dialect-helpers-
|
|
109
|
+
export { isPostgres as a, listTablesLike as c, currentTimestampValue as i, tableExists as l, columnExists as n, isSqlite as o, currentTimestamp as r, jsonExtractExpr as s, binaryType as t };
|
|
110
|
+
//# sourceMappingURL=dialect-helpers-BKCvISIQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialect-helpers-BKCvISIQ.mjs","names":[],"sources":["../src/database/dialect-helpers.ts"],"sourcesContent":["/**\n * Dialect-specific SQL helpers\n *\n * Every function takes a Kysely `db` instance and detects the dialect from\n * the adapter class. No module-level state, no globals, no heuristics —\n * the adapter is the source of truth.\n *\n * This is NOT an ORM abstraction — just targeted helpers for the ~15 places\n * that use raw dialect-specific SQL. Most Kysely schema builder code already\n * works cross-dialect.\n */\n\nimport type { ColumnDataType, Kysely, RawBuilder } from \"kysely\";\nimport { sql } from \"kysely\";\n\nimport type { DatabaseDialectType } from \"../db/adapters.js\";\nimport { validateIdentifier, validateJsonFieldName } from \"./validate.js\";\n\nexport type { DatabaseDialectType };\n\n/**\n * Detect dialect type from a Kysely instance via the adapter class name.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function detectDialect(db: Kysely<any>): DatabaseDialectType {\n\tconst name = db.getExecutor().adapter.constructor.name;\n\tif (name === \"PostgresAdapter\") return \"postgres\";\n\treturn \"sqlite\";\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function isSqlite(db: Kysely<any>): boolean {\n\treturn detectDialect(db) === \"sqlite\";\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function isPostgres(db: Kysely<any>): boolean {\n\treturn detectDialect(db) === \"postgres\";\n}\n\n/**\n * Default timestamp expression for column defaults.\n * Wrapped in parens for use in CREATE TABLE ... DEFAULT (...).\n *\n * sqlite: (datetime('now'))\n * postgres: CURRENT_TIMESTAMP\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function currentTimestamp(db: Kysely<any>): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql`CURRENT_TIMESTAMP`;\n\t}\n\treturn sql`(datetime('now'))`;\n}\n\n/**\n * Timestamp expression for use in WHERE clauses and SET expressions.\n * No wrapping parens.\n *\n * sqlite: datetime('now')\n * postgres: CURRENT_TIMESTAMP\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function currentTimestampValue(db: Kysely<any>): RawBuilder<string> {\n\tif (isPostgres(db)) {\n\t\treturn sql`CURRENT_TIMESTAMP`;\n\t}\n\treturn sql`datetime('now')`;\n}\n\n/**\n * Check if a table exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function tableExists(db: Kysely<any>, tableName: string): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM information_schema.tables\n\t\t\t\tWHERE table_schema = 'public' AND table_name = ${tableName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'table' AND name = ${tableName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * Check if an index exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function indexExists(db: Kysely<any>, indexName: string): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM pg_indexes\n\t\t\t\tWHERE schemaname = current_schema() AND indexname = ${indexName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'index' AND name = ${indexName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * Check if a column exists in the database.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function columnExists(\n\tdb: Kysely<any>,\n\ttableName: string,\n\tcolumnName: string,\n): Promise<boolean> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ exists: boolean }>`\n\t\t\tSELECT EXISTS(\n\t\t\t\tSELECT 1 FROM information_schema.columns\n\t\t\t\tWHERE table_schema = current_schema()\n\t\t\t\t\tAND table_name = ${tableName}\n\t\t\t\t\tAND column_name = ${columnName}\n\t\t\t) as exists\n\t\t`.execute(db);\n\t\treturn result.rows[0]?.exists === true;\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM pragma_table_info(${tableName})\n\t\tWHERE name = ${columnName}\n\t`.execute(db);\n\treturn result.rows.length > 0;\n}\n\n/**\n * List tables matching a LIKE pattern.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport async function listTablesLike(db: Kysely<any>, pattern: string): Promise<string[]> {\n\tif (isPostgres(db)) {\n\t\tconst result = await sql<{ table_name: string }>`\n\t\t\tSELECT table_name FROM information_schema.tables\n\t\t\tWHERE table_schema = 'public' AND table_name LIKE ${pattern}\n\t\t`.execute(db);\n\t\treturn result.rows.map((r) => r.table_name);\n\t}\n\n\tconst result = await sql<{ name: string }>`\n\t\tSELECT name FROM sqlite_master\n\t\tWHERE type = 'table' AND name LIKE ${pattern}\n\t`.execute(db);\n\treturn result.rows.map((r) => r.name);\n}\n\n/**\n * Column type for binary data.\n *\n * sqlite: blob\n * postgres: bytea\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function binaryType(db: Kysely<any>): ColumnDataType {\n\tif (isPostgres(db)) {\n\t\treturn \"bytea\";\n\t}\n\treturn \"blob\";\n}\n\n/**\n * SQL expression for extracting a field from a JSON/JSONB column.\n *\n * sqlite: json_extract(column, '$.path')\n * postgres: column->>'path'\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- accepts any Kysely instance\nexport function jsonExtractExpr(db: Kysely<any>, column: string, path: string): string {\n\tvalidateIdentifier(column, \"JSON column name\");\n\tvalidateJsonFieldName(path, \"JSON path\");\n\tif (isPostgres(db)) {\n\t\treturn `${column}->>'${path}'`;\n\t}\n\treturn `json_extract(${column}, '$.${path}')`;\n}\n"],"mappings":";;;;;;;AAwBA,SAAgB,cAAc,IAAsC;AAEnE,KADa,GAAG,aAAa,CAAC,QAAQ,YAAY,SACrC,kBAAmB,QAAO;AACvC,QAAO;;AAIR,SAAgB,SAAS,IAA0B;AAClD,QAAO,cAAc,GAAG,KAAK;;AAI9B,SAAgB,WAAW,IAA0B;AACpD,QAAO,cAAc,GAAG,KAAK;;;;;;;;;AAW9B,SAAgB,iBAAiB,IAAqC;AACrE,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG;AAEX,QAAO,GAAG;;;;;;;;;AAWX,SAAgB,sBAAsB,IAAqC;AAC1E,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG;AAEX,QAAO,GAAG;;;;;AAOX,eAAsB,YAAY,IAAiB,WAAqC;AACvF,KAAI,WAAW,GAAG,CAOjB,SANe,MAAM,GAAwB;;;qDAGM,UAAU;;IAE3D,QAAQ,GAAG,EACC,KAAK,IAAI,WAAW;AAOnC,SAJe,MAAM,GAAqB;;oCAEP,UAAU;GAC3C,QAAQ,GAAG,EACC,KAAK,SAAS;;;;;AA6B7B,eAAsB,aACrB,IACA,WACA,YACmB;AACnB,KAAI,WAAW,GAAG,CASjB,SARe,MAAM,GAAwB;;;;wBAIvB,UAAU;yBACT,WAAW;;IAEhC,QAAQ,GAAG,EACC,KAAK,IAAI,WAAW;AAOnC,SAJe,MAAM,GAAqB;uCACJ,UAAU;iBAChC,WAAW;GACzB,QAAQ,GAAG,EACC,KAAK,SAAS;;;;;AAO7B,eAAsB,eAAe,IAAiB,SAAoC;AACzF,KAAI,WAAW,GAAG,CAKjB,SAJe,MAAM,GAA2B;;uDAEK,QAAQ;IAC3D,QAAQ,GAAG,EACC,KAAK,KAAK,MAAM,EAAE,WAAW;AAO5C,SAJe,MAAM,GAAqB;;uCAEJ,QAAQ;GAC5C,QAAQ,GAAG,EACC,KAAK,KAAK,MAAM,EAAE,KAAK;;;;;;;;AAUtC,SAAgB,WAAW,IAAiC;AAC3D,KAAI,WAAW,GAAG,CACjB,QAAO;AAER,QAAO;;;;;;;;AAUR,SAAgB,gBAAgB,IAAiB,QAAgB,MAAsB;AACtF,oBAAmB,QAAQ,mBAAmB;AAC9C,uBAAsB,MAAM,YAAY;AACxC,KAAI,WAAW,GAAG,CACjB,QAAO,GAAG,OAAO,MAAM,KAAK;AAE7B,QAAO,gBAAgB,OAAO,OAAO,KAAK"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-D_-tqP-I.mjs","names":[],"sources":["../src/api/error.ts"],"sourcesContent":["/**\n * Standardized API error responses.\n *\n * All API routes should use these utilities instead of inline\n * `new Response(JSON.stringify({ error: ... }), ...)` patterns.\n */\n\nimport { InvalidCursorError } from \"../database/repositories/types.js\";\nimport { mapErrorStatus } from \"./errors.js\";\nimport type { ApiResult } from \"./types.js\";\n\n// Re-export everything from errors.ts so existing `import { mapErrorStatus } from \"./error.js\"` still works\nexport * from \"./errors.js\";\n\n/**\n * Standard cache headers for all API responses.\n *\n * Cache-Control: private, no-store -- prevents CDN/proxy caching of authenticated data.\n * no-store already tells caches not to store the response, so Vary is unnecessary.\n */\nconst API_CACHE_HEADERS: HeadersInit = {\n\t\"Cache-Control\": \"private, no-store\",\n};\n\n/**\n * Create a standardized error response.\n *\n * Always returns `{ error: { code, message } }` with correct Content-Type.\n * Use this for all error responses in API routes.\n */\nexport function apiError(code: string, message: string, status: number): Response {\n\treturn Response.json({ error: { code, message } }, { status, headers: API_CACHE_HEADERS });\n}\n\n/**\n * Create a standardized success response.\n *\n * Always returns `{ data: T }` with correct status code.\n * Use this for all success responses in API routes.\n */\nexport function apiSuccess<T>(data: T, status = 200): Response {\n\treturn Response.json({ data }, { status, headers: API_CACHE_HEADERS });\n}\n\n/**\n * Handle an unknown error in a catch block.\n *\n * - Logs the full error server-side\n * - Returns a generic message to the client (never leaks error.message)\n * - Use `fallbackMessage` for the public-facing message\n * - Use `fallbackCode` for the error code\n */\nexport function handleError(\n\terror: unknown,\n\tfallbackMessage: string,\n\tfallbackCode: string,\n): Response {\n\t// Bubble malformed-cursor errors as a structured 400 instead of a\n\t// generic 500.\n\tif (error instanceof InvalidCursorError) {\n\t\treturn apiError(\"INVALID_CURSOR\", error.message, 400);\n\t}\n\tconsole.error(`[${fallbackCode}]`, error);\n\treturn apiError(fallbackCode, fallbackMessage, 500);\n}\n\n/**\n * Standard initialization check.\n *\n * Returns an error response if EmDash is not initialized, or null if OK.\n * Usage: `const err = requireInit(emdash); if (err) return err;`\n */\nexport function requireInit(emdash: unknown): Response | null {\n\tif (!emdash || typeof emdash !== \"object\") {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\treturn null;\n}\n\n/**\n * Standard database check.\n *\n * Returns an error response if the database is not available, or null if OK.\n * Usage: `const err = requireDb(emdash?.db); if (err) return err;`\n */\nexport function requireDb(db: unknown): Response | null {\n\tif (!db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\treturn null;\n}\n\n/**\n * Convert an ApiResult into an HTTP Response.\n *\n * Collapses the handler-to-response boilerplate:\n * - Success: returns `apiSuccess(result.data, successStatus)`\n * - Error: returns `apiError(code, message, mapErrorStatus(code))`\n */\nexport function unwrapResult<T>(result: ApiResult<T>, successStatus = 200): Response {\n\tif (!result.success) {\n\t\treturn apiError(result.error.code, result.error.message, mapErrorStatus(result.error.code));\n\t}\n\treturn apiSuccess(result.data, successStatus);\n}\n"],"mappings":";;;;;;;AAoBA,MAAM,oBAAiC,EACtC,iBAAiB,qBACjB;;;;;;;AAQD,SAAgB,SAAS,MAAc,SAAiB,QAA0B;AACjF,QAAO,SAAS,KAAK,EAAE,OAAO;EAAE;EAAM;EAAS,EAAE,EAAE;EAAE;EAAQ,SAAS;EAAmB,CAAC"}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { _ as MediaValue, m as MediaProviderDescriptor } from "./placeholder-
|
|
2
|
-
import { t as Database } from "./types-
|
|
3
|
-
import { a as ContentSeoInput, c as FindManyOptions, l as FindManyResult, o as CreateContentInput, r as ContentItem, t as BylineSummary
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { d as Storage } from "./types-
|
|
7
|
-
import { t as DatabaseDescriptor } from "./adapters-
|
|
1
|
+
import { _ as MediaValue, m as MediaProviderDescriptor } from "./placeholder-BE4o_2dc.mjs";
|
|
2
|
+
import { t as Database } from "./types-CrtWgIvl.mjs";
|
|
3
|
+
import { a as ContentSeoInput, c as FindManyOptions, d as UpdateContentInput, l as FindManyResult, o as CreateContentInput, r as ContentItem, t as BylineSummary } from "./types-CJsYGpco.mjs";
|
|
4
|
+
import { a as Collection, b as UpdateFieldInput, c as CollectionWithFields, d as CreateFieldInput, i as SiteSettings, p as Field, r as SiteSettingKey, u as CreateCollectionInput, y as UpdateCollectionInput } from "./types-BSyXeCFW.mjs";
|
|
5
|
+
import { $ as ResolvedPlugin, A as PageFragmentContribution, D as MediaItem$1, G as PluginManifest, N as PageMetadataContribution, P as PageMetadataEvent, U as PluginDefinition, Z as RequestMeta, c as CommentBeforeCreateEvent, g as CronEvent, i as CommentAfterCreateEvent, it as StandardPluginDefinition, j as PageFragmentEvent, o as CommentAfterModerateEvent, q as PluginStorageConfig, y as EmailMessage } from "./types-BuBIptGk.mjs";
|
|
6
|
+
import { d as Storage } from "./types-M78DQ1lx.mjs";
|
|
7
|
+
import { t as DatabaseDescriptor } from "./adapters-DoNJiveC.mjs";
|
|
8
8
|
import { Kysely } from "kysely";
|
|
9
9
|
import { z } from "astro/zod";
|
|
10
10
|
import { z as z$1 } from "zod";
|
|
11
11
|
import { PortableTextBlock } from "@emdash-cms/gutenberg-to-portable-text";
|
|
12
12
|
import { Readable } from "node:stream";
|
|
13
13
|
import { LiveLoader } from "astro/loaders";
|
|
14
|
+
import * as react from "react";
|
|
14
15
|
|
|
15
16
|
//#region src/database/connection.d.ts
|
|
16
17
|
interface DatabaseConfig {
|
|
@@ -157,8 +158,14 @@ declare class ContentRepository {
|
|
|
157
158
|
* Syncs the draft revision's data into the content table columns so the
|
|
158
159
|
* content table always reflects the published version.
|
|
159
160
|
* If no draft revision exists, creates one from current data and publishes it.
|
|
161
|
+
*
|
|
162
|
+
* `publishedAt` (optional) overrides the publication timestamp. If omitted,
|
|
163
|
+
* the existing `published_at` is preserved (idempotent re-publish keeps the
|
|
164
|
+
* original date) and falls back to the current time on first publish. Pass
|
|
165
|
+
* an explicit value to backdate a publish (e.g. when migrating content from
|
|
166
|
+
* another CMS).
|
|
160
167
|
*/
|
|
161
|
-
publish(type: string, id: string): Promise<ContentItem>;
|
|
168
|
+
publish(type: string, id: string, publishedAt?: string): Promise<ContentItem>;
|
|
162
169
|
/**
|
|
163
170
|
* Unpublish content
|
|
164
171
|
*
|
|
@@ -483,10 +490,14 @@ interface FieldDescriptor {
|
|
|
483
490
|
kind: string;
|
|
484
491
|
label?: string;
|
|
485
492
|
required?: boolean;
|
|
493
|
+
/**
|
|
494
|
+
* For `select` / `multiSelect`: the list of enum choices.
|
|
495
|
+
* For `json` fields driven by a plugin `widget`: arbitrary widget config.
|
|
496
|
+
*/
|
|
486
497
|
options?: Array<{
|
|
487
498
|
value: string;
|
|
488
499
|
label: string;
|
|
489
|
-
}>;
|
|
500
|
+
}> | Record<string, unknown>;
|
|
490
501
|
}
|
|
491
502
|
/**
|
|
492
503
|
* Discriminated union for handler results.
|
|
@@ -650,7 +661,9 @@ declare function handleContentUnschedule(db: Kysely<Database>, collection: strin
|
|
|
650
661
|
* (syncDataColumns, slug sync, status/revision update) that must
|
|
651
662
|
* be atomic to prevent FTS shadow table corruption on crash.
|
|
652
663
|
*/
|
|
653
|
-
declare function handleContentPublish(db: Kysely<Database>, collection: string, id: string
|
|
664
|
+
declare function handleContentPublish(db: Kysely<Database>, collection: string, id: string, options?: {
|
|
665
|
+
publishedAt?: string;
|
|
666
|
+
}): Promise<ApiResult<ContentResponse>>;
|
|
654
667
|
/**
|
|
655
668
|
* Unpublish content (revert to draft).
|
|
656
669
|
*
|
|
@@ -822,6 +835,23 @@ declare class SchemaRegistry {
|
|
|
822
835
|
* Get a collection with all its fields
|
|
823
836
|
*/
|
|
824
837
|
getCollectionWithFields(slug: string): Promise<CollectionWithFields | null>;
|
|
838
|
+
/**
|
|
839
|
+
* List every collection together with its fields in O(1) query shapes
|
|
840
|
+
* — one for collections, then one batched query for the fields of every
|
|
841
|
+
* returned collection — instead of the N+1 pattern of `listCollections`
|
|
842
|
+
* + per-collection `listFields`. The fields query is chunked at
|
|
843
|
+
* `SQL_BATCH_SIZE` to stay under D1's bound-parameter limit, so on
|
|
844
|
+
* sites with more than `SQL_BATCH_SIZE` collections the field fetch
|
|
845
|
+
* becomes `ceil(collectionCount / SQL_BATCH_SIZE)` queries — still
|
|
846
|
+
* a constant factor, not N+1. Typical sites have well under
|
|
847
|
+
* `SQL_BATCH_SIZE` collections, so this is two queries in practice.
|
|
848
|
+
*
|
|
849
|
+
* Used by the manifest build, which previously paid N+1 round-trips on
|
|
850
|
+
* every admin request. Each round-trip costs ~80–150ms against the D1
|
|
851
|
+
* primary on a busy link, so a 10-collection site spent ~1 s rebuilding
|
|
852
|
+
* a manifest that is now built fresh per admin request (no cache).
|
|
853
|
+
*/
|
|
854
|
+
listCollectionsWithFields(): Promise<CollectionWithFields[]>;
|
|
825
855
|
/**
|
|
826
856
|
* Create a new collection
|
|
827
857
|
*/
|
|
@@ -2017,7 +2047,7 @@ declare function parseWxrString(xml: string): Promise<WxrData>;
|
|
|
2017
2047
|
* export default definePlugin({
|
|
2018
2048
|
* id: "my-plugin",
|
|
2019
2049
|
* version: "1.0.0",
|
|
2020
|
-
* capabilities: ["read
|
|
2050
|
+
* capabilities: ["content:read"],
|
|
2021
2051
|
* hooks: {
|
|
2022
2052
|
* "content:beforeSave": async (event, ctx) => {
|
|
2023
2053
|
* ctx.log.info("Saving content", { collection: event.collection });
|
|
@@ -2042,7 +2072,13 @@ declare function definePlugin(definition: StandardPluginDefinition): StandardPlu
|
|
|
2042
2072
|
* Auth Provider Types
|
|
2043
2073
|
*
|
|
2044
2074
|
* Defines the interfaces for pluggable authentication providers.
|
|
2045
|
-
*
|
|
2075
|
+
*
|
|
2076
|
+
* Two systems coexist:
|
|
2077
|
+
* - `AuthDescriptor` — transparent auth (Cloudflare Access) that authenticates
|
|
2078
|
+
* every request via headers/cookies. No login UI needed.
|
|
2079
|
+
* - `AuthProviderDescriptor` — pluggable login methods (GitHub, Google,
|
|
2080
|
+
* AT Protocol, etc.) that appear as options on the login page and setup
|
|
2081
|
+
* wizard. Passkey is built-in; providers are additive.
|
|
2046
2082
|
*/
|
|
2047
2083
|
/**
|
|
2048
2084
|
* Result of authenticating a request via an external auth provider
|
|
@@ -2060,10 +2096,10 @@ interface AuthResult {
|
|
|
2060
2096
|
metadata?: Record<string, unknown>;
|
|
2061
2097
|
}
|
|
2062
2098
|
/**
|
|
2063
|
-
* Auth descriptor
|
|
2099
|
+
* Auth descriptor — transparent auth providers (e.g., Cloudflare Access).
|
|
2064
2100
|
*
|
|
2065
|
-
*
|
|
2066
|
-
*
|
|
2101
|
+
* These authenticate every request via headers/cookies. No login UI needed.
|
|
2102
|
+
* The module's `authenticate()` function is called by middleware on each request.
|
|
2067
2103
|
*/
|
|
2068
2104
|
interface AuthDescriptor {
|
|
2069
2105
|
/**
|
|
@@ -2098,6 +2134,97 @@ interface AuthProviderModule {
|
|
|
2098
2134
|
*/
|
|
2099
2135
|
authenticate(request: Request, config: unknown): Promise<AuthResult>;
|
|
2100
2136
|
}
|
|
2137
|
+
/**
|
|
2138
|
+
* Descriptor for a pluggable auth provider.
|
|
2139
|
+
*
|
|
2140
|
+
* Auth providers appear as login options on the login page and setup wizard.
|
|
2141
|
+
* They coexist with passkey (which is built-in) and with each other.
|
|
2142
|
+
* Any provider can be used to create the initial admin account.
|
|
2143
|
+
*
|
|
2144
|
+
* @example
|
|
2145
|
+
* ```ts
|
|
2146
|
+
* // astro.config.ts
|
|
2147
|
+
* import { atproto } from "@emdash-cms/auth-atproto";
|
|
2148
|
+
*
|
|
2149
|
+
* emdash({
|
|
2150
|
+
* authProviders: [atproto(), github(), google()],
|
|
2151
|
+
* })
|
|
2152
|
+
* ```
|
|
2153
|
+
*/
|
|
2154
|
+
interface AuthProviderDescriptor {
|
|
2155
|
+
/** Unique provider ID (e.g., "github", "atproto") */
|
|
2156
|
+
id: string;
|
|
2157
|
+
/** Human-readable label for UI (e.g., "GitHub", "AT Protocol") */
|
|
2158
|
+
label: string;
|
|
2159
|
+
/** Provider-specific config (JSON-serializable) */
|
|
2160
|
+
config?: unknown;
|
|
2161
|
+
/**
|
|
2162
|
+
* Module exporting React components for the admin UI.
|
|
2163
|
+
* Statically imported at build time via virtual module.
|
|
2164
|
+
*
|
|
2165
|
+
* The module should export components matching `AuthProviderAdminExports`.
|
|
2166
|
+
*/
|
|
2167
|
+
adminEntry?: string;
|
|
2168
|
+
/**
|
|
2169
|
+
* Astro route handlers this provider needs injected at build time.
|
|
2170
|
+
* Used for login initiation, OAuth callbacks, well-known endpoints, etc.
|
|
2171
|
+
*/
|
|
2172
|
+
routes?: AuthRouteDescriptor[];
|
|
2173
|
+
/**
|
|
2174
|
+
* URL prefixes/paths that should bypass auth middleware.
|
|
2175
|
+
* Added to the public routes set so login/callback endpoints work
|
|
2176
|
+
* for unauthenticated users.
|
|
2177
|
+
*/
|
|
2178
|
+
publicRoutes?: string[];
|
|
2179
|
+
/**
|
|
2180
|
+
* Storage collections for persistent auth state (e.g., OAuth sessions).
|
|
2181
|
+
* Same format as plugin storage — collections are stored in the shared
|
|
2182
|
+
* `_plugin_storage` table namespaced under `auth:<providerId>`.
|
|
2183
|
+
*
|
|
2184
|
+
* Access via `getAuthProviderStorage()` from `emdash/api/route-utils`.
|
|
2185
|
+
*/
|
|
2186
|
+
storage?: Record<string, {
|
|
2187
|
+
indexes?: Array<string | string[]>;
|
|
2188
|
+
uniqueIndexes?: Array<string | string[]>;
|
|
2189
|
+
}>;
|
|
2190
|
+
}
|
|
2191
|
+
/**
|
|
2192
|
+
* A route that an auth provider needs injected into the Astro app.
|
|
2193
|
+
*/
|
|
2194
|
+
interface AuthRouteDescriptor {
|
|
2195
|
+
/** URL pattern (e.g., "/_emdash/api/auth/atproto/login") */
|
|
2196
|
+
pattern: string;
|
|
2197
|
+
/** Module specifier for the Astro route handler */
|
|
2198
|
+
entrypoint: string;
|
|
2199
|
+
}
|
|
2200
|
+
/**
|
|
2201
|
+
* Expected exports from an auth provider's `adminEntry` module.
|
|
2202
|
+
*
|
|
2203
|
+
* All exports are optional. Providers export whichever components
|
|
2204
|
+
* make sense for their auth flow.
|
|
2205
|
+
*/
|
|
2206
|
+
interface AuthProviderAdminExports {
|
|
2207
|
+
/**
|
|
2208
|
+
* Compact button for the login page (icon + label).
|
|
2209
|
+
* Used for providers with a simple redirect flow (GitHub, Google).
|
|
2210
|
+
* Rendered in the "Or continue with" section.
|
|
2211
|
+
*/
|
|
2212
|
+
LoginButton?: react.ComponentType;
|
|
2213
|
+
/**
|
|
2214
|
+
* Full login form for providers that need custom input.
|
|
2215
|
+
* Used for providers like AT Protocol that need a handle field.
|
|
2216
|
+
* Rendered as an expandable section on the login page.
|
|
2217
|
+
*/
|
|
2218
|
+
LoginForm?: react.ComponentType;
|
|
2219
|
+
/**
|
|
2220
|
+
* Setup wizard step for creating the admin account via this provider.
|
|
2221
|
+
* When present, this provider appears as an option in the setup wizard's
|
|
2222
|
+
* "Create admin account" step.
|
|
2223
|
+
*/
|
|
2224
|
+
SetupStep?: react.ComponentType<{
|
|
2225
|
+
onComplete: () => void;
|
|
2226
|
+
}>;
|
|
2227
|
+
}
|
|
2101
2228
|
/**
|
|
2102
2229
|
* Configuration options common to external auth providers
|
|
2103
2230
|
*/
|
|
@@ -2375,6 +2502,23 @@ interface EmDashConfig {
|
|
|
2375
2502
|
* ```
|
|
2376
2503
|
*/
|
|
2377
2504
|
auth?: AuthDescriptor;
|
|
2505
|
+
/**
|
|
2506
|
+
* Pluggable auth providers (login methods on the login page).
|
|
2507
|
+
*
|
|
2508
|
+
* Auth providers appear as options alongside passkey on the login page
|
|
2509
|
+
* and setup wizard. Any provider can be used to create the initial
|
|
2510
|
+
* admin account. Passkey is built-in; providers listed here are additive.
|
|
2511
|
+
*
|
|
2512
|
+
* @example
|
|
2513
|
+
* ```ts
|
|
2514
|
+
* import { atproto } from "@emdash-cms/auth-atproto";
|
|
2515
|
+
*
|
|
2516
|
+
* emdash({
|
|
2517
|
+
* authProviders: [atproto()],
|
|
2518
|
+
* })
|
|
2519
|
+
* ```
|
|
2520
|
+
*/
|
|
2521
|
+
authProviders?: AuthProviderDescriptor[];
|
|
2378
2522
|
/**
|
|
2379
2523
|
* MCP (Model Context Protocol) server endpoint.
|
|
2380
2524
|
*
|
|
@@ -2434,29 +2578,35 @@ interface EmDashConfig {
|
|
|
2434
2578
|
*/
|
|
2435
2579
|
siteUrl?: string;
|
|
2436
2580
|
/**
|
|
2437
|
-
*
|
|
2438
|
-
* proxy. The first header in this list that is present on the request
|
|
2439
|
-
* wins. Applies to rate limiting for auth endpoints and comment
|
|
2440
|
-
* submission.
|
|
2581
|
+
* Additional origins accepted by passkey verification.
|
|
2441
2582
|
*
|
|
2442
|
-
*
|
|
2443
|
-
*
|
|
2444
|
-
*
|
|
2445
|
-
*
|
|
2583
|
+
* When the same EmDash deployment is reachable under several hostnames sharing
|
|
2584
|
+
* a registrable parent (e.g. `https://example.com` plus
|
|
2585
|
+
* `https://preview.example.com`), the canonical `siteUrl` defines the `rpId`
|
|
2586
|
+
* and the entries here are the *additional* origins from which assertions
|
|
2587
|
+
* are accepted. Each entry must be the same hostname as `siteUrl` or a
|
|
2588
|
+
* subdomain of it — WebAuthn requires `rpId` to be a registrable suffix of
|
|
2589
|
+
* every origin.
|
|
2446
2590
|
*
|
|
2447
|
-
*
|
|
2448
|
-
*
|
|
2449
|
-
*
|
|
2591
|
+
* Merged at runtime with the `EMDASH_ALLOWED_ORIGINS` env var (comma-separated).
|
|
2592
|
+
* Validation:
|
|
2593
|
+
* - Config-declared entries are shape-checked at Astro startup.
|
|
2594
|
+
* - Subdomain relationship to `siteUrl` is checked at startup when
|
|
2595
|
+
* `siteUrl` is also config-declared, otherwise at first passkey
|
|
2596
|
+
* verification (since `siteUrl` may come from `EMDASH_SITE_URL`).
|
|
2450
2597
|
*
|
|
2451
|
-
*
|
|
2452
|
-
*
|
|
2453
|
-
* preserve the default: IP is resolved only when the request came
|
|
2454
|
-
* through Cloudflare's edge.
|
|
2598
|
+
* Mismatches throw with a source-attributed message naming
|
|
2599
|
+
* `config.allowedOrigins` or `EMDASH_ALLOWED_ORIGINS`.
|
|
2455
2600
|
*
|
|
2456
|
-
*
|
|
2457
|
-
*
|
|
2458
|
-
*
|
|
2601
|
+
* @example
|
|
2602
|
+
* ```ts
|
|
2603
|
+
* emdash({
|
|
2604
|
+
* siteUrl: "https://example.com",
|
|
2605
|
+
* allowedOrigins: ["https://preview.example.com"],
|
|
2606
|
+
* })
|
|
2607
|
+
* ```
|
|
2459
2608
|
*/
|
|
2609
|
+
allowedOrigins?: string[];
|
|
2460
2610
|
trustedProxyHeaders?: string[];
|
|
2461
2611
|
/**
|
|
2462
2612
|
* Enable playground mode for ephemeral "try EmDash" sites.
|
|
@@ -2605,10 +2755,20 @@ declare const pluginManifestSchema: z$1.ZodObject<{
|
|
|
2605
2755
|
"read:media": "read:media";
|
|
2606
2756
|
"write:media": "write:media";
|
|
2607
2757
|
"read:users": "read:users";
|
|
2608
|
-
"email:send": "email:send";
|
|
2609
2758
|
"email:provide": "email:provide";
|
|
2610
2759
|
"email:intercept": "email:intercept";
|
|
2611
2760
|
"page:inject": "page:inject";
|
|
2761
|
+
"network:request": "network:request";
|
|
2762
|
+
"network:request:unrestricted": "network:request:unrestricted";
|
|
2763
|
+
"content:read": "content:read";
|
|
2764
|
+
"content:write": "content:write";
|
|
2765
|
+
"media:read": "media:read";
|
|
2766
|
+
"media:write": "media:write";
|
|
2767
|
+
"users:read": "users:read";
|
|
2768
|
+
"email:send": "email:send";
|
|
2769
|
+
"hooks.email-transport:register": "hooks.email-transport:register";
|
|
2770
|
+
"hooks.email-events:register": "hooks.email-events:register";
|
|
2771
|
+
"hooks.page-fragments:register": "hooks.page-fragments:register";
|
|
2612
2772
|
}>>;
|
|
2613
2773
|
allowedHosts: z$1.ZodArray<z$1.ZodString>;
|
|
2614
2774
|
storage: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
@@ -2704,6 +2864,18 @@ declare const pluginManifestSchema: z$1.ZodObject<{
|
|
|
2704
2864
|
type: z$1.ZodLiteral<"secret">;
|
|
2705
2865
|
label: z$1.ZodString;
|
|
2706
2866
|
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2867
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2868
|
+
type: z$1.ZodLiteral<"url">;
|
|
2869
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2870
|
+
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
2871
|
+
label: z$1.ZodString;
|
|
2872
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2873
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2874
|
+
type: z$1.ZodLiteral<"email">;
|
|
2875
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2876
|
+
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
2877
|
+
label: z$1.ZodString;
|
|
2878
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2707
2879
|
}, z$1.core.$strip>], "type">>>;
|
|
2708
2880
|
pages: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
2709
2881
|
path: z$1.ZodString;
|
|
@@ -2726,14 +2898,14 @@ declare const pluginManifestSchema: z$1.ZodObject<{
|
|
|
2726
2898
|
string: "string";
|
|
2727
2899
|
number: "number";
|
|
2728
2900
|
boolean: "boolean";
|
|
2901
|
+
file: "file";
|
|
2902
|
+
select: "select";
|
|
2729
2903
|
text: "text";
|
|
2730
2904
|
integer: "integer";
|
|
2731
2905
|
datetime: "datetime";
|
|
2732
|
-
select: "select";
|
|
2733
2906
|
multiSelect: "multiSelect";
|
|
2734
2907
|
portableText: "portableText";
|
|
2735
2908
|
image: "image";
|
|
2736
|
-
file: "file";
|
|
2737
2909
|
reference: "reference";
|
|
2738
2910
|
json: "json";
|
|
2739
2911
|
slug: "slug";
|
|
@@ -3010,6 +3182,15 @@ declare class HookPipeline {
|
|
|
3010
3182
|
getExclusiveHookProviders(hookName: string): Array<{
|
|
3011
3183
|
pluginId: string;
|
|
3012
3184
|
}>;
|
|
3185
|
+
/**
|
|
3186
|
+
* Get all plugins that registered a non-exclusive handler for a given
|
|
3187
|
+
* hook (e.g. `email:beforeSend`, `email:afterSend`), preserving priority
|
|
3188
|
+
* order. Partitions with `getExclusiveHookProviders()`, which returns
|
|
3189
|
+
* plugins whose registration is marked `exclusive: true`.
|
|
3190
|
+
*/
|
|
3191
|
+
getHookProviders(hookName: string): Array<{
|
|
3192
|
+
pluginId: string;
|
|
3193
|
+
}>;
|
|
3013
3194
|
/**
|
|
3014
3195
|
* Invoke an exclusive hook — dispatch only to the selected provider.
|
|
3015
3196
|
* Returns null if no provider is selected or if the selected hook
|
|
@@ -3973,8 +4154,18 @@ interface GetPreviewUrlOptions {
|
|
|
3973
4154
|
expiresIn?: string | number;
|
|
3974
4155
|
/** Base URL of the site. If not provided, returns a relative URL. */
|
|
3975
4156
|
baseUrl?: string;
|
|
3976
|
-
/**
|
|
4157
|
+
/**
|
|
4158
|
+
* Custom path pattern. Supports `{collection}`, `{id}` and `{locale}`
|
|
4159
|
+
* placeholders. Default: `"/{collection}/{id}"`.
|
|
4160
|
+
*/
|
|
3977
4161
|
pathPattern?: string;
|
|
4162
|
+
/**
|
|
4163
|
+
* Locale segment substituted for the `{locale}` placeholder in `pathPattern`.
|
|
4164
|
+
* Pass an empty string to omit the locale prefix (e.g. for the default locale
|
|
4165
|
+
* when `prefixDefaultLocale` is `false`); adjacent slashes left by an empty
|
|
4166
|
+
* value are collapsed and any trailing slash is trimmed.
|
|
4167
|
+
*/
|
|
4168
|
+
locale?: string;
|
|
3978
4169
|
}
|
|
3979
4170
|
/**
|
|
3980
4171
|
* Generate a preview URL for content
|
|
@@ -4375,6 +4566,11 @@ declare function invalidateTermCache(): void;
|
|
|
4375
4566
|
declare function getTaxonomyDefs(): Promise<TaxonomyDef[]>;
|
|
4376
4567
|
/**
|
|
4377
4568
|
* Get a single taxonomy definition by name
|
|
4569
|
+
*
|
|
4570
|
+
* If `getTaxonomyDefs()` has already loaded the full list in this request
|
|
4571
|
+
* (which happens during entry-term hydration on every page that renders a
|
|
4572
|
+
* collection), find the matching def in memory rather than running a
|
|
4573
|
+
* second `WHERE name=?` query against `_emdash_taxonomy_defs`.
|
|
4378
4574
|
*/
|
|
4379
4575
|
declare function getTaxonomyDef(name: string): Promise<TaxonomyDef | null>;
|
|
4380
4576
|
/**
|
|
@@ -4547,7 +4743,14 @@ interface SearchResult {
|
|
|
4547
4743
|
locale: string;
|
|
4548
4744
|
/** Entry title (if available) */
|
|
4549
4745
|
title?: string;
|
|
4550
|
-
/**
|
|
4746
|
+
/**
|
|
4747
|
+
* Highlighted snippet showing match context.
|
|
4748
|
+
*
|
|
4749
|
+
* Sanitized server-side to be safe for `set:html` / `innerHTML`:
|
|
4750
|
+
* all HTML metacharacters in the source text are escaped, and
|
|
4751
|
+
* matched terms are wrapped in literal `<mark>...</mark>` tags
|
|
4752
|
+
* (the only HTML the snippet is allowed to contain).
|
|
4753
|
+
*/
|
|
4551
4754
|
snippet?: string;
|
|
4552
4755
|
/** Relevance score (higher = more relevant) */
|
|
4553
4756
|
score: number;
|
|
@@ -4808,5 +5011,5 @@ declare function extractPlainText(blocks: PortableTextBlock$1[] | string | null
|
|
|
4808
5011
|
*/
|
|
4809
5012
|
declare function extractSearchableFields(entry: Record<string, unknown>, fields: string[]): Record<string, string>;
|
|
4810
5013
|
//#endregion
|
|
4811
|
-
export { UpdateMenuInput as $,
|
|
4812
|
-
//# sourceMappingURL=index-
|
|
5014
|
+
export { UpdateMenuInput as $, EntryResult as $n, handleMediaList as $r, SuggestedAction as $t, getEntriesByTerm as A, ListResponse as Ai, WxrData as An, ProseMirrorNode as Ar, probeUrl as At, TaxonomyTerm as B, CreateMediaInput as Bi, getDb as Bn, CreateSectionInput as Br, ImportContext as Bt, ReorderWidgetsInput as C, handleContentUnpublish as Ci, AuthResult as Cn, PortableTextLinkMark as Cr, parseWxrDate as Ct, WidgetComponentDef as D, ContentListResponse as Di, WxrAttachment as Dn, PortableTextUnknownBlock as Dr, getFileSources as Dt, WidgetArea as E, ApiContext as Ei, definePlugin as En, PortableTextTextBlock as Er, getAllSources as Et, getTerm as F, FieldDefinition as Fi, parseWxrString as Fn, SandboxRunnerFactory as Fr, FetchOptions as Ft, getMenu as G, EmDashDatabaseError as Gi, WaitUntilFn as Gn, getCollectionInfo as Gr, OAuthInput as Gt, UpdateTermInput as H, MediaRepository as Hi, getFallbackChain as Hn, Section as Hr, ImportResult as Ht, getTermsForEntries as I, FieldUIHints as Ii, CollectionFilter as In, SandboxedPlugin as Ir, FieldCompatibility as It, CreateMenuItemInput as J, CollectionFilter$1 as Jn, MediaListResponse as Jr, ProbeResult as Jt, getMenus as K, after as Kn, SchemaError as Kr, PostTypeAnalysis as Kt, invalidateTermCache as L, FileValue as Li, EntryData as Ln, SerializedRequest as Lr, FileInput as Lt, getTaxonomyDef as M, portableText as Mi, WxrSite as Mn, SandboxEmailSendCallback as Mr, importReusableBlocksAsSections as Mt, getTaxonomyDefs as N, reference as Ni, WxrTag as Nn, SandboxOptions as Nr, AttachmentInfo as Nt, WidgetType as O, ContentResponse as Oi, WxrAuthor as On, ProseMirrorDocument as Or, getSource as Ot, getTaxonomyTerms as P, image as Pi, parseWxr as Pn, SandboxRunner as Pr, CollectionSchemaStatus as Pt, ReorderMenuItemsInput as Q, EmDashCollections as Qn, handleMediaGet as Qr, SourceProbeResult as Qt, CreateTermInput as R, ImageValue as Ri, EntryFilter as Rn, getSection as Rr, ImportAnalysis as Rt, PropDef as S, handleContentTranslations as Si, AuthProviderModule as Sn, PortableTextImageBlock as Sr, wordpressRestSource as St, Widget as T, handleContentUpdate as Ti, ExternalAuthConfig as Tn, PortableTextSpan as Tr, clearSources as Tt, getByline as U, ContentRepository as Ui, getI18nConfig as Un, SectionSource as Ur, ImportSource as Ut, TaxonomyTermRow as V, MediaItem as Vi, I18nConfig as Vn, GetSectionsOptions as Vr, ImportFieldDef as Vt, getBylineBySlug as W, DatabaseConfig as Wi, isI18nEnabled as Wn, UpdateSectionInput as Wr, NormalizedItem as Wt, MenuItem as X, ContentEntry as Xn, handleMediaCreate as Xr, SourceCapabilities as Xt, Menu as Y, CollectionResult as Yn, MediaResponse as Yr, SourceAuth as Yt, MenuItemType as Z, EditFieldMeta as Zn, handleMediaDelete as Zr, SourceInput as Zt, getWidgetArea as _, handleContentListTrashed as _i, S3StorageConfig as _n, computeContentHash as _r, VerifyPreviewTokenOptions as _t, search as a, handleRevisionRestore as ai, createPluginManager as an, getEmDashCollection as ar, getPluginSetting as at, CreateWidgetAreaInput as b, handleContentRestore as bi, AuthProviderAdminExports as bn, prosemirrorToPortableText as br, parseContentId as bt, FTSManager as c, handleContentCountScheduled as ci, HookPipeline as cn, resolveEmDashPath as cr, getSiteSettings as ct, SearchOptions as d, handleContentDelete as di, ValidatedPluginManifest as dn, FieldAnnotation as dr, isPreviewRequest as dt, handleMediaUpdate as ei, UrlInput as en, InferCollectionData as er, UpdateMenuItemInput as et, SearchResponse as f, handleContentDiscardDraft as fi, pluginManifestSchema as fn, createEditable as fr, GetPreviewUrlOptions as ft, Suggestion as g, handleContentList as gi, LocalStorageConfig as gn, sanitizeHref as gr, PreviewTokenPayload as gt, SuggestOptions as h, handleContentGetIncludingTrashed as hi, getStoredConfig as hn, isSafeHref as hr, GeneratePreviewTokenOptions as ht, getSuggestions as i, handleRevisionList as ii, PluginManager as in, getEditMeta as ir, getComments as it, getEntryTerms as j, ManifestResponse as ji, WxrPost as jn, SandboxEmailMessage as jr, registerSource as jt, getAllTermsForEntries as k, FieldDescriptor as ki, WxrCategory as kn, ProseMirrorMark as kr, getUrlSources as kt, CollectionSearchOptions as l, handleContentCountTrashed as li, HookResult as ln, CMSAnnotation as lr, setSiteSettings as lt, SearchStats as m, handleContentGet as mi, PluginDescriptor as mn, decodeSlug as mr, getPreviewUrl as mt, extractSearchableFields as n, RevisionResponse as ni, SandboxNotAvailableError as nn, TranslationSummary as nr, GetCommentsResult as nt, searchCollection as o, generateManifest as oi, PluginRouteError as on, getEmDashEntry as or, getPluginSettings as ot, SearchResult as p, handleContentDuplicate as pi, EmDashConfig as pn, createNoop as pr, buildPreviewUrl as pt, CreateMenuInput as q, CacheHint as qn, SchemaRegistry as qr, PostTypeMapping as qt, getSearchStats as r, handleRevisionGet as ri, createNoopSandboxRunner as rn, TranslationsResult as rr, getCommentCount as rt, searchWithDb as s, handleContentCompare as si, EmailPipeline as sn, getTranslations as sr, getSiteSetting as st, extractPlainText as t, RevisionListResponse as ti, NoopSandboxRunner as tn, ResolvePathResult as tr, GetCommentsOptions as tt, SearchConfig as u, handleContentCreate as ui, createHookPipeline as un, EditProxy as ur, getPreviewToken as ut, getWidgetAreas as v, handleContentPermanentDelete as vi, StorageDescriptor as vn, hashString as vr, VerifyPreviewTokenResult as vt, UpdateWidgetInput as w, handleContentUnschedule as wi, AuthRouteDescriptor as wn, PortableTextMarkDef as wr, wxrSource as wt, CreateWidgetInput as x, handleContentSchedule as xi, AuthProviderDescriptor as xn, PortableTextCodeBlock as xr, verifyPreviewToken as xt, getWidgetComponents as y, handleContentPublish as yi, AuthDescriptor as yn, portableTextToProsemirror as yr, generatePreviewToken as yt, TaxonomyDef as z, PortableTextBlock$2 as zi, emdashLoader as zn, getSections as zr, ImportConfig as zt };
|
|
5015
|
+
//# sourceMappingURL=index-BFRaVcD6.d.mts.map
|