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
|
@@ -1,31 +1,36 @@
|
|
|
1
|
+
import { r as runMigrations } from "../runner-C7ADox5q.mjs";
|
|
1
2
|
import { getRequestContext, runWithContext } from "../request-context.mjs";
|
|
2
3
|
import { createRecorder, flushRecorder, isInstrumentationEnabled, kyselyLogOption } from "../database/instrumentation.mjs";
|
|
3
4
|
import "../connection-2igzM-AT.mjs";
|
|
4
5
|
import { t as validateIdentifier } from "../validate-VPnKoIzW.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import "../
|
|
10
|
-
import "../
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import "../redirect-
|
|
14
|
-
import "../byline-
|
|
15
|
-
import { n as normalizeMediaValue } from "../placeholder-
|
|
16
|
-
import { i as setI18nConfig } from "../config-
|
|
17
|
-
import {
|
|
18
|
-
import { n as
|
|
19
|
-
import "../
|
|
20
|
-
import "../
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
import "../
|
|
24
|
-
import "../
|
|
25
|
-
import "../
|
|
6
|
+
import { o as isSqlite } from "../dialect-helpers-BKCvISIQ.mjs";
|
|
7
|
+
import { At as handleContentTranslations, Ct as handleContentGetIncludingTrashed, Dt as handleContentPublish, Et as handleContentPermanentDelete, G as sanitizeHeadersForSandbox, H as resolveExclusiveHooks, I as PluginRouteRegistry, K as getTrustedProxyHeaders, L as DEV_CONSOLE_EMAIL_PLUGIN_ID, Mt as handleContentUnschedule, Nt as handleContentUpdate, Ot as handleContentRestore, Pt as validateRev, R as devConsoleEmailDeliver, St as handleContentGet, Tt as handleContentListTrashed, U as CronExecutor, V as createHookPipeline, W as extractRequestMeta, X as after, _t as handleContentCountTrashed, bt as handleContentDiscardDraft, ct as handleMediaGet, dt as handleRevisionGet, ft as handleRevisionList, gt as handleContentCountScheduled, ht as handleContentCompare, it as PluginStateRepository, jt as handleContentUnpublish, kt as handleContentSchedule, lt as handleMediaList, ot as handleMediaCreate, pt as handleRevisionRestore, q as definePlugin, st as handleMediaDelete, tt as loadBundleFromR2, ut as handleMediaUpdate, vt as handleContentCreate, wt as handleContentList, xt as handleContentDuplicate, yt as handleContentDelete, z as EmailPipeline } from "../search-dOGEccMa.mjs";
|
|
8
|
+
import { r as RevisionRepository } from "../content-8lOYF0pr.mjs";
|
|
9
|
+
import "../base64-BRICGH2l.mjs";
|
|
10
|
+
import "../types-CRxNbK-Z.mjs";
|
|
11
|
+
import { t as MediaRepository } from "../media-BW32b4gi.mjs";
|
|
12
|
+
import "../apply-BzltprvY.mjs";
|
|
13
|
+
import { t as OptionsRepository } from "../options-BVp3UsTS.mjs";
|
|
14
|
+
import "../redirect-BhUBKRc1.mjs";
|
|
15
|
+
import "../byline-BSaNL1w7.mjs";
|
|
16
|
+
import { n as normalizeMediaValue } from "../placeholder-CIJejMlK.mjs";
|
|
17
|
+
import { i as setI18nConfig } from "../config-BI0V3ICQ.mjs";
|
|
18
|
+
import { r as hashString } from "../zod-generator-CC0xNe_K.mjs";
|
|
19
|
+
import { i as FTSManager, n as SchemaRegistry } from "../registry-Dw70ChxB.mjs";
|
|
20
|
+
import { r as getDb } from "../loader-CKLbBnhK.mjs";
|
|
21
|
+
import { n as requestCached } from "../request-cache-B-bmkipQ.mjs";
|
|
22
|
+
import "../taxonomies-ZlRtD6AG.mjs";
|
|
23
|
+
import { r as normalizeManifestRoute } from "../manifest-schema-DqWNC3lM.mjs";
|
|
24
|
+
import "../types-4fVtCIm0.mjs";
|
|
25
|
+
import "../error-D_-tqP-I.mjs";
|
|
26
|
+
import { a as invalidateUrlPatternCache } from "../query-Cg9ZKRQ0.mjs";
|
|
27
|
+
import "../tokens-D7zMmWi2.mjs";
|
|
28
|
+
import "../bylines-CvJ3PYz2.mjs";
|
|
29
|
+
import "../load-DDqMMvZL.mjs";
|
|
26
30
|
import "../index.mjs";
|
|
27
|
-
import { n as VERSION, t as COMMIT } from "../version-
|
|
28
|
-
import { t as getAuthMode } from "../mode-
|
|
31
|
+
import { n as VERSION, t as COMMIT } from "../version-DoxrVdYf.mjs";
|
|
32
|
+
import { t as getAuthMode } from "../mode-ier8jbBk.mjs";
|
|
33
|
+
import { a as validateEncryptionKeyAtStartup } from "../secrets-CW3reAnU.mjs";
|
|
29
34
|
import { Kysely, sql } from "kysely";
|
|
30
35
|
import { defineMiddleware } from "astro:middleware";
|
|
31
36
|
import virtualConfig from "virtual:emdash/config";
|
|
@@ -281,6 +286,19 @@ var PiggybackScheduler = class {
|
|
|
281
286
|
//#endregion
|
|
282
287
|
//#region src/emdash-runtime.ts
|
|
283
288
|
const LEADING_SLASH_PATTERN = /^\//;
|
|
289
|
+
/**
|
|
290
|
+
* Parse a JSON column expected to contain an array of strings.
|
|
291
|
+
*
|
|
292
|
+
* Throws on malformed JSON rather than returning []; callers are responsible
|
|
293
|
+
* for deciding how to handle/log the error. Empty string / null inputs return
|
|
294
|
+
* [] (they represent "no value"). Non-string array entries are filtered out.
|
|
295
|
+
*/
|
|
296
|
+
function parseStringArray(raw) {
|
|
297
|
+
if (!raw) return [];
|
|
298
|
+
const parsed = JSON.parse(raw);
|
|
299
|
+
if (!Array.isArray(parsed)) return [];
|
|
300
|
+
return parsed.filter((v) => typeof v === "string");
|
|
301
|
+
}
|
|
284
302
|
const VALID_METADATA_KINDS = new Set([
|
|
285
303
|
"meta",
|
|
286
304
|
"property",
|
|
@@ -375,9 +393,6 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
375
393
|
cronScheduler;
|
|
376
394
|
enabledPlugins;
|
|
377
395
|
pluginStates;
|
|
378
|
-
_cachedManifest = null;
|
|
379
|
-
_manifestPromise = null;
|
|
380
|
-
_manifestCacheKey;
|
|
381
396
|
/**
|
|
382
397
|
* Set to true after FTS indexes have been verified for this worker
|
|
383
398
|
* lifetime so we don't re-scan on every admin request. See
|
|
@@ -410,27 +425,26 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
410
425
|
if (ctx?.db) return ctx.db;
|
|
411
426
|
return this._db;
|
|
412
427
|
}
|
|
413
|
-
constructor(
|
|
414
|
-
this._db = db;
|
|
415
|
-
this.storage = storage;
|
|
416
|
-
this.configuredPlugins = configuredPlugins;
|
|
417
|
-
this.sandboxedPlugins = sandboxedPlugins;
|
|
418
|
-
this.sandboxedPluginEntries = sandboxedPluginEntries;
|
|
419
|
-
this.schemaRegistry = new SchemaRegistry(db);
|
|
420
|
-
this._hooks = hooks;
|
|
421
|
-
this.enabledPlugins = enabledPlugins;
|
|
422
|
-
this.pluginStates = pluginStates;
|
|
423
|
-
this.config = config;
|
|
424
|
-
this.mediaProviders = mediaProviders;
|
|
425
|
-
this.mediaProviderEntries = mediaProviderEntries;
|
|
426
|
-
this.cronExecutor = cronExecutor;
|
|
427
|
-
this.cronScheduler = cronScheduler;
|
|
428
|
-
this.email = emailPipeline;
|
|
429
|
-
this.allPipelinePlugins = allPipelinePlugins;
|
|
430
|
-
this.pipelineFactoryOptions = pipelineFactoryOptions;
|
|
431
|
-
this.runtimeDeps = runtimeDeps;
|
|
432
|
-
this.pipelineRef = pipelineRef;
|
|
433
|
-
this._manifestCacheKey = manifestCacheKey;
|
|
428
|
+
constructor(parts) {
|
|
429
|
+
this._db = parts.db;
|
|
430
|
+
this.storage = parts.storage;
|
|
431
|
+
this.configuredPlugins = parts.configuredPlugins;
|
|
432
|
+
this.sandboxedPlugins = parts.sandboxedPlugins;
|
|
433
|
+
this.sandboxedPluginEntries = parts.sandboxedPluginEntries;
|
|
434
|
+
this.schemaRegistry = new SchemaRegistry(parts.db);
|
|
435
|
+
this._hooks = parts.hooks;
|
|
436
|
+
this.enabledPlugins = parts.enabledPlugins;
|
|
437
|
+
this.pluginStates = parts.pluginStates;
|
|
438
|
+
this.config = parts.config;
|
|
439
|
+
this.mediaProviders = parts.mediaProviders;
|
|
440
|
+
this.mediaProviderEntries = parts.mediaProviderEntries;
|
|
441
|
+
this.cronExecutor = parts.cronExecutor;
|
|
442
|
+
this.cronScheduler = parts.cronScheduler;
|
|
443
|
+
this.email = parts.emailPipeline;
|
|
444
|
+
this.allPipelinePlugins = parts.allPipelinePlugins;
|
|
445
|
+
this.pipelineFactoryOptions = parts.pipelineFactoryOptions;
|
|
446
|
+
this.runtimeDeps = parts.runtimeDeps;
|
|
447
|
+
this.pipelineRef = parts.pipelineRef;
|
|
434
448
|
}
|
|
435
449
|
/**
|
|
436
450
|
* Get the sandbox runner instance (for marketplace install/update)
|
|
@@ -471,7 +485,6 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
471
485
|
this.enabledPlugins.delete(pluginId);
|
|
472
486
|
await this.rebuildHookPipeline();
|
|
473
487
|
}
|
|
474
|
-
this.invalidateManifest();
|
|
475
488
|
}
|
|
476
489
|
/**
|
|
477
490
|
* Rebuild the hook pipeline from the current set of enabled plugins.
|
|
@@ -595,6 +608,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
595
608
|
}
|
|
596
609
|
};
|
|
597
610
|
const db = await phase("rt.db", "DB init + migrations", () => EmDashRuntime.getDatabase(deps));
|
|
611
|
+
await phase("rt.secrets", "Validate encryption key", () => validateEncryptionKeyAtStartup());
|
|
598
612
|
const storage = EmDashRuntime.getStorage(deps);
|
|
599
613
|
let pluginStates = /* @__PURE__ */ new Map();
|
|
600
614
|
await phase("rt.plugins", "Plugin states", async () => {
|
|
@@ -628,7 +642,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
628
642
|
const devConsolePlugin = definePlugin({
|
|
629
643
|
id: DEV_CONSOLE_EMAIL_PLUGIN_ID,
|
|
630
644
|
version: "0.0.0",
|
|
631
|
-
capabilities: ["email:
|
|
645
|
+
capabilities: ["hooks.email-transport:register"],
|
|
632
646
|
hooks: { "email:deliver": {
|
|
633
647
|
exclusive: true,
|
|
634
648
|
handler: devConsoleEmailDeliver
|
|
@@ -643,7 +657,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
643
657
|
const defaultModeratorPlugin = definePlugin({
|
|
644
658
|
id: DEFAULT_COMMENT_MODERATOR_PLUGIN_ID,
|
|
645
659
|
version: "0.0.0",
|
|
646
|
-
capabilities: ["read
|
|
660
|
+
capabilities: ["users:read"],
|
|
647
661
|
hooks: { "comment:moderate": {
|
|
648
662
|
exclusive: true,
|
|
649
663
|
handler: defaultCommentModerate
|
|
@@ -716,14 +730,26 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
716
730
|
console.warn("[cron] Failed to initialize cron system:", error);
|
|
717
731
|
}
|
|
718
732
|
});
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
733
|
+
return new EmDashRuntime({
|
|
734
|
+
db,
|
|
735
|
+
storage,
|
|
736
|
+
configuredPlugins: deps.plugins,
|
|
737
|
+
sandboxedPlugins,
|
|
738
|
+
sandboxedPluginEntries: deps.sandboxedPluginEntries,
|
|
739
|
+
hooks: pipeline,
|
|
740
|
+
enabledPlugins,
|
|
741
|
+
pluginStates,
|
|
742
|
+
config: deps.config,
|
|
743
|
+
mediaProviders,
|
|
744
|
+
mediaProviderEntries,
|
|
745
|
+
cronExecutor,
|
|
746
|
+
cronScheduler,
|
|
747
|
+
emailPipeline,
|
|
748
|
+
allPipelinePlugins,
|
|
749
|
+
pipelineFactoryOptions,
|
|
750
|
+
runtimeDeps: deps,
|
|
751
|
+
pipelineRef
|
|
752
|
+
});
|
|
727
753
|
}
|
|
728
754
|
/**
|
|
729
755
|
* Get a media provider by ID
|
|
@@ -763,10 +789,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
763
789
|
dialect: deps.createDialect(dbConfig.config),
|
|
764
790
|
log: kyselyLogOption()
|
|
765
791
|
});
|
|
766
|
-
|
|
767
|
-
if (applied.length > 0) try {
|
|
768
|
-
await new OptionsRepository(db).delete("emdash:manifest_cache");
|
|
769
|
-
} catch {}
|
|
792
|
+
await runMigrations(db);
|
|
770
793
|
try {
|
|
771
794
|
const [collectionCount, setupOption] = await Promise.all([db.selectFrom("_emdash_collections").select((eb) => eb.fn.countAll().as("count")).executeTakeFirstOrThrow(), db.selectFrom("options").select("value").where("name", "=", "emdash:setup_complete").executeTakeFirst()]);
|
|
772
795
|
const setupDone = (() => {
|
|
@@ -777,9 +800,9 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
777
800
|
}
|
|
778
801
|
})();
|
|
779
802
|
if (collectionCount.count === 0 && !setupDone) {
|
|
780
|
-
const { applySeed } = await import("../apply-
|
|
781
|
-
const { loadSeed } = await import("../load-
|
|
782
|
-
const { validateSeed } = await import("../validate-
|
|
803
|
+
const { applySeed } = await import("../apply-BzltprvY.mjs").then((n) => n.n);
|
|
804
|
+
const { loadSeed } = await import("../load-DDqMMvZL.mjs").then((n) => n.r);
|
|
805
|
+
const { validateSeed } = await import("../validate-Baqf0slj.mjs").then((n) => n.n);
|
|
783
806
|
const seed = await loadSeed();
|
|
784
807
|
if (validateSeed(seed).valid) {
|
|
785
808
|
await applySeed(db, seed, { onConflict: "skip" });
|
|
@@ -918,60 +941,42 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
918
941
|
});
|
|
919
942
|
}
|
|
920
943
|
/**
|
|
921
|
-
*
|
|
922
|
-
* fallback for cold starts. Avoids N+1 schema registry queries
|
|
923
|
-
* on every request.
|
|
944
|
+
* Build the admin manifest from the live database.
|
|
924
945
|
*
|
|
925
|
-
*
|
|
926
|
-
*
|
|
946
|
+
* Used by the admin UI (sidebar collections, content editor field
|
|
947
|
+
* dispatch, manifest endpoint) and by WordPress import — it's never
|
|
948
|
+
* read on a public request, so this isn't on any anonymous hot path.
|
|
949
|
+
*
|
|
950
|
+
* No cross-request cache. The previous worker-isolate cache produced
|
|
951
|
+
* a class of cross-isolate staleness bugs (#776, #873, #876, #877)
|
|
952
|
+
* because Cloudflare Workers keeps multiple warm isolates per region
|
|
953
|
+
* and there's no fan-out primitive to invalidate them in step. The
|
|
954
|
+
* cache existed to amortize an N+1 schema query pattern; now that
|
|
955
|
+
* `listCollectionsWithFields()` does the same work in two queries,
|
|
956
|
+
* the rebuild is fast enough to pay on every admin request.
|
|
957
|
+
*
|
|
958
|
+
* Within a single request, `requestCached` deduplicates concurrent
|
|
959
|
+
* callers (the manifest endpoint and an admin SSR template, say).
|
|
927
960
|
*/
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
if (this._cachedManifest) return this._cachedManifest;
|
|
931
|
-
try {
|
|
932
|
-
const cached = await new OptionsRepository(this.db).get("emdash:manifest_cache");
|
|
933
|
-
if (cached && cached.key === this._manifestCacheKey && cached.manifest) {
|
|
934
|
-
this._cachedManifest = cached.manifest;
|
|
935
|
-
return cached.manifest;
|
|
936
|
-
}
|
|
937
|
-
} catch {}
|
|
938
|
-
if (!this._manifestPromise) {
|
|
939
|
-
let manifestPromise;
|
|
940
|
-
const isCurrentLoad = () => this._manifestPromise === manifestPromise;
|
|
941
|
-
manifestPromise = this._loadManifest(isCurrentLoad);
|
|
942
|
-
this._manifestPromise = manifestPromise;
|
|
943
|
-
}
|
|
944
|
-
return this._manifestPromise;
|
|
945
|
-
}
|
|
946
|
-
async _loadManifest(isCurrentLoad) {
|
|
947
|
-
try {
|
|
948
|
-
const manifest = await this._buildManifest();
|
|
949
|
-
if (isCurrentLoad()) {
|
|
950
|
-
this._cachedManifest = manifest;
|
|
951
|
-
try {
|
|
952
|
-
await new OptionsRepository(this.db).set("emdash:manifest_cache", {
|
|
953
|
-
key: this._manifestCacheKey,
|
|
954
|
-
manifest
|
|
955
|
-
});
|
|
956
|
-
} catch {}
|
|
957
|
-
}
|
|
958
|
-
return manifest;
|
|
959
|
-
} finally {
|
|
960
|
-
if (isCurrentLoad()) this._manifestPromise = null;
|
|
961
|
-
}
|
|
961
|
+
getManifest() {
|
|
962
|
+
return requestCached("emdash:manifest", () => this._buildManifest());
|
|
962
963
|
}
|
|
963
964
|
/**
|
|
964
|
-
* Build the manifest from database
|
|
965
|
+
* Build the manifest from the database.
|
|
966
|
+
*
|
|
967
|
+
* Constant query shapes via `listCollectionsWithFields()` — one query
|
|
968
|
+
* for collections, one batched query for fields (chunked at
|
|
969
|
+
* `SQL_BATCH_SIZE` collection IDs to stay under D1's bound-parameter
|
|
970
|
+
* limit). Typical sites stay well under the chunk threshold, so this
|
|
971
|
+
* is two queries in practice; never N+1.
|
|
965
972
|
*/
|
|
966
973
|
async _buildManifest() {
|
|
967
974
|
const manifestCollections = {};
|
|
968
975
|
try {
|
|
969
|
-
const
|
|
970
|
-
const dbCollections = await registry.listCollections();
|
|
976
|
+
const dbCollections = await new SchemaRegistry(this.db).listCollectionsWithFields();
|
|
971
977
|
for (const collection of dbCollections) {
|
|
972
|
-
const collectionWithFields = await registry.getCollectionWithFields(collection.slug);
|
|
973
978
|
const fields = {};
|
|
974
|
-
|
|
979
|
+
for (const field of collection.fields) {
|
|
975
980
|
const entry = {
|
|
976
981
|
kind: FIELD_TYPE_TO_KIND[field.type] ?? "string",
|
|
977
982
|
label: field.label,
|
|
@@ -1055,7 +1060,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1055
1060
|
label: row.label,
|
|
1056
1061
|
labelSingular: row.label_singular ?? void 0,
|
|
1057
1062
|
hierarchical: row.hierarchical === 1,
|
|
1058
|
-
collections:
|
|
1063
|
+
collections: parseStringArray(row.collections).toSorted()
|
|
1059
1064
|
}));
|
|
1060
1065
|
} catch (error) {
|
|
1061
1066
|
console.debug("EmDash: Could not load taxonomy definitions:", error);
|
|
@@ -1081,22 +1086,6 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1081
1086
|
};
|
|
1082
1087
|
}
|
|
1083
1088
|
/**
|
|
1084
|
-
* Invalidate cached data derived from the manifest/schema.
|
|
1085
|
-
* Called when collections, fields, plugins, or taxonomy defs change.
|
|
1086
|
-
*/
|
|
1087
|
-
invalidateManifest() {
|
|
1088
|
-
this._cachedManifest = null;
|
|
1089
|
-
this._manifestPromise = null;
|
|
1090
|
-
invalidateUrlPatternCache();
|
|
1091
|
-
try {
|
|
1092
|
-
new OptionsRepository(this.db).delete("emdash:manifest_cache").catch((error) => {
|
|
1093
|
-
console.error("Failed to delete persisted manifest cache", error);
|
|
1094
|
-
});
|
|
1095
|
-
} catch (error) {
|
|
1096
|
-
console.error("Failed to initialize manifest cache invalidation", error);
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
/**
|
|
1100
1089
|
* Verify and repair FTS indexes on demand. Runs at most once per worker
|
|
1101
1090
|
* lifetime.
|
|
1102
1091
|
*
|
|
@@ -1143,16 +1132,67 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1143
1132
|
return handleContentList(this.db, collection, params);
|
|
1144
1133
|
}
|
|
1145
1134
|
async handleContentGet(collection, id, locale) {
|
|
1146
|
-
|
|
1135
|
+
const result = await handleContentGet(this.db, collection, id, locale);
|
|
1136
|
+
return this.hydrateDraftData(result);
|
|
1147
1137
|
}
|
|
1148
1138
|
async handleContentGetIncludingTrashed(collection, id, locale) {
|
|
1149
|
-
|
|
1139
|
+
const result = await handleContentGetIncludingTrashed(this.db, collection, id, locale);
|
|
1140
|
+
return this.hydrateDraftData(result);
|
|
1141
|
+
}
|
|
1142
|
+
/**
|
|
1143
|
+
* If the response item has a `draftRevisionId`, replace `item.data` with
|
|
1144
|
+
* the draft revision's data and expose the original published values as
|
|
1145
|
+
* `liveData`. This makes the content_get / content_update round-trip
|
|
1146
|
+
* intuitive — read returns the latest content the caller has saved
|
|
1147
|
+
* (their pending draft), with the previously-published values still
|
|
1148
|
+
* accessible for compare-style flows.
|
|
1149
|
+
*
|
|
1150
|
+
* No-op when no draft exists or the response is an error.
|
|
1151
|
+
*/
|
|
1152
|
+
async hydrateDraftData(result) {
|
|
1153
|
+
if (!result || typeof result !== "object") return result;
|
|
1154
|
+
const r = result;
|
|
1155
|
+
if (!r.success || !r.data?.item) return result;
|
|
1156
|
+
const item = r.data.item;
|
|
1157
|
+
const draftRevisionId = typeof item.draftRevisionId === "string" ? item.draftRevisionId : null;
|
|
1158
|
+
if (!draftRevisionId) return result;
|
|
1159
|
+
try {
|
|
1160
|
+
const revision = await new RevisionRepository(this.db).findById(draftRevisionId);
|
|
1161
|
+
if (!revision) return result;
|
|
1162
|
+
const liveData = item.data && typeof item.data === "object" ? item.data : {};
|
|
1163
|
+
const revisionData = {};
|
|
1164
|
+
for (const [key, value] of Object.entries(revision.data)) if (!key.startsWith("_")) revisionData[key] = value;
|
|
1165
|
+
const mergedData = {
|
|
1166
|
+
...liveData,
|
|
1167
|
+
...revisionData
|
|
1168
|
+
};
|
|
1169
|
+
return {
|
|
1170
|
+
...result,
|
|
1171
|
+
data: {
|
|
1172
|
+
...r.data,
|
|
1173
|
+
item: {
|
|
1174
|
+
...item,
|
|
1175
|
+
data: mergedData,
|
|
1176
|
+
liveData
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
};
|
|
1180
|
+
} catch (error) {
|
|
1181
|
+
console.error("[emdash] draft hydration failed:", error);
|
|
1182
|
+
return result;
|
|
1183
|
+
}
|
|
1150
1184
|
}
|
|
1151
1185
|
async handleContentCreate(collection, body) {
|
|
1152
1186
|
let processedData = body.data;
|
|
1153
1187
|
if (this.hooks.hasHooks("content:beforeSave")) processedData = (await this.hooks.runContentBeforeSave(body.data, collection, true)).content;
|
|
1154
1188
|
processedData = await this.runSandboxedBeforeSave(processedData, collection, true);
|
|
1155
1189
|
processedData = await this.normalizeMediaFields(collection, processedData);
|
|
1190
|
+
const { validateContentData } = await import("../validation-BfEI7tNe.mjs");
|
|
1191
|
+
const validation = await validateContentData(this.db, collection, processedData, { partial: false });
|
|
1192
|
+
if (!validation.ok) return {
|
|
1193
|
+
success: false,
|
|
1194
|
+
error: validation.error
|
|
1195
|
+
};
|
|
1156
1196
|
const result = await handleContentCreate(this.db, collection, {
|
|
1157
1197
|
...body,
|
|
1158
1198
|
data: processedData,
|
|
@@ -1163,7 +1203,7 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1163
1203
|
return result;
|
|
1164
1204
|
}
|
|
1165
1205
|
async handleContentUpdate(collection, id, body) {
|
|
1166
|
-
const { ContentRepository } = await import("../content-
|
|
1206
|
+
const { ContentRepository } = await import("../content-8lOYF0pr.mjs").then((n) => n.n);
|
|
1167
1207
|
const repo = new ContentRepository(this.db);
|
|
1168
1208
|
const resolvedItem = await repo.findByIdOrSlug(collection, id);
|
|
1169
1209
|
const resolvedId = resolvedItem?.id ?? id;
|
|
@@ -1190,6 +1230,12 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1190
1230
|
if (this.hooks.hasHooks("content:beforeSave")) processedData = (await this.hooks.runContentBeforeSave(bodyWithoutRev.data, collection, false)).content;
|
|
1191
1231
|
processedData = await this.runSandboxedBeforeSave(processedData, collection, false);
|
|
1192
1232
|
processedData = await this.normalizeMediaFields(collection, processedData);
|
|
1233
|
+
const { validateContentData } = await import("../validation-BfEI7tNe.mjs");
|
|
1234
|
+
const validation = await validateContentData(this.db, collection, processedData, { partial: true });
|
|
1235
|
+
if (!validation.ok) return {
|
|
1236
|
+
success: false,
|
|
1237
|
+
error: validation.error
|
|
1238
|
+
};
|
|
1193
1239
|
}
|
|
1194
1240
|
let usesDraftRevisions = false;
|
|
1195
1241
|
if (processedData) try {
|
|
@@ -1234,8 +1280,9 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1234
1280
|
authorId: bodyWithoutRev.authorId,
|
|
1235
1281
|
bylines: bodyWithoutRev.bylines
|
|
1236
1282
|
});
|
|
1237
|
-
|
|
1238
|
-
|
|
1283
|
+
const hydrated = await this.hydrateDraftData(result);
|
|
1284
|
+
if (hydrated.success && hydrated.data) this.runAfterSaveHooks(contentItemToRecord(hydrated.data.item), collection, false);
|
|
1285
|
+
return hydrated;
|
|
1239
1286
|
}
|
|
1240
1287
|
async handleContentDelete(collection, id) {
|
|
1241
1288
|
if (this.hooks.hasHooks("content:beforeDelete")) {
|
|
@@ -1276,8 +1323,8 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1276
1323
|
async handleContentDuplicate(collection, id, authorId) {
|
|
1277
1324
|
return handleContentDuplicate(this.db, collection, id, authorId);
|
|
1278
1325
|
}
|
|
1279
|
-
async handleContentPublish(collection, id) {
|
|
1280
|
-
const result = await handleContentPublish(this.db, collection, id);
|
|
1326
|
+
async handleContentPublish(collection, id, options = {}) {
|
|
1327
|
+
const result = await handleContentPublish(this.db, collection, id, options);
|
|
1281
1328
|
if (result.success && result.data) this.runAfterPublishHooks(contentItemToRecord(result.data.item), collection);
|
|
1282
1329
|
return result;
|
|
1283
1330
|
}
|
|
@@ -1353,7 +1400,47 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1353
1400
|
return handleRevisionGet(this.db, revisionId);
|
|
1354
1401
|
}
|
|
1355
1402
|
async handleRevisionRestore(revisionId, callerUserId) {
|
|
1356
|
-
|
|
1403
|
+
const revisionRepo = new RevisionRepository(this.db);
|
|
1404
|
+
const revision = await revisionRepo.findById(revisionId);
|
|
1405
|
+
if (!revision) return {
|
|
1406
|
+
success: false,
|
|
1407
|
+
error: {
|
|
1408
|
+
code: "NOT_FOUND",
|
|
1409
|
+
message: `Revision not found: ${revisionId}`
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
if (!((await this.schemaRegistry.getCollectionWithFields(revision.collection))?.supports?.includes("revisions") ?? false)) {
|
|
1413
|
+
const result = await handleRevisionRestore(this.db, revisionId, callerUserId);
|
|
1414
|
+
return this.hydrateDraftData(result);
|
|
1415
|
+
}
|
|
1416
|
+
try {
|
|
1417
|
+
const newDraft = await revisionRepo.create({
|
|
1418
|
+
collection: revision.collection,
|
|
1419
|
+
entryId: revision.entryId,
|
|
1420
|
+
data: revision.data,
|
|
1421
|
+
authorId: callerUserId
|
|
1422
|
+
});
|
|
1423
|
+
validateIdentifier(revision.collection, "collection");
|
|
1424
|
+
const tableName = `ec_${revision.collection}`;
|
|
1425
|
+
await sql`
|
|
1426
|
+
UPDATE ${sql.ref(tableName)}
|
|
1427
|
+
SET draft_revision_id = ${newDraft.id},
|
|
1428
|
+
updated_at = ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
1429
|
+
WHERE id = ${revision.entryId}
|
|
1430
|
+
`.execute(this.db);
|
|
1431
|
+
revisionRepo.pruneOldRevisions(revision.collection, revision.entryId, 50).catch(() => {});
|
|
1432
|
+
const refetched = await handleContentGet(this.db, revision.collection, revision.entryId);
|
|
1433
|
+
return this.hydrateDraftData(refetched);
|
|
1434
|
+
} catch (error) {
|
|
1435
|
+
console.error("[emdash] revision restore failed:", error);
|
|
1436
|
+
return {
|
|
1437
|
+
success: false,
|
|
1438
|
+
error: {
|
|
1439
|
+
code: "REVISION_RESTORE_ERROR",
|
|
1440
|
+
message: "Failed to restore revision"
|
|
1441
|
+
}
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1357
1444
|
}
|
|
1358
1445
|
/**
|
|
1359
1446
|
* Get route metadata for a plugin route without invoking the handler.
|
|
@@ -1486,16 +1573,30 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1486
1573
|
return true;
|
|
1487
1574
|
}
|
|
1488
1575
|
runAfterSaveHooks(content, collection, isNew) {
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1576
|
+
after(async () => {
|
|
1577
|
+
if (this.hooks.hasHooks("content:afterSave")) try {
|
|
1578
|
+
await this.hooks.runContentAfterSave(content, collection, isNew);
|
|
1579
|
+
} catch (err) {
|
|
1580
|
+
console.error("EmDash afterSave hook error:", err);
|
|
1581
|
+
}
|
|
1582
|
+
const tasks = [];
|
|
1583
|
+
for (const [pluginKey, plugin] of this.sandboxedPlugins) {
|
|
1584
|
+
const [id] = pluginKey.split(":");
|
|
1585
|
+
if (!id || !this.isPluginEnabled(id)) continue;
|
|
1586
|
+
tasks.push((async () => {
|
|
1587
|
+
try {
|
|
1588
|
+
await plugin.invokeHook("content:afterSave", {
|
|
1589
|
+
content,
|
|
1590
|
+
collection,
|
|
1591
|
+
isNew
|
|
1592
|
+
});
|
|
1593
|
+
} catch (err) {
|
|
1594
|
+
console.error(`EmDash: Sandboxed plugin ${id} afterSave error:`, err);
|
|
1595
|
+
}
|
|
1596
|
+
})());
|
|
1597
|
+
}
|
|
1598
|
+
await Promise.allSettled(tasks);
|
|
1599
|
+
});
|
|
1499
1600
|
}
|
|
1500
1601
|
runAfterDeleteHooks(id, collection, permanent) {
|
|
1501
1602
|
if (this.hooks.hasHooks("content:afterDelete")) this.hooks.runContentAfterDelete(id, collection, permanent).catch((err) => console.error("EmDash afterDelete hook error:", err));
|
|
@@ -1510,15 +1611,29 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1510
1611
|
}
|
|
1511
1612
|
}
|
|
1512
1613
|
runAfterPublishHooks(content, collection) {
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1614
|
+
after(async () => {
|
|
1615
|
+
if (this.hooks.hasHooks("content:afterPublish")) try {
|
|
1616
|
+
await this.hooks.runContentAfterPublish(content, collection);
|
|
1617
|
+
} catch (err) {
|
|
1618
|
+
console.error("EmDash afterPublish hook error:", err);
|
|
1619
|
+
}
|
|
1620
|
+
const tasks = [];
|
|
1621
|
+
for (const [pluginKey, plugin] of this.sandboxedPlugins) {
|
|
1622
|
+
const [pluginId] = pluginKey.split(":");
|
|
1623
|
+
if (!pluginId || !this.isPluginEnabled(pluginId)) continue;
|
|
1624
|
+
tasks.push((async () => {
|
|
1625
|
+
try {
|
|
1626
|
+
await plugin.invokeHook("content:afterPublish", {
|
|
1627
|
+
content,
|
|
1628
|
+
collection
|
|
1629
|
+
});
|
|
1630
|
+
} catch (err) {
|
|
1631
|
+
console.error(`EmDash: Sandboxed plugin ${pluginId} afterPublish error:`, err);
|
|
1632
|
+
}
|
|
1633
|
+
})());
|
|
1634
|
+
}
|
|
1635
|
+
await Promise.allSettled(tasks);
|
|
1636
|
+
});
|
|
1522
1637
|
}
|
|
1523
1638
|
runAfterUnpublishHooks(content, collection) {
|
|
1524
1639
|
if (this.hooks.hasHooks("content:afterUnpublish")) this.hooks.runContentAfterUnpublish(content, collection).catch((err) => console.error("EmDash afterUnpublish hook error:", err));
|
|
@@ -1629,6 +1744,28 @@ var EmDashRuntime = class EmDashRuntime {
|
|
|
1629
1744
|
}
|
|
1630
1745
|
};
|
|
1631
1746
|
|
|
1747
|
+
//#endregion
|
|
1748
|
+
//#region src/media/url.ts
|
|
1749
|
+
/**
|
|
1750
|
+
* Resolve the public URL for a locally stored media key. Returns an empty
|
|
1751
|
+
* string when no key is given. When a storage adapter is supplied, defers to
|
|
1752
|
+
* `storage.getPublicUrl()`; otherwise returns the internal proxy route.
|
|
1753
|
+
*/
|
|
1754
|
+
function resolvePublicMediaUrl(storage, storageKey) {
|
|
1755
|
+
if (!storageKey) return "";
|
|
1756
|
+
if (storage) return storage.getPublicUrl(storageKey);
|
|
1757
|
+
return `/_emdash/api/media/file/${storageKey}`;
|
|
1758
|
+
}
|
|
1759
|
+
/**
|
|
1760
|
+
* Build the `getPublicMediaUrl` closure attached to `Astro.locals.emdash`.
|
|
1761
|
+
* Shared by the anonymous fast path and the full-runtime path in middleware.
|
|
1762
|
+
*
|
|
1763
|
+
* @internal
|
|
1764
|
+
*/
|
|
1765
|
+
function createPublicMediaUrlResolver(storage) {
|
|
1766
|
+
return (key) => resolvePublicMediaUrl(storage, key);
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1632
1769
|
//#endregion
|
|
1633
1770
|
//#region src/astro/middleware.ts
|
|
1634
1771
|
/**
|
|
@@ -1751,6 +1888,9 @@ function createRequestScopedDb$1(opts) {
|
|
|
1751
1888
|
const onRequest = defineMiddleware(async (context, next) => {
|
|
1752
1889
|
const { request, locals, cookies } = context;
|
|
1753
1890
|
const url = context.url;
|
|
1891
|
+
if (!url.pathname.startsWith("/_emdash") && virtualConfig?.authProviders) {
|
|
1892
|
+
if (virtualConfig.authProviders.some((p) => p.routes?.some((r) => r.pattern && url.pathname === r.pattern))) return finalizeResponse(await next());
|
|
1893
|
+
}
|
|
1754
1894
|
const queryRecorder = isInstrumentationEnabled() ? createRecorder(url.pathname, request.method, request.headers.get("x-perf-phase") ?? "default") : void 0;
|
|
1755
1895
|
const run = async () => {
|
|
1756
1896
|
const isEmDashRoute = url.pathname.startsWith("/_emdash");
|
|
@@ -1758,7 +1898,8 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
1758
1898
|
const hasEditCookie = cookies.get("emdash-edit-mode")?.value === "true";
|
|
1759
1899
|
const hasPreviewToken = url.searchParams.has("_preview");
|
|
1760
1900
|
const playgroundDb = locals.__playgroundDb;
|
|
1761
|
-
const
|
|
1901
|
+
const hasSessionCookie = cookies.get("astro-session") !== void 0;
|
|
1902
|
+
const sessionUser = context.isPrerendered || !hasSessionCookie ? null : await context.session?.get("user");
|
|
1762
1903
|
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
|
1763
1904
|
if (!sessionUser && !playgroundDb) {
|
|
1764
1905
|
const timings = [];
|
|
@@ -1766,7 +1907,7 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
1766
1907
|
if (!setupVerified) {
|
|
1767
1908
|
const t0 = performance.now();
|
|
1768
1909
|
try {
|
|
1769
|
-
const { getDb } = await import("../loader-
|
|
1910
|
+
const { getDb } = await import("../loader-CKLbBnhK.mjs").then((n) => n.i);
|
|
1770
1911
|
await (await getDb()).selectFrom("_emdash_migrations").selectAll().limit(1).execute();
|
|
1771
1912
|
setupVerified = true;
|
|
1772
1913
|
} catch {
|
|
@@ -1787,7 +1928,8 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
1787
1928
|
setupVerified = true;
|
|
1788
1929
|
locals.emdash = {
|
|
1789
1930
|
collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
|
|
1790
|
-
collectPageFragments: runtime.collectPageFragments.bind(runtime)
|
|
1931
|
+
collectPageFragments: runtime.collectPageFragments.bind(runtime),
|
|
1932
|
+
getPublicMediaUrl: createPublicMediaUrlResolver(runtime.storage)
|
|
1791
1933
|
};
|
|
1792
1934
|
} catch {}
|
|
1793
1935
|
timings.push({
|
|
@@ -1855,14 +1997,6 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
1855
1997
|
});
|
|
1856
1998
|
for (const sub of initSubTimings) timings.push(sub);
|
|
1857
1999
|
setupVerified = true;
|
|
1858
|
-
t0 = performance.now();
|
|
1859
|
-
const manifest = await runtime.getManifest();
|
|
1860
|
-
timings.push({
|
|
1861
|
-
name: "manifest",
|
|
1862
|
-
dur: performance.now() - t0,
|
|
1863
|
-
desc: "Manifest"
|
|
1864
|
-
});
|
|
1865
|
-
locals.emdashManifest = manifest;
|
|
1866
2000
|
locals.emdash = {
|
|
1867
2001
|
handleContentList: runtime.handleContentList.bind(runtime),
|
|
1868
2002
|
handleContentGet: runtime.handleContentGet.bind(runtime),
|
|
@@ -1900,11 +2034,13 @@ const onRequest = defineMiddleware(async (context, next) => {
|
|
|
1900
2034
|
ensureSearchHealthy: runtime.ensureSearchHealthy.bind(runtime),
|
|
1901
2035
|
storage: runtime.storage,
|
|
1902
2036
|
db: runtime.db,
|
|
2037
|
+
getPublicMediaUrl: createPublicMediaUrlResolver(runtime.storage),
|
|
1903
2038
|
hooks: runtime.hooks,
|
|
1904
2039
|
email: runtime.email,
|
|
1905
2040
|
configuredPlugins: runtime.configuredPlugins,
|
|
1906
2041
|
config,
|
|
1907
|
-
|
|
2042
|
+
getManifest: runtime.getManifest.bind(runtime),
|
|
2043
|
+
invalidateUrlPatternCache,
|
|
1908
2044
|
getSandboxRunner: runtime.getSandboxRunner.bind(runtime),
|
|
1909
2045
|
syncMarketplacePlugins: runtime.syncMarketplacePlugins.bind(runtime),
|
|
1910
2046
|
setPluginStatus: runtime.setPluginStatus.bind(runtime)
|