dineway 0.1.49 → 0.2.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/{activity-events-CwM7yxPW.mjs → activity-events-y6eT8UW6.mjs} +6 -38
- package/dist/actor-CrObAPV0.mjs +37 -0
- package/dist/after-BfniwgIf.mjs +9 -0
- package/dist/{allowed-origins-CyGnbgBd.mjs → allowed-origins-_oeyP6x-.mjs} +1 -1
- package/dist/api/route-utils.d.mts +10 -10
- package/dist/api/route-utils.mjs +16 -13
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +5 -4
- package/dist/{api-BMIxRIEN.mjs → api-ByrU2q-Z.mjs} +60 -36
- package/dist/{api-tokens-DtvdtIkm.mjs → api-tokens-CjVMQT-X.mjs} +6 -2
- package/dist/{apply-D_RlTYtC.mjs → apply-bZswmZPm.mjs} +117 -77
- package/dist/astro/image-endpoint.d.mts +7 -0
- package/dist/astro/image-endpoint.mjs +54 -0
- package/dist/astro/index.d.mts +35 -11
- package/dist/astro/index.mjs +157 -23
- package/dist/astro/integration/shims/use-sync-external-store-with-selector.js +71 -0
- package/dist/astro/integration/shims/use-sync-external-store.js +1 -0
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +42 -24
- package/dist/astro/middleware/redirect.mjs +13 -4
- package/dist/astro/middleware/request-context.mjs +8 -5
- package/dist/astro/middleware/seed.d.mts +1 -1
- package/dist/astro/middleware/seed.mjs +2 -2
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.mjs +333 -192
- package/dist/astro/routes/admin.astro +6 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
- package/dist/astro/routes/api/admin/briefing.mjs +21 -17
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -8
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -8
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -8
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -14
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -14
- package/dist/astro/routes/api/admin/bylines/index.mjs +17 -14
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +14 -12
- package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +11 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +6 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +11 -9
- package/dist/astro/routes/api/admin/context/_id_/history.mjs +26 -24
- package/dist/astro/routes/api/admin/context/_id_/index.mjs +26 -24
- package/dist/astro/routes/api/admin/context/_id_/review.mjs +31 -28
- package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +31 -28
- package/dist/astro/routes/api/admin/context/diff.mjs +30 -27
- package/dist/astro/routes/api/admin/context/index.mjs +31 -28
- package/dist/astro/routes/api/admin/context/stale.mjs +30 -27
- package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +26 -24
- package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +30 -27
- package/dist/astro/routes/api/admin/hitl-requests/index.mjs +30 -27
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +27 -25
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +6 -6
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +55 -51
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +55 -51
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +47 -43
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +53 -49
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +52 -48
- package/dist/astro/routes/api/admin/plugins/index.mjs +47 -43
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +46 -42
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +52 -48
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +46 -42
- package/dist/astro/routes/api/admin/plugins/updates.mjs +46 -42
- package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +5 -5
- package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +31 -27
- package/dist/astro/routes/api/admin/review-requests/index.mjs +10 -9
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +46 -42
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +46 -42
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -7
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
- package/dist/astro/routes/api/admin/users/index.mjs +7 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +4 -4
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +12 -11
- package/dist/astro/routes/api/auth/invite/index.mjs +9 -8
- package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -10
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +11 -10
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/me.mjs +9 -8
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -5
- package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/options.mjs +12 -11
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -9
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -10
- package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -10
- package/dist/astro/routes/api/auth/setup-token/index.mjs +5 -5
- package/dist/astro/routes/api/auth/setup-token/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/signup/complete.mjs +12 -11
- package/dist/astro/routes/api/auth/signup/request.mjs +11 -10
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +15 -13
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +8 -0
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +160 -0
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +16 -14
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -6
- package/dist/astro/routes/api/dashboard.mjs +9 -8
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/health.mjs +1 -1
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +22 -10
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +9 -6
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +19 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +84 -37
- package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +19 -13
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +35 -32
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +18 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +120 -100
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +24 -12
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +56 -2
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +283 -55
- package/dist/astro/routes/api/manifest.mjs +14 -5
- package/dist/astro/routes/api/mcp.mjs +265 -69
- package/dist/astro/routes/api/media/_id_/confirm.mjs +38 -10
- package/dist/astro/routes/api/media/_id_.mjs +11 -7
- package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
- package/dist/astro/routes/api/media/providers/index.mjs +2 -2
- package/dist/astro/routes/api/media/upload-url.mjs +11 -10
- package/dist/astro/routes/api/media.mjs +27 -34
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +31 -28
- package/dist/astro/routes/api/menus/_name_/items.mjs +31 -28
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +31 -28
- package/dist/astro/routes/api/menus/_name_/translations.mjs +31 -28
- package/dist/astro/routes/api/menus/_name_.mjs +31 -28
- package/dist/astro/routes/api/menus/index.mjs +31 -28
- package/dist/astro/routes/api/oauth/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
- package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.mjs +6 -6
- package/dist/astro/routes/api/openapi.json.mjs +4 -3
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +30 -30
- package/dist/astro/routes/api/redirects/404s/index.mjs +11 -10
- package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -10
- package/dist/astro/routes/api/redirects/_id_.mjs +32 -29
- package/dist/astro/routes/api/redirects/index.mjs +32 -29
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +47 -43
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +47 -43
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +47 -43
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +47 -43
- package/dist/astro/routes/api/schema/collections/index.mjs +47 -43
- package/dist/astro/routes/api/schema/index.mjs +13 -14
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +46 -42
- package/dist/astro/routes/api/schema/orphans/index.mjs +46 -42
- package/dist/astro/routes/api/search/enable.mjs +11 -10
- package/dist/astro/routes/api/search/index.mjs +10 -9
- package/dist/astro/routes/api/search/rebuild.mjs +11 -10
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +10 -9
- package/dist/astro/routes/api/sections/_slug_.mjs +31 -28
- package/dist/astro/routes/api/sections/index.mjs +31 -28
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +31 -28
- package/dist/astro/routes/api/setup/admin-verify.mjs +14 -13
- package/dist/astro/routes/api/setup/admin.mjs +12 -11
- package/dist/astro/routes/api/setup/dev-bypass.mjs +31 -25
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +29 -25
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +8 -7
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +34 -31
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +34 -31
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +34 -31
- package/dist/astro/routes/api/taxonomies/index.mjs +34 -31
- package/dist/astro/routes/api/themes/preview.mjs +5 -5
- package/dist/astro/routes/api/typegen.mjs +4 -4
- package/dist/astro/routes/api/well-known/auth.mjs +3 -3
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +3 -3
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +3 -3
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +30 -27
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +31 -28
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +31 -28
- package/dist/astro/routes/api/widget-areas/_name_.mjs +28 -26
- package/dist/astro/routes/api/widget-areas/index.mjs +31 -28
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +8 -7
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +23 -14
- package/dist/astro/routes/sitemap.xml.mjs +9 -8
- package/dist/astro/session-driver.d.mts +1 -1
- package/dist/astro/session-driver.mjs +2 -2
- package/dist/astro/types.d.mts +21 -13
- package/dist/{audit-BeNsSyfU.mjs → audit-ByVKIwWF.mjs} +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{auth-control-guard-Dr14I98m.mjs → auth-control-guard-CqeUmQsv.mjs} +1 -1
- package/dist/{authorize-BLO0m7fW.mjs → authorize-CcBxcHtz.mjs} +1 -1
- package/dist/{briefing-DJX6irto.mjs → briefing-BJaJI8dm.mjs} +2 -1
- package/dist/{briefing-CkTee1ex.mjs → briefing-CawZ59CY.mjs} +90 -28
- package/dist/bundle-7C_DpkEq.mjs +602 -0
- package/dist/{byline-BVC1lV6G.mjs → byline-e51-fWRs.mjs} +30 -62
- package/dist/{byline-fields-uJlygdzM.d.mts → byline-fields-CUvbslGc.d.mts} +80 -37
- package/dist/{byline-fields-Cj39WhXC.mjs → byline-fields-D-N5qVIG.mjs} +1 -1
- package/dist/{byline-fields-cNrLJVRs.mjs → byline-fields-DOJO16Gm.mjs} +3 -3
- package/dist/{byline-registry-4v6tXMNX.mjs → byline-registry-87nNnYl4.mjs} +2 -2
- package/dist/{bylines-LN9XISRo.mjs → bylines-CMQNCNFh.mjs} +9 -3
- package/dist/{bylines-DwokOFj6.mjs → bylines-y4LO-dTj.mjs} +5 -5
- package/dist/{cache-Bac05gBd.mjs → cache-C-FNTFYK.mjs} +2 -2
- package/dist/{chunks-CuUt7K50.mjs → chunks-CxBt-GxR.mjs} +1 -1
- package/dist/cli/index.mjs +94 -659
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +2 -1
- package/dist/{comment-Beue8-15.mjs → comment-DlA4iChg.mjs} +13 -3
- package/dist/comment-reaction-DfFao1ST.mjs +58 -0
- package/dist/{comments-DcjFIfqX.mjs → comments-DApFGMsP.mjs} +1 -1
- package/dist/{content-CBxYGWfL.mjs → content-Bh4BDjv8.mjs} +51 -34
- package/dist/content-refresh-CgutSUfO.mjs +1576 -0
- package/dist/{context-CQVNZaR8.mjs → context-C5W3G18y.mjs} +111 -50
- package/dist/{context-Df1xVYyr.mjs → context-CK4ym2Sf.mjs} +2 -2
- package/dist/{context-route-helpers-B9wj8Rmh.mjs → context-route-helpers-MASyGgWf.mjs} +2 -1
- package/dist/{cron-DxCAU_Sn.mjs → cron-cKcNTix_.mjs} +7 -3
- package/dist/{dashboard-B7ZUNuyF.mjs → dashboard-DQkVT7Ei.mjs} +4 -4
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{device-flow-BZVGftqi.mjs → device-flow-BnqRH-T9.mjs} +5 -5
- package/dist/{placeholder-d54Qr_7n.mjs → enrich-DIFIFA8O.mjs} +36 -9
- package/dist/{error-DCSuUAZW.mjs → error-CytFlgcd.mjs} +5 -0
- package/dist/field-defs-cache-DRNdhBJv.mjs +49 -0
- package/dist/{fts-manager-B5l_qwrA.mjs → fts-manager-Crzypjqu.mjs} +1 -1
- package/dist/hitl-Hw1RmWOq.mjs +677 -0
- package/dist/{hitl-requests-7NlzVeUA.mjs → hitl-requests-B4Vbcmaq.mjs} +2 -2
- package/dist/{hitl-route-helpers-k---_H3-.mjs → hitl-route-helpers-hEVzvP8l.mjs} +5 -4
- package/dist/import-Bh9biJfx.mjs +1354 -0
- package/dist/{index-CZiWCQDp.d.mts → index-D4y6NGiy.d.mts} +75 -3
- package/dist/index.d.mts +17 -16
- package/dist/index.mjs +80 -68
- package/dist/{jsonld-DZ67souc.d.mts → jsonld-Dq0gsnOH.d.mts} +8 -4
- package/dist/{load-D9OiGr2m.mjs → load-DmYeniXl.mjs} +1 -1
- package/dist/{loader--GOYux8M.mjs → loader-CjWqjweO.mjs} +117 -31
- package/dist/{manifest-schema-qh2P7RDX.mjs → manifest-schema-BxVPYMJR.mjs} +34 -1
- package/dist/mcp-reviewed-executor-TwVbMzG6.mjs +555 -0
- package/dist/media/image-endpoint.d.mts +32 -0
- package/dist/media/image-endpoint.mjs +111 -0
- package/dist/media/index.d.mts +27 -2
- package/dist/media/index.mjs +5 -3
- package/dist/media/local-runtime.d.mts +16 -11
- package/dist/media/local-runtime.mjs +9 -7
- package/dist/{media-CbKyYukG.mjs → media-DMj0grzC.mjs} +3 -1
- package/dist/{media-allowlist-BYxJIcTO.mjs → media-allowlist-BlVCSzHx.mjs} +1 -1
- package/dist/media-url-lEKSrpr9.mjs +20 -0
- package/dist/{menus-BZbXf-ej.mjs → menus-TaW1gKnk.mjs} +19 -5
- package/dist/{menus-C7F0sCrC.mjs → menus-xvsnVZXw.mjs} +80 -15
- package/dist/{normalize-ByemhhfW.mjs → normalize-5ek_z7de.mjs} +8 -1
- package/dist/{oauth-authorization-DF-LCsIA.mjs → oauth-authorization-DiaGvRVz.mjs} +5 -5
- package/dist/{oauth-clients-Du-V0fEm.mjs → oauth-clients-Dl9E8dEM.mjs} +2 -2
- package/dist/object-cache/memory.d.mts +14 -0
- package/dist/object-cache/memory.mjs +55 -0
- package/dist/object-cache-D51qOseS.mjs +419 -0
- package/dist/page/index.d.mts +4 -3
- package/dist/page/index.mjs +2 -2
- package/dist/{parse-CneSgl7-.mjs → parse-CbymENaR.mjs} +1 -1
- package/dist/{parser-DxfsARXL.mjs → parser-C1nYd-81.mjs} +151 -9
- package/dist/{placeholder-CXfoCtCd.d.mts → placeholder-uvNRZBX9.d.mts} +12 -4
- package/dist/plugin-utils.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.mjs +11 -2
- package/dist/{plugins-DzfqRREq.mjs → plugins-BolVa-tl.mjs} +831 -63
- package/dist/{transport-LSdZVXHF.mjs → portable-text-dA_UlJwW.mjs} +1 -134
- package/dist/{preview-C-3YTX2U.mjs → preview-vSVg6fwG.mjs} +4 -3
- package/dist/process-cache-7xgAO9JY.mjs +106 -0
- package/dist/{provider-loader-9it4vd6L.d.mts → provider-loader-MD8zAbnH.d.mts} +1 -1
- package/dist/{public-url-B4xV4rGa.d.mts → public-url-gsp3oUbu.d.mts} +1 -1
- package/dist/{query-Ds0EnMFX.mjs → query-CfRCdaL3.mjs} +281 -76
- package/dist/{query-CZ3TH_Uu.mjs → query-jaAmw8E1.mjs} +11 -6
- package/dist/{rate-limit-i0G3IAOX.mjs → rate-limit-ZLdyWoZF.mjs} +2 -2
- package/dist/{redirect-CEACczxo.mjs → redirect-BAjt4Z6b.mjs} +2 -2
- package/dist/{redirects-DYj1yPxs.mjs → redirects-BTdwpQtE.mjs} +47 -24
- package/dist/{redirects-ocRJmQHP.mjs → redirects-CA-xylPG.mjs} +19 -11
- package/dist/{registry-D7HACema.mjs → registry-CtyVedcN.mjs} +130 -77
- package/dist/request-context.d.mts +2 -0
- package/dist/{request-meta-DAb6xaP9.mjs → request-meta-CUypToDJ.mjs} +1 -1
- package/dist/{review-requests-Qum4713s.mjs → review-requests-C9Ff11Vq.mjs} +1 -1
- package/dist/{review-requests-BW2NxY-l.mjs → review-requests-DUyEmtmG.mjs} +1 -1
- package/dist/{runner-09sTqtv0.d.mts → runner-1tC2tIRV.d.mts} +1 -1
- package/dist/runner-DB7CRfOF.mjs +6740 -0
- package/dist/{runtime-C4-2lSFg.d.mts → runtime-BOeiQsCv.d.mts} +1952 -1489
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +3 -3
- package/dist/schema-DXdYj4R3.mjs +8 -0
- package/dist/{search-Gdrqj582.mjs → search-DSaLgEFI.mjs} +5 -3
- package/dist/{secrets-CeGpBFV2.mjs → secrets-CDZo2k8L.mjs} +14 -11
- package/dist/{sections-BOjU13Y-.mjs → sections-PVVXHGfp.mjs} +2 -2
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +21 -18
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.mjs +3 -12
- package/dist/{seo-CLj8lS7Q.mjs → seo-CQG3GCHQ.mjs} +5 -2
- package/dist/{seo-contributions-CqVvReEj.mjs → seo-contributions-C1EnikHB.mjs} +11 -3
- package/dist/{seo-5lJOtB5J.mjs → seo-qa7Dn0jK.mjs} +22 -4
- package/dist/{service-jGlhrICs.mjs → service-DiN4ZuPp.mjs} +2 -2
- package/dist/session-user-CAKImna3.mjs +22 -0
- package/dist/{settings-CUXOxzsT.mjs → settings-BbqgHWpU.mjs} +28 -55
- package/dist/{settings-DlBsT2VS.mjs → settings-i4VPP8bT.mjs} +2 -2
- package/dist/{setup-complete-BRrdPYjZ.mjs → setup-complete-B8fl-mjV.mjs} +1 -1
- package/dist/{site-activity-DONFrMBJ.mjs → site-activity-Dy3FROs0.mjs} +1 -1
- package/dist/{site-context-C8Az_P_I.mjs → site-context-DQiL8Fl5.mjs} +23 -652
- package/dist/{site-url-DIMD68go.mjs → site-url-BML3GQYm.mjs} +1 -1
- package/dist/status-DANd8ERo.mjs +21 -0
- 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.mjs +1 -1
- package/dist/{taxonomies-D9Sw4wWM.mjs → taxonomies-9s-v03H-.mjs} +36 -29
- package/dist/taxonomies-DRiixp_E.mjs +443 -0
- package/dist/{taxonomy-B169Nm6B.mjs → taxonomy-Dvsw6BOs.mjs} +44 -9
- package/dist/transport-BNmCqLu7.mjs +134 -0
- package/dist/types-4garmdWa.mjs +66 -0
- package/dist/{types-DSPGWjxO.d.mts → types-C8XW6L19.d.mts} +225 -4
- package/dist/{types-GaCtZ1k9.d.mts → types-CDpH6MA4.d.mts} +18 -0
- package/dist/{types-DRIKLmJI.d.mts → types-C_ly5eTp.d.mts} +17 -2
- package/dist/types-DF7ZuGGk.d.mts +118 -0
- package/dist/types-DU0bU2Wu.d.mts +2392 -0
- package/dist/{types-CwawBUTa.d.mts → types-DW_-sFyz.d.mts} +2 -1
- package/dist/{types-CSgR9nQB.mjs → types-Dq1qT19x.mjs} +1 -1
- package/dist/ui/server-runtime.d.mts +15 -15
- package/dist/ui/server-runtime.mjs +24 -20
- package/dist/url-Cac7a9QZ.mjs +33 -0
- package/dist/{user-DTLoZs16.mjs → user-BIZPzCb9.mjs} +2 -2
- package/dist/{utils-B8hBJ9Oz.mjs → utils-CMDhr5Xd.mjs} +129 -7
- package/dist/{validate-DzjCdy6v.d.mts → validate-CZvb-BKB.d.mts} +10 -7
- package/dist/{validate-DWmPO6oj.mjs → validate-DNs0pTSc.mjs} +11 -6
- package/dist/version-BTvfRGc6.mjs +6 -0
- package/dist/{widgets-BpJ8EpPd.mjs → widgets-f0ibZUIq.mjs} +46 -43
- package/dist/{wordpress-slugs-DHNR9LpG.mjs → wordpress-slugs-BhHJX8XE.mjs} +1 -1
- package/dist/{zod-generator-K91-g665.mjs → zod-generator-B7TMjyFJ.mjs} +41 -13
- package/package.json +30 -8
- package/src/components/Block.astro +50 -0
- package/src/components/Comments.astro +143 -1
- package/src/components/DinewayHead.astro +19 -2
- package/src/components/DinewayImage.astro +66 -33
- package/src/components/DinewayMedia.astro +1 -2
- package/src/components/Image.astro +85 -40
- package/src/components/InlinePortableTextEditor.tsx +12 -2
- package/src/components/JsonLdScript.astro +9 -0
- package/src/components/LiveSearch.astro +40 -4
- package/src/components/index.ts +4 -0
- package/src/components/live-search-routing.ts +30 -0
- package/src/components/portable-text-text-align.ts +15 -0
- package/src/ui.ts +2 -0
- package/dist/entity-aliases-4y93Yjuc.mjs +0 -51
- package/dist/import-4YBXbDkI.mjs +0 -684
- package/dist/runner-DzIpHGND.mjs +0 -2836
- package/dist/schema-Bsi-VpYv.mjs +0 -8
- package/dist/taxonomies-CZ-_DitR.mjs +0 -327
- package/dist/types-CuJOqHfM.d.mts +0 -758
- package/dist/version-C4gfn0PJ.mjs +0 -6
- /package/dist/{adapters-OQCImOL7.d.mts → adapters-NVSs4UH7.d.mts} +0 -0
- /package/dist/{api-tokens-CYUoFGo7.mjs → api-tokens-2r7OWi_I.mjs} +0 -0
- /package/dist/{challenge-store-DFxX0_15.mjs → challenge-store-Bjlepa2E.mjs} +0 -0
- /package/dist/{components--pg6zBvu.mjs → components-Bclf98Be.mjs} +0 -0
- /package/dist/{context-types-r8oFvyOq.mjs → context-types-DqTo6C79.mjs} +0 -0
- /package/dist/{default-B6iaLvP7.mjs → default--K40jqm0.mjs} +0 -0
- /package/dist/{email-console-BOVqIYpB.mjs → email-console-ChgKFO8-.mjs} +0 -0
- /package/dist/{escape-BDgouFFY.mjs → escape-Bd4P_xKg.mjs} +0 -0
- /package/dist/{experimental-workflows-CSMffP6q.mjs → experimental-workflows-BMsUnIAw.mjs} +0 -0
- /package/dist/{mime-CbKsKDCB.mjs → mime-CA7Lgovc.mjs} +0 -0
- /package/dist/{mode-CZqCF9dZ.mjs → mode-C4CIyjtR.mjs} +0 -0
- /package/dist/{oauth-state-store-qncPB_IU.mjs → oauth-state-store-CNoXafF7.mjs} +0 -0
- /package/dist/{oauth-user-lookup-BFjWF8wK.mjs → oauth-user-lookup-Ygw4bNyt.mjs} +0 -0
- /package/dist/{options-LsPjZlqD.mjs → options-DQPTH5n0.mjs} +0 -0
- /package/dist/{passkey-config-DzHQK90v.mjs → passkey-config-BUwu8BA3.mjs} +0 -0
- /package/dist/{patterns-DKAX6oqN.mjs → patterns-BhAvqO0S.mjs} +0 -0
- /package/dist/{provider-loader-DzUxejk7.mjs → provider-loader-D0w9dqjm.mjs} +0 -0
- /package/dist/{public-url-B_m9IwdV.mjs → public-url-BEz_sM9n.mjs} +0 -0
- /package/dist/{redirect-BjIBtDWY.mjs → redirect-wphRBv4y.mjs} +0 -0
- /package/dist/{request-cache-ho99schz.mjs → request-cache-D9GQBxMP.mjs} +0 -0
- /package/dist/{resolve-DTuDyYKs.mjs → resolve-Cb6Dbz-C.mjs} +0 -0
- /package/dist/{setup-nonce-pyGfc9hV.mjs → setup-nonce-CoyjILvW.mjs} +0 -0
- /package/dist/{sidecar-client-mJxwayYN.mjs → sidecar-client-C3mqXg4C.mjs} +0 -0
- /package/dist/{slugify-BqebcqBg.mjs → slugify-KSsVD_D3.mjs} +0 -0
- /package/dist/{ssrf-DiKqWd3N.mjs → ssrf-DWe8jwAp.mjs} +0 -0
- /package/dist/{tokens-SLmgowfd.mjs → tokens-1RK1n6ED.mjs} +0 -0
- /package/dist/{transaction-CFLhEOuH.mjs → transaction-C2EOMTJA.mjs} +0 -0
- /package/dist/{transport-BnsNxh2l.d.mts → transport-CcJu3Co8.d.mts} +0 -0
- /package/dist/{trusted-proxy-BgIIcbsN.mjs → trusted-proxy-DTXQ2IMv.mjs} +0 -0
- /package/dist/{types-CJ8DkL0q.mjs → types-B3t5cxhU.mjs} +0 -0
- /package/dist/{types-nP9vGUFq.d.mts → types-C46EvNdc.d.mts} +0 -0
- /package/dist/{types-Cg276-3z.mjs → types-C5CVgwsV.mjs} +0 -0
- /package/dist/{types-DZpT-PnG.d.mts → types-POH8PQZh.d.mts} +0 -0
- /package/dist/{types-Dryvv7LH.d.mts → types-Rc3gQqqw.d.mts} +0 -0
- /package/dist/{url-w7Mp5qAD.mjs → url-CpyFDFpO.mjs} +0 -0
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { _ as UpdateFieldInput, f as FieldValidation, g as UpdateCollectionInput, i as CollectionWithFields, o as CreateCollectionInput, s as CreateFieldInput, t as Collection, u as Field } from "./types-
|
|
2
|
-
import { f as UpdateContentInput, i as ContentItem, l as FindManyOptions, o as ContentSeoInput, r as ContentDateField, s as CreateContentInput, t as BylineSummary, u as FindManyResult } from "./types-
|
|
3
|
-
import { t as Database } from "./types-
|
|
4
|
-
import { A as PageMetadataContribution,
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
1
|
+
import { _ as UpdateFieldInput, f as FieldValidation, g as UpdateCollectionInput, i as CollectionWithFields, o as CreateCollectionInput, s as CreateFieldInput, t as Collection, u as Field } from "./types-DW_-sFyz.mjs";
|
|
2
|
+
import { f as UpdateContentInput, i as ContentItem, l as FindManyOptions, o as ContentSeoInput, r as ContentDateField, s as CreateContentInput, t as BylineSummary, u as FindManyResult } from "./types-C_ly5eTp.mjs";
|
|
3
|
+
import { t as Database } from "./types-DU0bU2Wu.mjs";
|
|
4
|
+
import { A as PageMetadataContribution, D as PageFragmentContribution, Dt as StandardPluginDefinition, F as PluginActor, G as PluginManifest, J as PluginMcpCommandTool, O as PageFragmentEvent, U as PluginDefinition, V as PluginCapability, X as PluginMcpExecutionContext, _ as FieldWidgetConfig, a as CommentAfterModerateEvent, at as PluginMcpTargetAuthorizer$1, et as PluginMcpResource, g as EmailMessage, gt as PortableTextBlockConfig, h as CronEvent, ht as PluginTargetScope, j as PageMetadataEvent, mt as PluginStorageConfig, ot as PluginMcpTool, r as CommentAfterCreateEvent, s as CommentBeforeCreateEvent, w as MediaItem$1, xt as ResolvedPlugin, yt as RequestMeta } from "./types-C8XW6L19.mjs";
|
|
5
|
+
import { d as Storage } from "./types-POH8PQZh.mjs";
|
|
6
|
+
import { r as AuthProviderDescriptor, t as AuthDescriptor } from "./types-Rc3gQqqw.mjs";
|
|
7
|
+
import { t as DatabaseDescriptor } from "./adapters-NVSs4UH7.mjs";
|
|
8
|
+
import { _ as MediaValue, m as MediaProviderDescriptor } from "./placeholder-uvNRZBX9.mjs";
|
|
9
|
+
import { r as ObjectCacheDescriptor } from "./types-DF7ZuGGk.mjs";
|
|
10
|
+
import { E as ContentBylineInput } from "./index-D4y6NGiy.mjs";
|
|
11
|
+
import { i as SiteSettings, r as SiteSettingKey } from "./types-C46EvNdc.mjs";
|
|
12
|
+
import { Dialect, Kysely, Transaction } from "kysely";
|
|
12
13
|
import { z } from "astro/zod";
|
|
13
14
|
import { z as z$1 } from "zod";
|
|
15
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
16
|
import { LiveLoader } from "astro/loaders";
|
|
15
17
|
import { MiddlewareHandler } from "astro";
|
|
16
18
|
|
|
@@ -254,17 +256,12 @@ interface WhereRange {
|
|
|
254
256
|
}
|
|
255
257
|
type WhereValue = string | string[] | WhereRange;
|
|
256
258
|
/**
|
|
257
|
-
*
|
|
259
|
+
* Fields shared by every collection filter, independent of pagination mode.
|
|
258
260
|
*/
|
|
259
|
-
interface
|
|
261
|
+
interface CollectionFilterBase$1 {
|
|
260
262
|
type: string;
|
|
261
263
|
status?: "draft" | "published" | "archived";
|
|
262
264
|
limit?: number;
|
|
263
|
-
/**
|
|
264
|
-
* Opaque cursor for keyset pagination.
|
|
265
|
-
* Pass the `nextCursor` value from a previous result to fetch the next page.
|
|
266
|
-
*/
|
|
267
|
-
cursor?: string;
|
|
268
265
|
/**
|
|
269
266
|
* Filter by field values, taxonomy terms, byline credits, or ranges.
|
|
270
267
|
*
|
|
@@ -288,6 +285,31 @@ interface CollectionFilter$1 {
|
|
|
288
285
|
*/
|
|
289
286
|
locale?: string;
|
|
290
287
|
}
|
|
288
|
+
/** Keyset-paginated collection filter. Cannot also carry an offset. */
|
|
289
|
+
interface CursorCollectionFilter$1 extends CollectionFilterBase$1 {
|
|
290
|
+
/**
|
|
291
|
+
* Opaque cursor for keyset pagination.
|
|
292
|
+
* Pass the `nextCursor` value from a previous result to fetch the next page.
|
|
293
|
+
*/
|
|
294
|
+
cursor?: string;
|
|
295
|
+
offset?: never;
|
|
296
|
+
}
|
|
297
|
+
/** Offset-paginated collection filter. Cannot also carry a cursor. */
|
|
298
|
+
interface OffsetCollectionFilter$1 extends CollectionFilterBase$1 {
|
|
299
|
+
/**
|
|
300
|
+
* Skip this many rows before returning results. Use with `limit` for numbered
|
|
301
|
+
* archives, for example `offset = (page - 1) * perPage`.
|
|
302
|
+
*/
|
|
303
|
+
offset?: number;
|
|
304
|
+
cursor?: never;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Filter for loadCollection - type is required.
|
|
308
|
+
*
|
|
309
|
+
* Cursor and offset are mutually exclusive pagination modes. Runtime callers
|
|
310
|
+
* that supply both are treated as cursor-paginated so the two skips do not stack.
|
|
311
|
+
*/
|
|
312
|
+
type CollectionFilter$1 = CursorCollectionFilter$1 | OffsetCollectionFilter$1;
|
|
291
313
|
/**
|
|
292
314
|
* Filter for loadEntry - type and id are required
|
|
293
315
|
*/
|
|
@@ -414,7 +436,7 @@ declare class ContentRepository {
|
|
|
414
436
|
/**
|
|
415
437
|
* Restore content from trash
|
|
416
438
|
*/
|
|
417
|
-
restore(type: string, id: string): Promise<
|
|
439
|
+
restore(type: string, id: string): Promise<ContentItem | null>;
|
|
418
440
|
/**
|
|
419
441
|
* Permanently delete a soft-deleted content row.
|
|
420
442
|
*/
|
|
@@ -603,6 +625,8 @@ declare class MediaRepository {
|
|
|
603
625
|
width?: number;
|
|
604
626
|
height?: number;
|
|
605
627
|
size?: number;
|
|
628
|
+
blurhash?: string;
|
|
629
|
+
dominantColor?: string;
|
|
606
630
|
}): Promise<MediaItem | null>;
|
|
607
631
|
/**
|
|
608
632
|
* Mark upload as failed
|
|
@@ -674,6 +698,7 @@ interface PublicComment {
|
|
|
674
698
|
isRegisteredUser: boolean;
|
|
675
699
|
body: string;
|
|
676
700
|
createdAt: string;
|
|
701
|
+
reactions?: Record<string, number>;
|
|
677
702
|
replies?: PublicComment[];
|
|
678
703
|
}
|
|
679
704
|
//#endregion
|
|
@@ -919,12 +944,14 @@ declare function handleContentDuplicate(db: Kysely<Database>, collection: string
|
|
|
919
944
|
*/
|
|
920
945
|
declare function handleContentDelete(db: Kysely<Database>, collection: string, id: string): Promise<ApiResult<{
|
|
921
946
|
deleted: true;
|
|
947
|
+
id: string;
|
|
922
948
|
}>>;
|
|
923
949
|
/**
|
|
924
950
|
* Restore content item from trash
|
|
925
951
|
*/
|
|
926
952
|
declare function handleContentRestore(db: Kysely<Database>, collection: string, id: string): Promise<ApiResult<{
|
|
927
953
|
restored: true;
|
|
954
|
+
item: ContentItem;
|
|
928
955
|
}>>;
|
|
929
956
|
/**
|
|
930
957
|
* Permanently delete content item (cannot be undone).
|
|
@@ -932,6 +959,7 @@ declare function handleContentRestore(db: Kysely<Database>, collection: string,
|
|
|
932
959
|
*/
|
|
933
960
|
declare function handleContentPermanentDelete(db: Kysely<Database>, collection: string, id: string): Promise<ApiResult<{
|
|
934
961
|
deleted: true;
|
|
962
|
+
id: string;
|
|
935
963
|
}>>;
|
|
936
964
|
/**
|
|
937
965
|
* List trashed content items
|
|
@@ -1008,392 +1036,443 @@ declare function handleContentTranslations(db: Kysely<Database>, collection: str
|
|
|
1008
1036
|
}>;
|
|
1009
1037
|
}>>;
|
|
1010
1038
|
//#endregion
|
|
1011
|
-
//#region src/
|
|
1012
|
-
interface CollectionDefinition {
|
|
1013
|
-
schema: {
|
|
1014
|
-
_def?: {
|
|
1015
|
-
shape?: () => Record<string, unknown>;
|
|
1016
|
-
};
|
|
1017
|
-
shape?: Record<string, unknown>;
|
|
1018
|
-
};
|
|
1019
|
-
admin: {
|
|
1020
|
-
label: string;
|
|
1021
|
-
labelSingular?: string;
|
|
1022
|
-
supports?: string[];
|
|
1023
|
-
};
|
|
1024
|
-
}
|
|
1025
|
-
type CollectionMap = Record<string, CollectionDefinition>;
|
|
1026
|
-
/**
|
|
1027
|
-
* Generate admin manifest from collections
|
|
1028
|
-
*/
|
|
1029
|
-
declare function generateManifest(collections: CollectionMap, plugins?: Record<string, {
|
|
1030
|
-
adminPages?: Array<{
|
|
1031
|
-
path: string;
|
|
1032
|
-
component: string;
|
|
1033
|
-
}>;
|
|
1034
|
-
widgets?: string[];
|
|
1035
|
-
}>): Promise<ManifestResponse>;
|
|
1036
|
-
//#endregion
|
|
1037
|
-
//#region src/api/handlers/revision.d.ts
|
|
1038
|
-
interface RevisionListResponse {
|
|
1039
|
-
items: Revision[];
|
|
1040
|
-
total: number;
|
|
1041
|
-
}
|
|
1042
|
-
interface RevisionResponse {
|
|
1043
|
-
item: Revision;
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* List revisions for a content entry
|
|
1047
|
-
*/
|
|
1048
|
-
declare function handleRevisionList(db: Kysely<Database>, collection: string, entryId: string, params?: {
|
|
1049
|
-
limit?: number;
|
|
1050
|
-
}): Promise<ApiResult<RevisionListResponse>>;
|
|
1051
|
-
/**
|
|
1052
|
-
* Get a specific revision
|
|
1053
|
-
*/
|
|
1054
|
-
declare function handleRevisionGet(db: Kysely<Database>, revisionId: string): Promise<ApiResult<RevisionResponse>>;
|
|
1055
|
-
/**
|
|
1056
|
-
* Restore a revision (updates content to this revision's data and creates new revision)
|
|
1057
|
-
*/
|
|
1058
|
-
declare function handleRevisionRestore(db: Kysely<Database>, revisionId: string, callerUserId: string): Promise<ApiResult<ContentResponse>>;
|
|
1059
|
-
//#endregion
|
|
1060
|
-
//#region src/api/handlers/media.d.ts
|
|
1061
|
-
interface MediaListResponse {
|
|
1062
|
-
items: MediaItem[];
|
|
1063
|
-
nextCursor?: string;
|
|
1064
|
-
}
|
|
1065
|
-
interface MediaResponse {
|
|
1066
|
-
item: MediaItem;
|
|
1067
|
-
}
|
|
1068
|
-
/**
|
|
1069
|
-
* List media items
|
|
1070
|
-
*/
|
|
1071
|
-
declare function handleMediaList(db: Kysely<Database>, params: {
|
|
1072
|
-
cursor?: string;
|
|
1073
|
-
limit?: number;
|
|
1074
|
-
mimeType?: string | readonly string[];
|
|
1075
|
-
q?: string;
|
|
1076
|
-
}): Promise<ApiResult<MediaListResponse>>;
|
|
1077
|
-
/**
|
|
1078
|
-
* Get single media item
|
|
1079
|
-
*/
|
|
1080
|
-
declare function handleMediaGet(db: Kysely<Database>, id: string): Promise<ApiResult<MediaResponse>>;
|
|
1081
|
-
/**
|
|
1082
|
-
* Create media item (after file upload)
|
|
1083
|
-
*/
|
|
1084
|
-
declare function handleMediaCreate(db: Kysely<Database>, input: {
|
|
1085
|
-
filename: string;
|
|
1086
|
-
mimeType: string;
|
|
1087
|
-
size?: number;
|
|
1088
|
-
width?: number;
|
|
1089
|
-
height?: number;
|
|
1090
|
-
alt?: string;
|
|
1091
|
-
storageKey: string;
|
|
1092
|
-
contentHash?: string;
|
|
1093
|
-
blurhash?: string;
|
|
1094
|
-
dominantColor?: string;
|
|
1095
|
-
authorId?: string;
|
|
1096
|
-
}): Promise<ApiResult<MediaResponse>>;
|
|
1097
|
-
/**
|
|
1098
|
-
* Update media metadata
|
|
1099
|
-
*/
|
|
1100
|
-
declare function handleMediaUpdate(db: Kysely<Database>, id: string, input: {
|
|
1101
|
-
alt?: string;
|
|
1102
|
-
caption?: string;
|
|
1103
|
-
width?: number;
|
|
1104
|
-
height?: number;
|
|
1105
|
-
}): Promise<ApiResult<MediaResponse>>;
|
|
1106
|
-
/**
|
|
1107
|
-
* Delete media item
|
|
1108
|
-
*/
|
|
1109
|
-
declare function handleMediaDelete(db: Kysely<Database>, id: string): Promise<ApiResult<{
|
|
1110
|
-
deleted: true;
|
|
1111
|
-
}>>;
|
|
1112
|
-
//#endregion
|
|
1113
|
-
//#region src/schema/registry.d.ts
|
|
1114
|
-
/**
|
|
1115
|
-
* Error thrown when a schema operation fails
|
|
1116
|
-
*/
|
|
1117
|
-
declare class SchemaError extends Error {
|
|
1118
|
-
code: string;
|
|
1119
|
-
details?: Record<string, unknown> | undefined;
|
|
1120
|
-
constructor(message: string, code: string, details?: Record<string, unknown> | undefined);
|
|
1121
|
-
}
|
|
1039
|
+
//#region src/plugins/email.d.ts
|
|
1122
1040
|
/**
|
|
1123
|
-
*
|
|
1041
|
+
* EmailPipeline orchestrates email delivery through the plugin hook system.
|
|
1124
1042
|
*
|
|
1125
|
-
*
|
|
1126
|
-
*
|
|
1043
|
+
* The pipeline runs in three stages:
|
|
1044
|
+
* 1. email:beforeSend — middleware hooks that can transform or cancel messages
|
|
1045
|
+
* 2. email:deliver — exclusive hook dispatching to the selected provider
|
|
1046
|
+
* 3. email:afterSend — fire-and-forget hooks for logging/analytics
|
|
1127
1047
|
*/
|
|
1128
|
-
declare class
|
|
1129
|
-
private
|
|
1130
|
-
constructor(
|
|
1131
|
-
/**
|
|
1132
|
-
* List all collections
|
|
1133
|
-
*/
|
|
1134
|
-
listCollections(): Promise<Collection[]>;
|
|
1135
|
-
/**
|
|
1136
|
-
* List all collections with their fields using bounded query shapes.
|
|
1137
|
-
*/
|
|
1138
|
-
listCollectionsWithFields(): Promise<CollectionWithFields[]>;
|
|
1139
|
-
/**
|
|
1140
|
-
* Get a collection by slug
|
|
1141
|
-
*/
|
|
1142
|
-
getCollection(slug: string): Promise<Collection | null>;
|
|
1143
|
-
/**
|
|
1144
|
-
* Get a collection with all its fields
|
|
1145
|
-
*/
|
|
1146
|
-
getCollectionWithFields(slug: string): Promise<CollectionWithFields | null>;
|
|
1048
|
+
declare class EmailPipeline {
|
|
1049
|
+
private pipeline;
|
|
1050
|
+
constructor(pipeline: HookPipeline);
|
|
1147
1051
|
/**
|
|
1148
|
-
*
|
|
1052
|
+
* Replace the underlying hook pipeline.
|
|
1053
|
+
*
|
|
1054
|
+
* Called by the runtime when rebuilding the hook pipeline after a
|
|
1055
|
+
* plugin is enabled or disabled, so the email pipeline dispatches
|
|
1056
|
+
* to the current set of active hooks.
|
|
1149
1057
|
*/
|
|
1150
|
-
|
|
1058
|
+
setPipeline(pipeline: HookPipeline): void;
|
|
1151
1059
|
/**
|
|
1152
|
-
*
|
|
1060
|
+
* Send an email through the full pipeline.
|
|
1061
|
+
*
|
|
1062
|
+
* @param message - The email to send
|
|
1063
|
+
* @param source - Where the email originated ("system" for auth, plugin ID for plugins)
|
|
1064
|
+
* @throws EmailNotConfiguredError if no provider is selected
|
|
1065
|
+
* @throws EmailRecursionError if called re-entrantly from within a hook
|
|
1066
|
+
* @throws Error if the provider handler throws
|
|
1153
1067
|
*/
|
|
1154
|
-
|
|
1155
|
-
private validateUrlPattern;
|
|
1156
|
-
private checkLabelUniqueness;
|
|
1157
|
-
private checkUrlPatternUniqueness;
|
|
1068
|
+
send(message: EmailMessage, source: string): Promise<void>;
|
|
1158
1069
|
/**
|
|
1159
|
-
*
|
|
1070
|
+
* Inner send implementation, separated from the recursion guard.
|
|
1160
1071
|
*/
|
|
1161
|
-
|
|
1162
|
-
force?: boolean;
|
|
1163
|
-
}): Promise<void>;
|
|
1072
|
+
private sendInner;
|
|
1164
1073
|
/**
|
|
1165
|
-
*
|
|
1074
|
+
* Check if an email provider is configured and available.
|
|
1075
|
+
*
|
|
1076
|
+
* Returns true if an email:deliver provider is selected in the exclusive
|
|
1077
|
+
* hook system. Plugins and auth code use this to decide whether to show
|
|
1078
|
+
* "send invite" vs "copy invite link" UI.
|
|
1166
1079
|
*/
|
|
1167
|
-
|
|
1080
|
+
isAvailable(): boolean;
|
|
1081
|
+
}
|
|
1082
|
+
//#endregion
|
|
1083
|
+
//#region src/plugins/context.d.ts
|
|
1084
|
+
/**
|
|
1085
|
+
* Options for creating site info
|
|
1086
|
+
*/
|
|
1087
|
+
interface SiteInfoOptions {
|
|
1088
|
+
/** Site name from options table */
|
|
1089
|
+
siteName?: string;
|
|
1090
|
+
/** Site URL from options table or Astro config */
|
|
1091
|
+
siteUrl?: string;
|
|
1092
|
+
/** Site locale from options table */
|
|
1093
|
+
locale?: string;
|
|
1094
|
+
}
|
|
1095
|
+
interface PluginContextFactoryOptions {
|
|
1096
|
+
db: Kysely<Database>;
|
|
1168
1097
|
/**
|
|
1169
|
-
*
|
|
1098
|
+
* Resolver for the current database connection. When omitted, `db` is used.
|
|
1099
|
+
* Runtime code provides this so plugin hooks and routes honor request-scoped
|
|
1100
|
+
* database overrides from preview/playground sidecars.
|
|
1170
1101
|
*/
|
|
1171
|
-
|
|
1102
|
+
getDb?: () => Kysely<Database>;
|
|
1172
1103
|
/**
|
|
1173
|
-
*
|
|
1104
|
+
* Storage backend for direct media uploads.
|
|
1105
|
+
* If not provided, upload() will throw.
|
|
1174
1106
|
*/
|
|
1175
|
-
|
|
1107
|
+
storage?: Storage;
|
|
1176
1108
|
/**
|
|
1177
|
-
*
|
|
1178
|
-
*
|
|
1179
|
-
* This repairs interrupted schema creation where the metadata row exists but
|
|
1180
|
-
* the physical `ec_*` table was not created.
|
|
1109
|
+
* Function to generate upload URLs for media.
|
|
1110
|
+
* If not provided, media write operations will throw.
|
|
1181
1111
|
*/
|
|
1182
|
-
|
|
1112
|
+
getUploadUrl?: (filename: string, contentType: string) => Promise<{
|
|
1113
|
+
uploadUrl: string;
|
|
1114
|
+
mediaId: string;
|
|
1115
|
+
}>;
|
|
1183
1116
|
/**
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
* This repairs interrupted field creation where `_dineway_fields` was written
|
|
1187
|
-
* but `ALTER TABLE ec_* ADD COLUMN` did not complete.
|
|
1117
|
+
* Site information for ctx.site and ctx.url().
|
|
1118
|
+
* If not provided, site info will have empty defaults.
|
|
1188
1119
|
*/
|
|
1189
|
-
|
|
1120
|
+
siteInfo?: SiteInfoOptions;
|
|
1190
1121
|
/**
|
|
1191
|
-
*
|
|
1122
|
+
* Callback to notify the cron scheduler that the next due time may have changed.
|
|
1123
|
+
* If not provided, ctx.cron will not be available.
|
|
1192
1124
|
*/
|
|
1193
|
-
|
|
1125
|
+
cronReschedule?: () => void;
|
|
1194
1126
|
/**
|
|
1195
|
-
*
|
|
1196
|
-
*
|
|
1197
|
-
* Schema writes must not first-time enable FTS. Initial enablement stays in
|
|
1198
|
-
* explicit seed/import/admin flows where FTS failures can be handled deliberately.
|
|
1127
|
+
* Email pipeline instance for ctx.email.
|
|
1128
|
+
* If not provided (or no provider configured), ctx.email will be undefined.
|
|
1199
1129
|
*/
|
|
1200
|
-
|
|
1130
|
+
emailPipeline?: EmailPipeline;
|
|
1201
1131
|
/**
|
|
1202
|
-
*
|
|
1132
|
+
* Trusted reverse-proxy headers for request metadata IP extraction.
|
|
1203
1133
|
*/
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1134
|
+
trustedProxyHeaders?: string[];
|
|
1135
|
+
}
|
|
1136
|
+
//#endregion
|
|
1137
|
+
//#region src/plugins/hooks.d.ts
|
|
1138
|
+
type HookNameV2 = "plugin:install" | "plugin:activate" | "plugin:deactivate" | "plugin:uninstall" | "content:beforeSave" | "content:afterSave" | "content:beforeDelete" | "content:afterDelete" | "content:afterPublish" | "content:afterUnpublish" | "content:afterRestore" | "content:afterSchedule" | "content:afterUnschedule" | "media:beforeUpload" | "media:afterUpload" | "cron" | "email:beforeSend" | "email:deliver" | "email:afterSend" | "comment:beforeCreate" | "comment:moderate" | "comment:afterCreate" | "comment:afterModerate" | "page:metadata" | "page:fragments";
|
|
1139
|
+
/**
|
|
1140
|
+
* Hook execution result
|
|
1141
|
+
*/
|
|
1142
|
+
interface HookResult<T> {
|
|
1143
|
+
success: boolean;
|
|
1144
|
+
value?: T;
|
|
1145
|
+
error?: Error;
|
|
1146
|
+
pluginId: string;
|
|
1147
|
+
duration: number;
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Hook pipeline for executing hooks in order
|
|
1151
|
+
*/
|
|
1152
|
+
declare class HookPipeline {
|
|
1153
|
+
private hooks;
|
|
1154
|
+
private pluginMap;
|
|
1155
|
+
private contextFactory;
|
|
1156
|
+
/** Stored so setContextFactory can merge incrementally. */
|
|
1157
|
+
private contextFactoryOptions;
|
|
1158
|
+
/** Hook names where at least one handler declared exclusive: true */
|
|
1159
|
+
private exclusiveHookNames;
|
|
1160
|
+
/**
|
|
1161
|
+
* Selected provider plugin ID for each exclusive hook.
|
|
1162
|
+
* Set by the PluginManager after resolution.
|
|
1207
1163
|
*/
|
|
1208
|
-
|
|
1164
|
+
private exclusiveSelections;
|
|
1165
|
+
constructor(plugins: ResolvedPlugin[], factoryOptions?: PluginContextFactoryOptions);
|
|
1209
1166
|
/**
|
|
1210
|
-
*
|
|
1167
|
+
* Set or update the context factory options.
|
|
1168
|
+
*
|
|
1169
|
+
* When called on a pipeline that already has a factory, the new options
|
|
1170
|
+
* are merged on top of the existing ones so that callers don't need to
|
|
1171
|
+
* repeat every field (e.g. adding `cronReschedule` without losing
|
|
1172
|
+
* `storage` / `getUploadUrl`).
|
|
1211
1173
|
*/
|
|
1212
|
-
|
|
1174
|
+
setContextFactory(options: Partial<PluginContextFactoryOptions>): void;
|
|
1213
1175
|
/**
|
|
1214
|
-
*
|
|
1176
|
+
* Get context for a plugin
|
|
1215
1177
|
*/
|
|
1216
|
-
private
|
|
1178
|
+
private getContext;
|
|
1217
1179
|
/**
|
|
1218
|
-
*
|
|
1180
|
+
* Get typed hooks for a specific hook name.
|
|
1181
|
+
* The internal map stores ResolvedHook<unknown>, but we know each name
|
|
1182
|
+
* maps to a specific handler type via HookHandlerMap.
|
|
1183
|
+
*
|
|
1184
|
+
* Exclusive hooks that have a selected provider are filtered out — they
|
|
1185
|
+
* should only run via invokeExclusiveHook(), not in the regular pipeline.
|
|
1219
1186
|
*/
|
|
1220
|
-
private
|
|
1187
|
+
private getTypedHooks;
|
|
1221
1188
|
/**
|
|
1222
|
-
*
|
|
1189
|
+
* Register all hooks from plugins.
|
|
1190
|
+
*
|
|
1191
|
+
* Registers each hook name individually to preserve type safety. The
|
|
1192
|
+
* internal map stores ResolvedHook<unknown> since it's keyed by string,
|
|
1193
|
+
* but getTypedHooks() restores the correct handler type on retrieval.
|
|
1223
1194
|
*/
|
|
1224
|
-
private
|
|
1195
|
+
private registerPlugins;
|
|
1225
1196
|
/**
|
|
1226
|
-
*
|
|
1197
|
+
* Maps hook names to the capability required to register them.
|
|
1198
|
+
*
|
|
1199
|
+
* Hooks not listed here have no capability requirement (e.g. lifecycle
|
|
1200
|
+
* hooks, cron). Any plugin declaring a listed hook without the required
|
|
1201
|
+
* capability will have that hook silently skipped at registration time.
|
|
1227
1202
|
*/
|
|
1228
|
-
private
|
|
1203
|
+
private static readonly HOOK_REQUIRED_CAPABILITY;
|
|
1229
1204
|
/**
|
|
1230
|
-
*
|
|
1205
|
+
* Register a single plugin's hook by name
|
|
1231
1206
|
*/
|
|
1232
|
-
private
|
|
1207
|
+
private registerPluginHook;
|
|
1233
1208
|
/**
|
|
1234
|
-
*
|
|
1209
|
+
* Register a single hook
|
|
1235
1210
|
*/
|
|
1236
|
-
private
|
|
1211
|
+
private registerHook;
|
|
1237
1212
|
/**
|
|
1238
|
-
*
|
|
1213
|
+
* Sort hooks by priority and dependencies
|
|
1239
1214
|
*/
|
|
1240
|
-
private
|
|
1215
|
+
private sortHooks;
|
|
1241
1216
|
/**
|
|
1242
|
-
*
|
|
1217
|
+
* Execute a hook with timeout
|
|
1218
|
+
*/
|
|
1219
|
+
private executeWithTimeout;
|
|
1220
|
+
/**
|
|
1221
|
+
* Run plugin:install hooks
|
|
1222
|
+
*/
|
|
1223
|
+
runPluginInstall(pluginId: string): Promise<HookResult<void>[]>;
|
|
1224
|
+
/**
|
|
1225
|
+
* Run plugin:activate hooks
|
|
1226
|
+
*/
|
|
1227
|
+
runPluginActivate(pluginId: string): Promise<HookResult<void>[]>;
|
|
1228
|
+
/**
|
|
1229
|
+
* Run plugin:deactivate hooks
|
|
1230
|
+
*/
|
|
1231
|
+
runPluginDeactivate(pluginId: string): Promise<HookResult<void>[]>;
|
|
1232
|
+
/**
|
|
1233
|
+
* Run plugin:uninstall hooks
|
|
1234
|
+
*/
|
|
1235
|
+
runPluginUninstall(pluginId: string, deleteData: boolean): Promise<HookResult<void>[]>;
|
|
1236
|
+
private runLifecycleHook;
|
|
1237
|
+
/**
|
|
1238
|
+
* Run content:beforeSave hooks
|
|
1239
|
+
* Returns modified content from the pipeline
|
|
1240
|
+
*/
|
|
1241
|
+
runContentBeforeSave(content: Record<string, unknown>, collection: string, isNew: boolean): Promise<{
|
|
1242
|
+
content: Record<string, unknown>;
|
|
1243
|
+
results: HookResult<Record<string, unknown>>[];
|
|
1244
|
+
}>;
|
|
1245
|
+
/**
|
|
1246
|
+
* Run content:afterSave hooks
|
|
1247
|
+
*/
|
|
1248
|
+
runContentAfterSave(content: Record<string, unknown>, collection: string, isNew: boolean): Promise<HookResult<void>[]>;
|
|
1249
|
+
/**
|
|
1250
|
+
* Run content:beforeDelete hooks
|
|
1251
|
+
* Returns whether deletion is allowed
|
|
1252
|
+
*/
|
|
1253
|
+
runContentBeforeDelete(id: string, collection: string): Promise<{
|
|
1254
|
+
allowed: boolean;
|
|
1255
|
+
results: HookResult<boolean>[];
|
|
1256
|
+
}>;
|
|
1257
|
+
/**
|
|
1258
|
+
* Run content:afterDelete hooks
|
|
1259
|
+
*/
|
|
1260
|
+
runContentAfterDelete(id: string, collection: string, permanent: boolean): Promise<HookResult<void>[]>;
|
|
1261
|
+
/**
|
|
1262
|
+
* Run content:afterPublish hooks (fire-and-forget).
|
|
1263
|
+
*/
|
|
1264
|
+
runContentAfterPublish(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
1265
|
+
/**
|
|
1266
|
+
* Run content:afterUnpublish hooks (fire-and-forget).
|
|
1267
|
+
*/
|
|
1268
|
+
runContentAfterUnpublish(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
1269
|
+
/**
|
|
1270
|
+
* Run content:afterRestore hooks (fire-and-forget).
|
|
1271
|
+
*/
|
|
1272
|
+
runContentAfterRestore(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Run content:afterSchedule hooks (fire-and-forget).
|
|
1275
|
+
*/
|
|
1276
|
+
runContentAfterSchedule(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
1277
|
+
/**
|
|
1278
|
+
* Run content:afterUnschedule hooks (fire-and-forget).
|
|
1279
|
+
*/
|
|
1280
|
+
runContentAfterUnschedule(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
1281
|
+
private runContentStateChangeHook;
|
|
1282
|
+
/**
|
|
1283
|
+
* Run media:beforeUpload hooks
|
|
1284
|
+
*/
|
|
1285
|
+
runMediaBeforeUpload(file: {
|
|
1286
|
+
name: string;
|
|
1287
|
+
type: string;
|
|
1288
|
+
size: number;
|
|
1289
|
+
}): Promise<{
|
|
1290
|
+
file: {
|
|
1291
|
+
name: string;
|
|
1292
|
+
type: string;
|
|
1293
|
+
size: number;
|
|
1294
|
+
};
|
|
1295
|
+
results: HookResult<{
|
|
1296
|
+
name: string;
|
|
1297
|
+
type: string;
|
|
1298
|
+
size: number;
|
|
1299
|
+
}>[];
|
|
1300
|
+
}>;
|
|
1301
|
+
/**
|
|
1302
|
+
* Run media:afterUpload hooks
|
|
1303
|
+
*/
|
|
1304
|
+
runMediaAfterUpload(media: {
|
|
1305
|
+
id: string;
|
|
1306
|
+
filename: string;
|
|
1307
|
+
mimeType: string;
|
|
1308
|
+
size: number | null;
|
|
1309
|
+
url: string;
|
|
1310
|
+
createdAt: string;
|
|
1311
|
+
}): Promise<HookResult<void>[]>;
|
|
1312
|
+
/**
|
|
1313
|
+
* Invoke the cron hook for a specific plugin.
|
|
1243
1314
|
*
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
|
|
1315
|
+
* Unlike other hooks which broadcast to all plugins, the cron hook is
|
|
1316
|
+
* dispatched only to the target plugin — the one that owns the task.
|
|
1317
|
+
*/
|
|
1318
|
+
invokeCronHook(pluginId: string, event: CronEvent): Promise<HookResult<void>>;
|
|
1319
|
+
/**
|
|
1320
|
+
* Run email:beforeSend hooks (middleware pipeline).
|
|
1247
1321
|
*
|
|
1248
|
-
*
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1322
|
+
* Each handler receives the message and returns a modified message or
|
|
1323
|
+
* `false` to cancel delivery. The pipeline chains message transformations —
|
|
1324
|
+
* each handler receives the output of the previous one.
|
|
1251
1325
|
*/
|
|
1252
|
-
|
|
1326
|
+
runEmailBeforeSend(message: EmailMessage, source: string): Promise<{
|
|
1327
|
+
message: EmailMessage | false;
|
|
1328
|
+
results: HookResult<EmailMessage | false>[];
|
|
1329
|
+
}>;
|
|
1253
1330
|
/**
|
|
1254
|
-
*
|
|
1331
|
+
* Run email:afterSend hooks (fire-and-forget).
|
|
1332
|
+
*
|
|
1333
|
+
* Errors are logged but don't propagate — they don't affect the caller.
|
|
1255
1334
|
*/
|
|
1256
|
-
|
|
1335
|
+
runEmailAfterSend(message: EmailMessage, source: string): Promise<HookResult<void>[]>;
|
|
1257
1336
|
/**
|
|
1258
|
-
*
|
|
1337
|
+
* Run comment:beforeCreate hooks (middleware pipeline).
|
|
1338
|
+
*
|
|
1339
|
+
* Each handler receives the event and returns a modified event or
|
|
1340
|
+
* `false` to reject the comment. The pipeline chains transformations —
|
|
1341
|
+
* each handler receives the output of the previous one.
|
|
1259
1342
|
*/
|
|
1260
|
-
|
|
1343
|
+
runCommentBeforeCreate(event: CommentBeforeCreateEvent): Promise<CommentBeforeCreateEvent | false>;
|
|
1261
1344
|
/**
|
|
1262
|
-
*
|
|
1345
|
+
* Run comment:afterCreate hooks (fire-and-forget).
|
|
1346
|
+
*
|
|
1347
|
+
* Errors are logged but don't propagate — they don't affect the caller.
|
|
1263
1348
|
*/
|
|
1264
|
-
|
|
1349
|
+
runCommentAfterCreate(event: CommentAfterCreateEvent): Promise<void>;
|
|
1265
1350
|
/**
|
|
1266
|
-
*
|
|
1351
|
+
* Run comment:afterModerate hooks (fire-and-forget).
|
|
1267
1352
|
*
|
|
1268
|
-
*
|
|
1269
|
-
* corresponding entry in _dineway_collections.
|
|
1353
|
+
* Errors are logged but don't propagate — they don't affect the caller.
|
|
1270
1354
|
*/
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1355
|
+
runCommentAfterModerate(event: CommentAfterModerateEvent): Promise<void>;
|
|
1356
|
+
/**
|
|
1357
|
+
* Run page:metadata hooks. Each handler returns contributions that are
|
|
1358
|
+
* merged by the metadata collector. Errors are logged but don't propagate.
|
|
1359
|
+
*/
|
|
1360
|
+
runPageMetadata(event: PageMetadataEvent): Promise<Array<{
|
|
1361
|
+
pluginId: string;
|
|
1362
|
+
contributions: PageMetadataContribution[];
|
|
1275
1363
|
}>>;
|
|
1276
1364
|
/**
|
|
1277
|
-
*
|
|
1278
|
-
*
|
|
1279
|
-
* Creates a _dineway_collections entry for an existing ec_* table.
|
|
1365
|
+
* Run page:fragments hooks. Only trusted plugins should be registered
|
|
1366
|
+
* for this hook. Errors are logged but don't propagate.
|
|
1280
1367
|
*/
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}): Promise<Collection>;
|
|
1368
|
+
runPageFragments(event: PageFragmentEvent): Promise<Array<{
|
|
1369
|
+
pluginId: string;
|
|
1370
|
+
contributions: PageFragmentContribution[];
|
|
1371
|
+
}>>;
|
|
1286
1372
|
/**
|
|
1287
|
-
*
|
|
1373
|
+
* Check if any hooks are registered for a given name
|
|
1288
1374
|
*/
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
content?: PortableTextBlock$1[];
|
|
1351
|
-
previewMediaId?: string | null;
|
|
1375
|
+
hasHooks(name: HookNameV2): boolean;
|
|
1376
|
+
/**
|
|
1377
|
+
* Get hook count for debugging
|
|
1378
|
+
*/
|
|
1379
|
+
getHookCount(name: HookNameV2): number;
|
|
1380
|
+
/**
|
|
1381
|
+
* Get all registered hook names
|
|
1382
|
+
*/
|
|
1383
|
+
getRegisteredHooks(): HookNameV2[];
|
|
1384
|
+
/**
|
|
1385
|
+
* Returns hook names where at least one handler declared exclusive: true
|
|
1386
|
+
*/
|
|
1387
|
+
getRegisteredExclusiveHooks(): string[];
|
|
1388
|
+
/**
|
|
1389
|
+
* Check if a hook is exclusive
|
|
1390
|
+
*/
|
|
1391
|
+
isExclusiveHook(name: string): boolean;
|
|
1392
|
+
/**
|
|
1393
|
+
* Set the selected provider for an exclusive hook.
|
|
1394
|
+
* Called by PluginManager after resolution.
|
|
1395
|
+
*/
|
|
1396
|
+
setExclusiveSelection(hookName: string, pluginId: string): void;
|
|
1397
|
+
/**
|
|
1398
|
+
* Clear the selected provider for an exclusive hook.
|
|
1399
|
+
*/
|
|
1400
|
+
clearExclusiveSelection(hookName: string): void;
|
|
1401
|
+
/**
|
|
1402
|
+
* Get the selected provider for an exclusive hook (if any).
|
|
1403
|
+
*/
|
|
1404
|
+
getExclusiveSelection(hookName: string): string | undefined;
|
|
1405
|
+
/**
|
|
1406
|
+
* Get all plugins that registered a handler for a given exclusive hook.
|
|
1407
|
+
*/
|
|
1408
|
+
getExclusiveHookProviders(hookName: string): Array<{
|
|
1409
|
+
pluginId: string;
|
|
1410
|
+
}>;
|
|
1411
|
+
/**
|
|
1412
|
+
* Get all plugins that registered a non-exclusive handler for a given hook,
|
|
1413
|
+
* preserving priority order. This partitions with getExclusiveHookProviders().
|
|
1414
|
+
*/
|
|
1415
|
+
getHookProviders(hookName: string): Array<{
|
|
1416
|
+
pluginId: string;
|
|
1417
|
+
}>;
|
|
1418
|
+
/**
|
|
1419
|
+
* Invoke an exclusive hook — dispatch only to the selected provider.
|
|
1420
|
+
* Returns null if no provider is selected or if the selected hook
|
|
1421
|
+
* is not found in the pipeline.
|
|
1422
|
+
*
|
|
1423
|
+
* This is a generic dispatch used by the email pipeline and other
|
|
1424
|
+
* exclusive hook consumers. The handler type is unknown — callers
|
|
1425
|
+
* must know the expected signature.
|
|
1426
|
+
*
|
|
1427
|
+
* Errors are isolated: a failing handler returns an error result
|
|
1428
|
+
* instead of propagating the exception to the caller.
|
|
1429
|
+
*/
|
|
1430
|
+
invokeExclusiveHook(hookName: string, event: unknown): Promise<{
|
|
1431
|
+
result: unknown;
|
|
1432
|
+
pluginId: string;
|
|
1433
|
+
error?: Error;
|
|
1434
|
+
duration: number;
|
|
1435
|
+
} | null>;
|
|
1352
1436
|
}
|
|
1353
1437
|
/**
|
|
1354
|
-
*
|
|
1438
|
+
* Create a hook pipeline from plugins
|
|
1355
1439
|
*/
|
|
1356
|
-
|
|
1357
|
-
/** Filter by source */
|
|
1358
|
-
source?: SectionSource;
|
|
1359
|
-
/** Search title, description, keywords */
|
|
1360
|
-
search?: string;
|
|
1361
|
-
/** Limit results */
|
|
1362
|
-
limit?: number;
|
|
1363
|
-
/** Cursor for pagination */
|
|
1364
|
-
cursor?: string;
|
|
1365
|
-
}
|
|
1440
|
+
declare function createHookPipeline(plugins: ResolvedPlugin[], factoryOptions?: PluginContextFactoryOptions): HookPipeline;
|
|
1366
1441
|
//#endregion
|
|
1367
|
-
//#region src/
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1442
|
+
//#region src/plugins/mcp.d.ts
|
|
1443
|
+
interface RegisteredPluginMcpTool {
|
|
1444
|
+
pluginId: string;
|
|
1445
|
+
pluginVersion: string;
|
|
1446
|
+
tool: PluginMcpTool;
|
|
1447
|
+
authorizeTarget?: PluginMcpTargetAuthorizer$1;
|
|
1448
|
+
}
|
|
1449
|
+
interface RegisteredPluginMcpResource {
|
|
1450
|
+
pluginId: string;
|
|
1451
|
+
pluginVersion: string;
|
|
1452
|
+
resource: PluginMcpResource;
|
|
1453
|
+
authorizeTarget?: PluginMcpTargetAuthorizer$1;
|
|
1454
|
+
}
|
|
1455
|
+
interface PluginMcpRegistry {
|
|
1456
|
+
tools: RegisteredPluginMcpTool[];
|
|
1457
|
+
resources: RegisteredPluginMcpResource[];
|
|
1458
|
+
}
|
|
1459
|
+
interface PluginMcpTargetAuthorizationRequest {
|
|
1460
|
+
restaurantPermission: string;
|
|
1461
|
+
target: PluginTargetScope;
|
|
1462
|
+
context: PluginMcpExecutionContext;
|
|
1463
|
+
}
|
|
1464
|
+
type PluginMcpTargetAuthorizer = (request: PluginMcpTargetAuthorizationRequest) => Promise<void>;
|
|
1465
|
+
interface PluginMcpReviewMetadata {
|
|
1466
|
+
hitlRequestId?: string;
|
|
1467
|
+
quickActionHash?: string;
|
|
1468
|
+
}
|
|
1469
|
+
interface PluginMcpCommandExecutionRequest {
|
|
1470
|
+
target?: PluginTargetScope;
|
|
1471
|
+
review: PluginMcpReviewMetadata;
|
|
1472
|
+
}
|
|
1473
|
+
type PluginMcpCommandExecutor = (command: RegisteredPluginMcpTool & {
|
|
1474
|
+
tool: PluginMcpCommandTool;
|
|
1475
|
+
}, input: Record<string, unknown>, context: PluginMcpExecutionContext, request: PluginMcpCommandExecutionRequest) => Promise<Record<string, unknown>>;
|
|
1397
1476
|
//#endregion
|
|
1398
1477
|
//#region src/plugins/sandbox/types.d.ts
|
|
1399
1478
|
/**
|
|
@@ -1497,6 +1576,8 @@ interface SerializedRequest {
|
|
|
1497
1576
|
headers: Record<string, string>;
|
|
1498
1577
|
/** Normalized request metadata extracted before RPC serialization */
|
|
1499
1578
|
meta: RequestMeta;
|
|
1579
|
+
/** Safe authenticated actor metadata; null for unauthenticated public routes. */
|
|
1580
|
+
actor?: PluginActor | null;
|
|
1500
1581
|
}
|
|
1501
1582
|
/**
|
|
1502
1583
|
* Sandbox runner interface.
|
|
@@ -1543,1316 +1624,1654 @@ interface SandboxRunner {
|
|
|
1543
1624
|
*/
|
|
1544
1625
|
type SandboxRunnerFactory = (options: SandboxOptions) => SandboxRunner;
|
|
1545
1626
|
//#endregion
|
|
1546
|
-
//#region src/
|
|
1547
|
-
/**
|
|
1548
|
-
* Portable Text Types
|
|
1549
|
-
*
|
|
1550
|
-
* Defines the structure of Portable Text blocks used in Dineway.
|
|
1551
|
-
*/
|
|
1627
|
+
//#region src/plugins/routes.d.ts
|
|
1552
1628
|
/**
|
|
1553
|
-
*
|
|
1629
|
+
* Result from a route invocation
|
|
1554
1630
|
*/
|
|
1555
|
-
interface
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1631
|
+
interface RouteResult<T = unknown> {
|
|
1632
|
+
success: boolean;
|
|
1633
|
+
data?: T;
|
|
1634
|
+
error?: {
|
|
1635
|
+
code: string;
|
|
1636
|
+
message: string;
|
|
1637
|
+
details?: unknown;
|
|
1638
|
+
};
|
|
1639
|
+
status: number;
|
|
1560
1640
|
}
|
|
1561
1641
|
/**
|
|
1562
|
-
*
|
|
1642
|
+
* Route invocation options
|
|
1563
1643
|
*/
|
|
1564
|
-
interface
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1644
|
+
interface InvokeRouteOptions {
|
|
1645
|
+
/** The original request */
|
|
1646
|
+
request: Request;
|
|
1647
|
+
/** Request body (already parsed) */
|
|
1648
|
+
body?: unknown;
|
|
1649
|
+
/** Exact request bytes for routes that declare body: "raw". */
|
|
1650
|
+
rawBody?: Uint8Array;
|
|
1651
|
+
/** Normalized authenticated actor supplied by the core route boundary. */
|
|
1652
|
+
actor?: PluginActor | null;
|
|
1568
1653
|
}
|
|
1569
1654
|
/**
|
|
1570
|
-
*
|
|
1655
|
+
* Error class for plugin routes
|
|
1656
|
+
* Allows plugins to return structured errors with specific HTTP status codes
|
|
1571
1657
|
*/
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1658
|
+
declare class PluginRouteError extends Error {
|
|
1659
|
+
code: string;
|
|
1660
|
+
status: number;
|
|
1661
|
+
details?: unknown | undefined;
|
|
1662
|
+
constructor(code: string, message: string, status?: number, details?: unknown | undefined);
|
|
1663
|
+
/**
|
|
1664
|
+
* Create a bad request error (400)
|
|
1665
|
+
*/
|
|
1666
|
+
static badRequest(message: string, details?: unknown): PluginRouteError;
|
|
1667
|
+
/**
|
|
1668
|
+
* Create an unauthorized error (401)
|
|
1669
|
+
*/
|
|
1670
|
+
static unauthorized(message?: string): PluginRouteError;
|
|
1671
|
+
/**
|
|
1672
|
+
* Create a forbidden error (403)
|
|
1673
|
+
*/
|
|
1674
|
+
static forbidden(message?: string): PluginRouteError;
|
|
1675
|
+
/**
|
|
1676
|
+
* Create a not found error (404)
|
|
1677
|
+
*/
|
|
1678
|
+
static notFound(message?: string): PluginRouteError;
|
|
1679
|
+
/**
|
|
1680
|
+
* Create a conflict error (409)
|
|
1681
|
+
*/
|
|
1682
|
+
static conflict(message: string, details?: unknown): PluginRouteError;
|
|
1683
|
+
/**
|
|
1684
|
+
* Create an internal error (500)
|
|
1685
|
+
*/
|
|
1686
|
+
static internal(message?: string): PluginRouteError;
|
|
1576
1687
|
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
_key: string;
|
|
1583
|
-
style?: "normal" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "blockquote";
|
|
1584
|
-
listItem?: "bullet" | "number";
|
|
1585
|
-
level?: number;
|
|
1586
|
-
children: PortableTextSpan[];
|
|
1587
|
-
markDefs?: PortableTextMarkDef[];
|
|
1688
|
+
//#endregion
|
|
1689
|
+
//#region src/plugins/sandbox/runtime-options.d.ts
|
|
1690
|
+
interface SandboxRunnerRuntimeOptions extends SandboxOptions {
|
|
1691
|
+
mediaStorage?: Storage;
|
|
1692
|
+
cronReschedule?: () => void;
|
|
1588
1693
|
}
|
|
1694
|
+
//#endregion
|
|
1695
|
+
//#region src/dineway-runtime.d.ts
|
|
1589
1696
|
/**
|
|
1590
|
-
*
|
|
1697
|
+
* Sandboxed plugin entry from virtual module
|
|
1591
1698
|
*/
|
|
1592
|
-
interface
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
_ref: string;
|
|
1597
|
-
url?: string; /** Provider ID for external media (e.g., "image-cdn") */
|
|
1598
|
-
provider?: string;
|
|
1599
|
-
};
|
|
1600
|
-
alt?: string;
|
|
1601
|
-
caption?: string;
|
|
1602
|
-
/** Original image width */
|
|
1603
|
-
width?: number;
|
|
1604
|
-
/** Original image height */
|
|
1605
|
-
height?: number;
|
|
1606
|
-
/** Display width for this instance (overrides original) */
|
|
1607
|
-
displayWidth?: number;
|
|
1608
|
-
/** Display height for this instance (overrides original) */
|
|
1609
|
-
displayHeight?: number;
|
|
1610
|
-
}
|
|
1611
|
-
/**
|
|
1612
|
-
* Code block
|
|
1613
|
-
*/
|
|
1614
|
-
interface PortableTextCodeBlock {
|
|
1615
|
-
_type: "code";
|
|
1616
|
-
_key: string;
|
|
1699
|
+
interface SandboxedPluginEntry {
|
|
1700
|
+
id: string;
|
|
1701
|
+
version: string;
|
|
1702
|
+
options: Record<string, unknown>;
|
|
1617
1703
|
code: string;
|
|
1618
|
-
|
|
1619
|
-
|
|
1704
|
+
/** Capabilities the plugin requests */
|
|
1705
|
+
capabilities: PluginCapability[];
|
|
1706
|
+
/** Allowed hosts for network:request */
|
|
1707
|
+
allowedHosts: string[];
|
|
1708
|
+
/** Declared storage collections */
|
|
1709
|
+
storage: PluginStorageConfig;
|
|
1710
|
+
/** Admin pages */
|
|
1711
|
+
adminPages?: Array<{
|
|
1712
|
+
path: string;
|
|
1713
|
+
label?: string;
|
|
1714
|
+
icon?: string;
|
|
1715
|
+
}>;
|
|
1716
|
+
/** Dashboard widgets */
|
|
1717
|
+
adminWidgets?: Array<{
|
|
1718
|
+
id: string;
|
|
1719
|
+
title?: string;
|
|
1720
|
+
size?: string;
|
|
1721
|
+
}>;
|
|
1722
|
+
/** Portable Text block types contributed to the editor through declarative Block Kit. */
|
|
1723
|
+
portableTextBlocks?: PortableTextBlockConfig[];
|
|
1724
|
+
/** Field widget types contributed for schema-field editing UIs. */
|
|
1725
|
+
fieldWidgets?: FieldWidgetConfig[];
|
|
1726
|
+
/** Admin entry module */
|
|
1727
|
+
adminEntry?: string;
|
|
1728
|
+
/**
|
|
1729
|
+
* Exclusive hooks this plugin should be auto-selected for.
|
|
1730
|
+
* Weaker than an existing admin DB selection — config order wins when no selection exists.
|
|
1731
|
+
*/
|
|
1732
|
+
preferred?: string[];
|
|
1620
1733
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1734
|
+
//#endregion
|
|
1735
|
+
//#region src/api/handlers/manifest.d.ts
|
|
1736
|
+
interface CollectionDefinition {
|
|
1737
|
+
schema: {
|
|
1738
|
+
_def?: {
|
|
1739
|
+
shape?: () => Record<string, unknown>;
|
|
1740
|
+
};
|
|
1741
|
+
shape?: Record<string, unknown>;
|
|
1742
|
+
};
|
|
1743
|
+
admin: {
|
|
1744
|
+
label: string;
|
|
1745
|
+
labelSingular?: string;
|
|
1746
|
+
supports?: string[];
|
|
1747
|
+
};
|
|
1628
1748
|
}
|
|
1749
|
+
type CollectionMap = Record<string, CollectionDefinition>;
|
|
1629
1750
|
/**
|
|
1630
|
-
*
|
|
1751
|
+
* Generate admin manifest from collections
|
|
1631
1752
|
*/
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1753
|
+
declare function generateManifest(collections: CollectionMap, plugins?: Record<string, {
|
|
1754
|
+
adminPages?: Array<{
|
|
1755
|
+
path: string;
|
|
1756
|
+
component: string;
|
|
1757
|
+
}>;
|
|
1758
|
+
widgets?: string[];
|
|
1759
|
+
}>): Promise<ManifestResponse>;
|
|
1760
|
+
//#endregion
|
|
1761
|
+
//#region src/api/handlers/revision.d.ts
|
|
1762
|
+
interface RevisionListResponse {
|
|
1763
|
+
items: Revision[];
|
|
1764
|
+
total: number;
|
|
1765
|
+
}
|
|
1766
|
+
interface RevisionResponse {
|
|
1767
|
+
item: Revision;
|
|
1636
1768
|
}
|
|
1637
1769
|
/**
|
|
1638
|
-
*
|
|
1639
|
-
*/
|
|
1640
|
-
type PortableTextBlock = PortableTextTextBlock | PortableTextImageBlock | PortableTextCodeBlock | PortableTextHtmlBlock | PortableTextUnknownBlock;
|
|
1641
|
-
/**
|
|
1642
|
-
* ProseMirror JSON types (simplified for TipTap)
|
|
1770
|
+
* List revisions for a content entry
|
|
1643
1771
|
*/
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
}
|
|
1648
|
-
interface ProseMirrorNode {
|
|
1649
|
-
type: string;
|
|
1650
|
-
attrs?: Record<string, unknown>;
|
|
1651
|
-
content?: ProseMirrorNode[];
|
|
1652
|
-
marks?: ProseMirrorMark[];
|
|
1653
|
-
text?: string;
|
|
1654
|
-
}
|
|
1655
|
-
interface ProseMirrorDocument {
|
|
1656
|
-
type: "doc";
|
|
1657
|
-
content: ProseMirrorNode[];
|
|
1658
|
-
}
|
|
1659
|
-
//#endregion
|
|
1660
|
-
//#region src/content/converters/prosemirror-to-portable-text.d.ts
|
|
1772
|
+
declare function handleRevisionList(db: Kysely<Database>, collection: string, entryId: string, params?: {
|
|
1773
|
+
limit?: number;
|
|
1774
|
+
}): Promise<ApiResult<RevisionListResponse>>;
|
|
1661
1775
|
/**
|
|
1662
|
-
*
|
|
1776
|
+
* Get a specific revision
|
|
1663
1777
|
*/
|
|
1664
|
-
declare function
|
|
1665
|
-
//#endregion
|
|
1666
|
-
//#region src/content/converters/portable-text-to-prosemirror.d.ts
|
|
1778
|
+
declare function handleRevisionGet(db: Kysely<Database>, revisionId: string): Promise<ApiResult<RevisionResponse>>;
|
|
1667
1779
|
/**
|
|
1668
|
-
*
|
|
1780
|
+
* Restore a revision (updates content to this revision's data and creates new revision)
|
|
1669
1781
|
*/
|
|
1670
|
-
declare function
|
|
1782
|
+
declare function handleRevisionRestore(db: Kysely<Database>, revisionId: string, callerUserId: string): Promise<ApiResult<ContentResponse>>;
|
|
1671
1783
|
//#endregion
|
|
1672
|
-
//#region src/
|
|
1784
|
+
//#region src/api/handlers/media.d.ts
|
|
1785
|
+
interface MediaListResponse {
|
|
1786
|
+
items: MediaItem[];
|
|
1787
|
+
nextCursor?: string;
|
|
1788
|
+
}
|
|
1789
|
+
interface MediaResponse {
|
|
1790
|
+
item: MediaItem;
|
|
1791
|
+
}
|
|
1673
1792
|
/**
|
|
1674
|
-
*
|
|
1675
|
-
* For cache invalidation / ETags — not for security.
|
|
1793
|
+
* List media items
|
|
1676
1794
|
*/
|
|
1677
|
-
declare function
|
|
1795
|
+
declare function handleMediaList(db: Kysely<Database>, params: {
|
|
1796
|
+
cursor?: string;
|
|
1797
|
+
limit?: number;
|
|
1798
|
+
mimeType?: string | readonly string[];
|
|
1799
|
+
q?: string;
|
|
1800
|
+
}): Promise<ApiResult<MediaListResponse>>;
|
|
1678
1801
|
/**
|
|
1679
|
-
*
|
|
1680
|
-
*
|
|
1681
|
-
* Uses SHA-1 which is the fastest option in SubtleCrypto.
|
|
1682
|
-
* SHA-1 is cryptographically weak but fine for content deduplication
|
|
1683
|
-
* where we only need to detect identical files, not resist attacks.
|
|
1684
|
-
*
|
|
1685
|
-
* Returns hex string prefixed with "sha1:" for future-proofing
|
|
1802
|
+
* Get single media item
|
|
1686
1803
|
*/
|
|
1687
|
-
declare function
|
|
1688
|
-
//#endregion
|
|
1689
|
-
//#region src/utils/url.d.ts
|
|
1804
|
+
declare function handleMediaGet(db: Kysely<Database>, id: string): Promise<ApiResult<MediaResponse>>;
|
|
1690
1805
|
/**
|
|
1691
|
-
*
|
|
1692
|
-
*
|
|
1693
|
-
* Prevents XSS via dangerous URL schemes (javascript:, data:, vbscript:, etc.)
|
|
1694
|
-
* by allowlisting known-safe schemes before rendering into href attributes.
|
|
1806
|
+
* Create media item (after file upload)
|
|
1695
1807
|
*/
|
|
1808
|
+
declare function handleMediaCreate(db: Kysely<Database>, input: {
|
|
1809
|
+
filename: string;
|
|
1810
|
+
mimeType: string;
|
|
1811
|
+
size?: number;
|
|
1812
|
+
width?: number;
|
|
1813
|
+
height?: number;
|
|
1814
|
+
alt?: string;
|
|
1815
|
+
storageKey: string;
|
|
1816
|
+
contentHash?: string;
|
|
1817
|
+
blurhash?: string;
|
|
1818
|
+
dominantColor?: string;
|
|
1819
|
+
authorId?: string;
|
|
1820
|
+
}): Promise<ApiResult<MediaResponse>>;
|
|
1696
1821
|
/**
|
|
1697
|
-
*
|
|
1698
|
-
*
|
|
1699
|
-
* Use this at the render layer as the primary defense against XSS via
|
|
1700
|
-
* dangerous URL schemes like `javascript:`, `data:`, or `vbscript:`.
|
|
1701
|
-
*
|
|
1702
|
-
* @example
|
|
1703
|
-
* ```ts
|
|
1704
|
-
* sanitizeHref("https://example.com") // "https://example.com"
|
|
1705
|
-
* sanitizeHref("/about") // "/about"
|
|
1706
|
-
* sanitizeHref("#section") // "#section"
|
|
1707
|
-
* sanitizeHref("mailto:a@b.com") // "mailto:a@b.com"
|
|
1708
|
-
* sanitizeHref("javascript:alert(1)") // "#"
|
|
1709
|
-
* sanitizeHref("data:text/html,<script>") // "#"
|
|
1710
|
-
* sanitizeHref("") // "#"
|
|
1711
|
-
* ```
|
|
1822
|
+
* Update media metadata
|
|
1712
1823
|
*/
|
|
1713
|
-
declare function
|
|
1824
|
+
declare function handleMediaUpdate(db: Kysely<Database>, id: string, input: {
|
|
1825
|
+
alt?: string;
|
|
1826
|
+
caption?: string;
|
|
1827
|
+
width?: number;
|
|
1828
|
+
height?: number;
|
|
1829
|
+
}): Promise<ApiResult<MediaResponse>>;
|
|
1714
1830
|
/**
|
|
1715
|
-
*
|
|
1831
|
+
* Delete media item
|
|
1716
1832
|
*/
|
|
1717
|
-
declare function
|
|
1833
|
+
declare function handleMediaDelete(db: Kysely<Database>, id: string): Promise<ApiResult<{
|
|
1834
|
+
deleted: true;
|
|
1835
|
+
}>>;
|
|
1718
1836
|
//#endregion
|
|
1719
|
-
//#region src/
|
|
1837
|
+
//#region src/schema/registry.d.ts
|
|
1720
1838
|
/**
|
|
1721
|
-
*
|
|
1722
|
-
*
|
|
1723
|
-
* Creates Proxy objects that emit data-dineway-ref attributes when spread onto elements.
|
|
1839
|
+
* Error thrown when a schema operation fails
|
|
1724
1840
|
*/
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
/** Entry status — only present on entry-level annotations (not field-level) */
|
|
1730
|
-
status?: string;
|
|
1731
|
-
/** Whether the entry has unpublished draft changes */
|
|
1732
|
-
hasDraft?: boolean;
|
|
1733
|
-
}
|
|
1734
|
-
/** The shape returned when spreading an edit annotation onto an element */
|
|
1735
|
-
interface FieldAnnotation {
|
|
1736
|
-
"data-dineway-ref": string;
|
|
1737
|
-
}
|
|
1738
|
-
interface EditableOptions {
|
|
1739
|
-
/** Entry status: "draft", "published", "scheduled" */
|
|
1740
|
-
status?: string;
|
|
1741
|
-
/** true when draftRevisionId exists and differs from liveRevisionId */
|
|
1742
|
-
hasDraft?: boolean;
|
|
1841
|
+
declare class SchemaError extends Error {
|
|
1842
|
+
code: string;
|
|
1843
|
+
details?: Record<string, unknown> | undefined;
|
|
1844
|
+
constructor(message: string, code: string, details?: Record<string, unknown> | undefined);
|
|
1743
1845
|
}
|
|
1744
1846
|
/**
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1747
|
-
* Usage:
|
|
1748
|
-
* - `{...entry.edit}` - entry-level annotation (includes status/hasDraft)
|
|
1749
|
-
* - `{...entry.edit.title}` - field-level annotation
|
|
1750
|
-
* - `{...entry.edit['nested.field']}` - nested field (bracket notation)
|
|
1751
|
-
*/
|
|
1752
|
-
declare function createEditable(collection: string, id: string, options?: EditableOptions): EditProxy;
|
|
1753
|
-
/**
|
|
1754
|
-
* Create a noop proxy for production mode.
|
|
1755
|
-
* Spreading this produces no attributes.
|
|
1756
|
-
*/
|
|
1757
|
-
declare function createNoop(): EditProxy;
|
|
1758
|
-
/**
|
|
1759
|
-
* Visual editing proxy type.
|
|
1760
|
-
*
|
|
1761
|
-
* Spread directly onto elements for entry-level annotations: `{...entry.edit}`
|
|
1762
|
-
* Access a field for field-level annotations: `{...entry.edit.title}`
|
|
1847
|
+
* Schema Registry
|
|
1763
1848
|
*
|
|
1764
|
-
*
|
|
1849
|
+
* Manages collection and field definitions stored in the database.
|
|
1850
|
+
* Handles runtime DDL operations (CREATE TABLE, ALTER TABLE).
|
|
1765
1851
|
*/
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
//#endregion
|
|
1770
|
-
//#region src/query.d.ts
|
|
1771
|
-
/**
|
|
1772
|
-
* Collection type registry for type-safe queries.
|
|
1773
|
-
*
|
|
1774
|
-
* This interface is extended by the generated dineway-env.d.ts file
|
|
1775
|
-
* to provide type inference for collection names and their data shapes.
|
|
1776
|
-
*
|
|
1777
|
-
* @example
|
|
1778
|
-
* ```ts
|
|
1779
|
-
* // In dineway-env.d.ts (generated):
|
|
1780
|
-
* declare module "dineway" {
|
|
1781
|
-
* interface DinewayCollections {
|
|
1782
|
-
* posts: { title: string; content: PortableTextBlock[]; };
|
|
1783
|
-
* pages: { title: string; body: PortableTextBlock[]; };
|
|
1784
|
-
* }
|
|
1785
|
-
* }
|
|
1786
|
-
*
|
|
1787
|
-
* // Then in your code:
|
|
1788
|
-
* const { entries } = await getDinewayCollection("posts");
|
|
1789
|
-
* // entries[0].data.title is typed as string
|
|
1790
|
-
* ```
|
|
1791
|
-
*/
|
|
1792
|
-
interface DinewayCollections {}
|
|
1793
|
-
/**
|
|
1794
|
-
* Helper type to infer the data type for a collection.
|
|
1795
|
-
* Returns the registered type if known, otherwise falls back to Record<string, unknown>.
|
|
1796
|
-
*/
|
|
1797
|
-
type InferCollectionData<T extends string> = T extends keyof DinewayCollections ? DinewayCollections[T] : Record<string, unknown>;
|
|
1798
|
-
/**
|
|
1799
|
-
* Sort direction
|
|
1800
|
-
*/
|
|
1801
|
-
type SortDirection = "asc" | "desc";
|
|
1802
|
-
/**
|
|
1803
|
-
* Order by specification - field name to direction
|
|
1804
|
-
* @example { created_at: "desc" } - Sort by created_at descending
|
|
1805
|
-
* @example { title: "asc" } - Sort by title ascending
|
|
1806
|
-
* @example { published_at: "desc", title: "asc" } - Multi-field sort
|
|
1807
|
-
*/
|
|
1808
|
-
type OrderBySpec = Record<string, SortDirection>;
|
|
1809
|
-
interface CollectionFilter {
|
|
1810
|
-
status?: "draft" | "published" | "archived";
|
|
1811
|
-
limit?: number;
|
|
1852
|
+
declare class SchemaRegistry {
|
|
1853
|
+
private db;
|
|
1854
|
+
constructor(db: Kysely<Database>);
|
|
1812
1855
|
/**
|
|
1813
|
-
*
|
|
1814
|
-
* Pass the `nextCursor` value from a previous result to fetch the next page.
|
|
1815
|
-
* @example
|
|
1816
|
-
* ```ts
|
|
1817
|
-
* const cursor = Astro.url.searchParams.get("cursor") ?? undefined;
|
|
1818
|
-
* const { entries, nextCursor } = await getDinewayCollection("posts", {
|
|
1819
|
-
* limit: 10,
|
|
1820
|
-
* cursor,
|
|
1821
|
-
* });
|
|
1822
|
-
* ```
|
|
1856
|
+
* List all collections
|
|
1823
1857
|
*/
|
|
1824
|
-
|
|
1858
|
+
listCollections(): Promise<Collection[]>;
|
|
1825
1859
|
/**
|
|
1826
|
-
*
|
|
1860
|
+
* List all collections with their fields using bounded query shapes.
|
|
1861
|
+
*/
|
|
1862
|
+
listCollectionsWithFields(): Promise<CollectionWithFields[]>;
|
|
1863
|
+
/**
|
|
1864
|
+
* Get a collection by slug
|
|
1865
|
+
*/
|
|
1866
|
+
getCollection(slug: string): Promise<Collection | null>;
|
|
1867
|
+
/**
|
|
1868
|
+
* Get a collection with all its fields
|
|
1869
|
+
*/
|
|
1870
|
+
getCollectionWithFields(slug: string): Promise<CollectionWithFields | null>;
|
|
1871
|
+
/**
|
|
1872
|
+
* Create a new collection
|
|
1873
|
+
*/
|
|
1874
|
+
createCollection(input: CreateCollectionInput): Promise<Collection>;
|
|
1875
|
+
/**
|
|
1876
|
+
* Update a collection
|
|
1877
|
+
*/
|
|
1878
|
+
updateCollection(slug: string, input: UpdateCollectionInput): Promise<Collection>;
|
|
1879
|
+
private validateUrlPattern;
|
|
1880
|
+
private checkLabelUniqueness;
|
|
1881
|
+
private checkUrlPatternUniqueness;
|
|
1882
|
+
/**
|
|
1883
|
+
* Delete a collection
|
|
1884
|
+
*/
|
|
1885
|
+
deleteCollection(slug: string, options?: {
|
|
1886
|
+
force?: boolean;
|
|
1887
|
+
}): Promise<void>;
|
|
1888
|
+
/**
|
|
1889
|
+
* List fields for a collection
|
|
1890
|
+
*/
|
|
1891
|
+
listFields(collectionId: string): Promise<Field[]>;
|
|
1892
|
+
/**
|
|
1893
|
+
* Get a field by slug within a collection
|
|
1894
|
+
*/
|
|
1895
|
+
getField(collectionSlug: string, fieldSlug: string): Promise<Field | null>;
|
|
1896
|
+
/**
|
|
1897
|
+
* Create a new field
|
|
1898
|
+
*/
|
|
1899
|
+
createField(collectionSlug: string, input: CreateFieldInput): Promise<Field>;
|
|
1900
|
+
/**
|
|
1901
|
+
* Ensure the content table for an existing collection exists.
|
|
1827
1902
|
*
|
|
1828
|
-
*
|
|
1829
|
-
*
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1903
|
+
* This repairs interrupted schema creation where the metadata row exists but
|
|
1904
|
+
* the physical `ec_*` table was not created.
|
|
1905
|
+
*/
|
|
1906
|
+
ensureCollectionContentTable(collectionSlug: string): Promise<boolean>;
|
|
1907
|
+
/**
|
|
1908
|
+
* Ensure the physical column for an existing field exists on its content table.
|
|
1833
1909
|
*
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1836
|
-
* @example { byline: '01HXYZ...' } - Entries credited to a byline (any position)
|
|
1837
|
-
* @example { byline: ['01HXYZ...', '01HABC...'] } - Credited to any of these bylines (OR)
|
|
1838
|
-
* @example { series: 'main' } - Exact match on a content field
|
|
1839
|
-
* @example { published_at: { gte: '2024-01-01', lt: '2025-01-01' } } - Date range
|
|
1910
|
+
* This repairs interrupted field creation where `_dineway_fields` was written
|
|
1911
|
+
* but `ALTER TABLE ec_* ADD COLUMN` did not complete.
|
|
1840
1912
|
*/
|
|
1841
|
-
|
|
1913
|
+
ensureFieldColumn(collectionSlug: string, fieldSlug: string): Promise<boolean>;
|
|
1842
1914
|
/**
|
|
1843
|
-
*
|
|
1915
|
+
* Update a field
|
|
1916
|
+
*/
|
|
1917
|
+
updateField(collectionSlug: string, fieldSlug: string, input: UpdateFieldInput): Promise<Field>;
|
|
1918
|
+
/**
|
|
1919
|
+
* Synchronize an existing FTS index with the collection's current state.
|
|
1844
1920
|
*
|
|
1845
|
-
*
|
|
1846
|
-
*
|
|
1921
|
+
* Schema writes must not first-time enable FTS. Initial enablement stays in
|
|
1922
|
+
* explicit seed/import/admin flows where FTS failures can be handled deliberately.
|
|
1847
1923
|
*/
|
|
1848
|
-
|
|
1849
|
-
searchColumns?: string[];
|
|
1924
|
+
private syncSearchState;
|
|
1850
1925
|
/**
|
|
1851
|
-
*
|
|
1852
|
-
* @default { created_at: "desc" }
|
|
1853
|
-
* @example { created_at: "desc" } - Sort by created_at descending (default)
|
|
1854
|
-
* @example { title: "asc" } - Sort by title ascending
|
|
1855
|
-
* @example { published_at: "desc", title: "asc" } - Multi-field sort
|
|
1926
|
+
* Delete a field
|
|
1856
1927
|
*/
|
|
1857
|
-
|
|
1928
|
+
deleteField(collectionSlug: string, fieldSlug: string): Promise<void>;
|
|
1858
1929
|
/**
|
|
1859
|
-
*
|
|
1860
|
-
* Only relevant when i18n is configured.
|
|
1861
|
-
* @example "en" — English entries only
|
|
1862
|
-
* @example "fr" — French entries only
|
|
1930
|
+
* Reorder fields
|
|
1863
1931
|
*/
|
|
1864
|
-
|
|
1865
|
-
}
|
|
1866
|
-
interface ContentEntry<T = Record<string, unknown>> {
|
|
1867
|
-
id: string;
|
|
1868
|
-
data: T;
|
|
1869
|
-
/** Visual editing annotations. Spread onto elements: {...entry.edit.title} */
|
|
1870
|
-
edit: EditProxy;
|
|
1871
|
-
}
|
|
1872
|
-
/** Cache hint returned by the content loader for route caching */
|
|
1873
|
-
interface CacheHint {
|
|
1874
|
-
tags?: string[];
|
|
1875
|
-
lastModified?: Date;
|
|
1876
|
-
}
|
|
1877
|
-
/**
|
|
1878
|
-
* Result from getDinewayCollection
|
|
1879
|
-
*/
|
|
1880
|
-
interface CollectionResult<T> {
|
|
1881
|
-
/** The entries (empty array if error or none found) */
|
|
1882
|
-
entries: ContentEntry<T>[];
|
|
1883
|
-
/** Error if the query failed */
|
|
1884
|
-
error?: Error;
|
|
1885
|
-
/** Cache hint for route caching (pass to Astro.cache.set()) */
|
|
1886
|
-
cacheHint: CacheHint;
|
|
1932
|
+
reorderFields(collectionSlug: string, fieldSlugs: string[]): Promise<void>;
|
|
1887
1933
|
/**
|
|
1888
|
-
*
|
|
1889
|
-
* Undefined when there are no more results.
|
|
1890
|
-
* Pass this as `cursor` in the next query to get the next page.
|
|
1934
|
+
* Create a content table for a collection
|
|
1891
1935
|
*/
|
|
1892
|
-
|
|
1936
|
+
private createContentTable;
|
|
1893
1937
|
/**
|
|
1894
|
-
*
|
|
1938
|
+
* Drop a content table
|
|
1895
1939
|
*/
|
|
1896
|
-
|
|
1940
|
+
private dropContentTable;
|
|
1941
|
+
/**
|
|
1942
|
+
* Add a column to a content table
|
|
1943
|
+
*/
|
|
1944
|
+
private addColumn;
|
|
1945
|
+
/**
|
|
1946
|
+
* Drop a column from a content table
|
|
1947
|
+
*/
|
|
1948
|
+
private dropColumn;
|
|
1949
|
+
/**
|
|
1950
|
+
* Check if a collection has any content
|
|
1951
|
+
*/
|
|
1952
|
+
private collectionHasContent;
|
|
1953
|
+
/**
|
|
1954
|
+
* Get table name for a collection
|
|
1955
|
+
*/
|
|
1956
|
+
private getTableName;
|
|
1957
|
+
/**
|
|
1958
|
+
* Get column name for a field
|
|
1959
|
+
*/
|
|
1960
|
+
private getColumnName;
|
|
1961
|
+
/**
|
|
1962
|
+
* Validate a slug
|
|
1963
|
+
*/
|
|
1964
|
+
private validateSlug;
|
|
1965
|
+
/**
|
|
1966
|
+
* Format a default value for SQL.
|
|
1967
|
+
*
|
|
1968
|
+
* SQLite `ALTER TABLE ADD COLUMN ... DEFAULT` requires a literal constant
|
|
1969
|
+
* expression — parameterized values cannot be used here. We manually escape
|
|
1970
|
+
* single quotes and coerce types to ensure the output is safe.
|
|
1971
|
+
*
|
|
1972
|
+
* INTEGER/REAL values are coerced through `Number()` which can only produce
|
|
1973
|
+
* digits, `.`, `-`, `e`, `Infinity`, or `NaN` — all safe in SQL.
|
|
1974
|
+
* TEXT/JSON values have single quotes escaped via SQL standard doubling (`''`).
|
|
1975
|
+
*/
|
|
1976
|
+
private formatDefaultValue;
|
|
1977
|
+
/**
|
|
1978
|
+
* Get empty default for a field type
|
|
1979
|
+
*/
|
|
1980
|
+
private getEmptyDefault;
|
|
1981
|
+
/**
|
|
1982
|
+
* Map a collection row to a Collection object
|
|
1983
|
+
*/
|
|
1984
|
+
private mapCollectionRow;
|
|
1985
|
+
/**
|
|
1986
|
+
* Map a field row to a Field object
|
|
1987
|
+
*/
|
|
1988
|
+
private mapFieldRow;
|
|
1989
|
+
/**
|
|
1990
|
+
* Discover orphaned content tables
|
|
1991
|
+
*
|
|
1992
|
+
* Finds ec_* tables that exist in the database but don't have a
|
|
1993
|
+
* corresponding entry in _dineway_collections.
|
|
1994
|
+
*/
|
|
1995
|
+
discoverOrphanedTables(): Promise<Array<{
|
|
1996
|
+
slug: string;
|
|
1997
|
+
tableName: string;
|
|
1998
|
+
rowCount: number;
|
|
1999
|
+
}>>;
|
|
2000
|
+
/**
|
|
2001
|
+
* Register an orphaned table as a collection
|
|
2002
|
+
*
|
|
2003
|
+
* Creates a _dineway_collections entry for an existing ec_* table.
|
|
2004
|
+
*/
|
|
2005
|
+
registerOrphanedTable(slug: string, options?: {
|
|
2006
|
+
label?: string;
|
|
2007
|
+
labelSingular?: string;
|
|
2008
|
+
description?: string;
|
|
2009
|
+
}): Promise<Collection>;
|
|
2010
|
+
/**
|
|
2011
|
+
* Convert slug to human-readable label
|
|
2012
|
+
*/
|
|
2013
|
+
private slugToLabel;
|
|
1897
2014
|
}
|
|
2015
|
+
//#endregion
|
|
2016
|
+
//#region src/schema/query.d.ts
|
|
1898
2017
|
/**
|
|
1899
|
-
*
|
|
2018
|
+
* Get collection metadata by slug.
|
|
2019
|
+
*
|
|
2020
|
+
* @example
|
|
2021
|
+
* ```ts
|
|
2022
|
+
* import { getCollectionInfo } from "dineway";
|
|
2023
|
+
*
|
|
2024
|
+
* const info = await getCollectionInfo("posts");
|
|
2025
|
+
* if (info?.commentsEnabled) {
|
|
2026
|
+
* // render comment UI
|
|
2027
|
+
* }
|
|
2028
|
+
* ```
|
|
1900
2029
|
*/
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
/** Error if the query failed (not set for "not found", only for actual errors) */
|
|
1905
|
-
error?: Error;
|
|
1906
|
-
/** Whether we're in preview mode (valid token was provided) */
|
|
1907
|
-
isPreview: boolean;
|
|
1908
|
-
/** Set when a fallback locale was used instead of the requested locale */
|
|
1909
|
-
fallbackLocale?: string;
|
|
1910
|
-
/** Cache hint for route caching (pass to Astro.cache.set()) */
|
|
1911
|
-
cacheHint: CacheHint;
|
|
1912
|
-
}
|
|
1913
|
-
/** Edit metadata attached to PT arrays in edit mode */
|
|
1914
|
-
interface EditFieldMeta {
|
|
1915
|
-
collection: string;
|
|
1916
|
-
id: string;
|
|
1917
|
-
field: string;
|
|
1918
|
-
}
|
|
2030
|
+
declare function getCollectionInfo(slug: string): Promise<Collection | null>;
|
|
2031
|
+
//#endregion
|
|
2032
|
+
//#region src/sections/types.d.ts
|
|
1919
2033
|
/**
|
|
1920
|
-
*
|
|
1921
|
-
* Uses Object.getOwnPropertyDescriptor to access Symbol-keyed property
|
|
1922
|
-
* without an unsafe type assertion.
|
|
2034
|
+
* Section source types
|
|
1923
2035
|
*/
|
|
1924
|
-
|
|
2036
|
+
type SectionSource = "theme" | "user" | "import";
|
|
1925
2037
|
/**
|
|
1926
|
-
*
|
|
1927
|
-
*
|
|
1928
|
-
* Returns { entries, error } for graceful error handling.
|
|
1929
|
-
*
|
|
1930
|
-
* When dineway-env.d.ts is generated, the collection name will be
|
|
1931
|
-
* type-checked and the return type will be inferred automatically.
|
|
1932
|
-
*
|
|
1933
|
-
* @example
|
|
1934
|
-
* ```ts
|
|
1935
|
-
* import { getDinewayCollection } from "dineway";
|
|
1936
|
-
*
|
|
1937
|
-
* const { entries: posts, error } = await getDinewayCollection("posts");
|
|
1938
|
-
* if (error) {
|
|
1939
|
-
* console.error("Failed to load posts:", error);
|
|
1940
|
-
* return;
|
|
1941
|
-
* }
|
|
1942
|
-
* // posts[0].data.title is typed (if dineway-env.d.ts exists)
|
|
1943
|
-
*
|
|
1944
|
-
* // With filters
|
|
1945
|
-
* const { entries: drafts } = await getDinewayCollection("posts", { status: "draft" });
|
|
1946
|
-
* ```
|
|
2038
|
+
* Section as returned to templates/admin
|
|
1947
2039
|
*/
|
|
1948
|
-
|
|
2040
|
+
interface Section {
|
|
2041
|
+
id: string;
|
|
2042
|
+
slug: string;
|
|
2043
|
+
title: string;
|
|
2044
|
+
description?: string;
|
|
2045
|
+
keywords: string[];
|
|
2046
|
+
content: PortableTextBlock$1[];
|
|
2047
|
+
previewUrl?: string;
|
|
2048
|
+
source: SectionSource;
|
|
2049
|
+
themeId?: string;
|
|
2050
|
+
createdAt: string;
|
|
2051
|
+
updatedAt: string;
|
|
2052
|
+
}
|
|
1949
2053
|
/**
|
|
1950
|
-
*
|
|
1951
|
-
*
|
|
1952
|
-
* Returns { entry, error, isPreview } for graceful error handling.
|
|
1953
|
-
* - entry is null if not found (not an error)
|
|
1954
|
-
* - error is set only for actual errors (db issues, etc.)
|
|
1955
|
-
*
|
|
1956
|
-
* Preview mode is detected automatically from request context (ALS).
|
|
1957
|
-
* When the URL has a valid `_preview` token, the middleware sets preview
|
|
1958
|
-
* context and this function serves draft revision data if available.
|
|
1959
|
-
*
|
|
1960
|
-
* @example
|
|
1961
|
-
* ```ts
|
|
1962
|
-
* import { getDinewayEntry } from "dineway";
|
|
1963
|
-
*
|
|
1964
|
-
* // Simple usage — preview just works via middleware
|
|
1965
|
-
* const { entry: post, isPreview, error } = await getDinewayEntry("posts", "my-slug");
|
|
1966
|
-
* if (!post) return Astro.redirect("/404");
|
|
1967
|
-
* ```
|
|
2054
|
+
* Input for creating a section
|
|
1968
2055
|
*/
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
2056
|
+
interface CreateSectionInput {
|
|
2057
|
+
slug: string;
|
|
2058
|
+
title: string;
|
|
2059
|
+
description?: string;
|
|
2060
|
+
keywords?: string[];
|
|
2061
|
+
content: PortableTextBlock$1[];
|
|
2062
|
+
previewMediaId?: string;
|
|
2063
|
+
source?: SectionSource;
|
|
2064
|
+
themeId?: string;
|
|
2065
|
+
}
|
|
1972
2066
|
/**
|
|
1973
|
-
*
|
|
2067
|
+
* Input for updating a section
|
|
1974
2068
|
*/
|
|
1975
|
-
interface
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
/** Current status */
|
|
1983
|
-
status: string;
|
|
2069
|
+
interface UpdateSectionInput {
|
|
2070
|
+
slug?: string;
|
|
2071
|
+
title?: string;
|
|
2072
|
+
description?: string;
|
|
2073
|
+
keywords?: string[];
|
|
2074
|
+
content?: PortableTextBlock$1[];
|
|
2075
|
+
previewMediaId?: string | null;
|
|
1984
2076
|
}
|
|
1985
2077
|
/**
|
|
1986
|
-
*
|
|
2078
|
+
* Options for querying sections
|
|
1987
2079
|
*/
|
|
1988
|
-
interface
|
|
1989
|
-
/**
|
|
1990
|
-
|
|
1991
|
-
/**
|
|
1992
|
-
|
|
1993
|
-
/**
|
|
1994
|
-
|
|
2080
|
+
interface GetSectionsOptions {
|
|
2081
|
+
/** Filter by source */
|
|
2082
|
+
source?: SectionSource;
|
|
2083
|
+
/** Search title, description, keywords */
|
|
2084
|
+
search?: string;
|
|
2085
|
+
/** Limit results */
|
|
2086
|
+
limit?: number;
|
|
2087
|
+
/** Cursor for pagination */
|
|
2088
|
+
cursor?: string;
|
|
1995
2089
|
}
|
|
2090
|
+
//#endregion
|
|
2091
|
+
//#region src/sections/index.d.ts
|
|
1996
2092
|
/**
|
|
1997
|
-
* Get
|
|
1998
|
-
*
|
|
1999
|
-
* Given a content entry, returns all locale variants that share the same
|
|
2000
|
-
* translation group. This is useful for building language switcher UI.
|
|
2093
|
+
* Get a section by slug
|
|
2001
2094
|
*
|
|
2002
2095
|
* @example
|
|
2003
2096
|
* ```ts
|
|
2004
|
-
* import {
|
|
2097
|
+
* import { getSection } from "dineway";
|
|
2005
2098
|
*
|
|
2006
|
-
* const
|
|
2007
|
-
*
|
|
2008
|
-
* //
|
|
2099
|
+
* const section = await getSection("hero-centered");
|
|
2100
|
+
* if (section) {
|
|
2101
|
+
* console.log(section.content); // Portable Text array
|
|
2102
|
+
* }
|
|
2009
2103
|
* ```
|
|
2010
2104
|
*/
|
|
2011
|
-
declare function
|
|
2012
|
-
/**
|
|
2013
|
-
* Result from resolveDinewayPath
|
|
2014
|
-
*/
|
|
2015
|
-
interface ResolvePathResult<T = Record<string, unknown>> {
|
|
2016
|
-
/** The matched entry */
|
|
2017
|
-
entry: ContentEntry<T>;
|
|
2018
|
-
/** The collection slug that matched */
|
|
2019
|
-
collection: string;
|
|
2020
|
-
/** Extracted parameters from the URL pattern (e.g. { slug: "my-post" }) */
|
|
2021
|
-
params: Record<string, string>;
|
|
2022
|
-
}
|
|
2105
|
+
declare function getSection(slug: string): Promise<Section | null>;
|
|
2023
2106
|
/**
|
|
2024
|
-
*
|
|
2025
|
-
*
|
|
2026
|
-
* Loads all collections with a `urlPattern` set, converts each pattern to a regex,
|
|
2027
|
-
* and tests the given path. On match, extracts the slug and fetches the entry.
|
|
2107
|
+
* Get all sections with optional filtering
|
|
2028
2108
|
*
|
|
2029
2109
|
* @example
|
|
2030
2110
|
* ```ts
|
|
2031
|
-
* import {
|
|
2111
|
+
* import { getSections } from "dineway";
|
|
2032
2112
|
*
|
|
2033
|
-
* //
|
|
2034
|
-
* const
|
|
2035
|
-
*
|
|
2036
|
-
*
|
|
2037
|
-
*
|
|
2038
|
-
* console.log(result.entry.data); // post data
|
|
2039
|
-
* }
|
|
2113
|
+
* // Get all theme-provided sections
|
|
2114
|
+
* const themeSections = await getSections({ source: "theme" });
|
|
2115
|
+
*
|
|
2116
|
+
* // Search sections
|
|
2117
|
+
* const results = await getSections({ search: "pricing" });
|
|
2040
2118
|
* ```
|
|
2041
2119
|
*/
|
|
2042
|
-
declare function
|
|
2120
|
+
declare function getSections(options?: GetSectionsOptions): Promise<FindManyResult<Section>>;
|
|
2043
2121
|
//#endregion
|
|
2044
|
-
//#region src/
|
|
2122
|
+
//#region src/content/converters/types.d.ts
|
|
2045
2123
|
/**
|
|
2046
|
-
*
|
|
2124
|
+
* Portable Text Types
|
|
2047
2125
|
*
|
|
2048
|
-
*
|
|
2049
|
-
* initialization or response handling. Node keeps the process alive for
|
|
2050
|
-
* pending work; callers that need stronger durability should await their own
|
|
2051
|
-
* operation instead of using this helper.
|
|
2126
|
+
* Defines the structure of Portable Text blocks used in Dineway.
|
|
2052
2127
|
*/
|
|
2053
|
-
type AfterCallback = () => void | Promise<void>;
|
|
2054
|
-
declare function after(fn: AfterCallback): void;
|
|
2055
|
-
//#endregion
|
|
2056
|
-
//#region src/i18n/config.d.ts
|
|
2057
2128
|
/**
|
|
2058
|
-
*
|
|
2059
|
-
*
|
|
2060
|
-
* Reads locale configuration from the virtual module (sourced from Astro config).
|
|
2061
|
-
* Initialized during runtime startup, then available via getI18nConfig().
|
|
2129
|
+
* Base span (inline text)
|
|
2062
2130
|
*/
|
|
2063
|
-
interface
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2131
|
+
interface PortableTextSpan {
|
|
2132
|
+
_type: "span";
|
|
2133
|
+
_key: string;
|
|
2134
|
+
text: string;
|
|
2135
|
+
marks?: string[];
|
|
2068
2136
|
}
|
|
2069
2137
|
/**
|
|
2070
|
-
*
|
|
2071
|
-
* Returns null if i18n is not configured.
|
|
2138
|
+
* Mark definition (bold, italic, link, etc.)
|
|
2072
2139
|
*/
|
|
2073
|
-
|
|
2140
|
+
interface PortableTextMarkDef {
|
|
2141
|
+
_type: string;
|
|
2142
|
+
_key: string;
|
|
2143
|
+
[key: string]: unknown;
|
|
2144
|
+
}
|
|
2074
2145
|
/**
|
|
2075
|
-
*
|
|
2076
|
-
* Returns true when multiple locales are configured.
|
|
2146
|
+
* Link mark definition
|
|
2077
2147
|
*/
|
|
2078
|
-
|
|
2148
|
+
interface PortableTextLinkMark extends PortableTextMarkDef {
|
|
2149
|
+
_type: "link";
|
|
2150
|
+
href: string;
|
|
2151
|
+
blank?: boolean;
|
|
2152
|
+
}
|
|
2079
2153
|
/**
|
|
2080
|
-
*
|
|
2081
|
-
* Returns array of locales to try, from most preferred to least.
|
|
2082
|
-
* Always ends with defaultLocale.
|
|
2154
|
+
* Text block (paragraph, heading, etc.)
|
|
2083
2155
|
*/
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2156
|
+
interface PortableTextTextBlock {
|
|
2157
|
+
_type: "block";
|
|
2158
|
+
_key: string;
|
|
2159
|
+
style?: "normal" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "blockquote";
|
|
2160
|
+
listItem?: "bullet" | "number";
|
|
2161
|
+
level?: number;
|
|
2162
|
+
children: PortableTextSpan[];
|
|
2163
|
+
markDefs?: PortableTextMarkDef[];
|
|
2164
|
+
textAlign?: "left" | "center" | "right" | "justify";
|
|
2165
|
+
}
|
|
2087
2166
|
/**
|
|
2088
|
-
*
|
|
2089
|
-
*
|
|
2090
|
-
* These utilities define the signed URL and snapshot-auth contract shared
|
|
2091
|
-
* by preview sidecars and the source site serving snapshot exports.
|
|
2167
|
+
* Image block
|
|
2092
2168
|
*/
|
|
2093
|
-
interface
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
dbPath: string;
|
|
2112
|
-
createdAt: number;
|
|
2113
|
-
expiresAt: number;
|
|
2114
|
-
lastTouchedAt: number;
|
|
2115
|
-
}
|
|
2116
|
-
interface SessionDatabaseHandle {
|
|
2117
|
-
created: boolean;
|
|
2118
|
-
session: SessionDatabaseInfo;
|
|
2119
|
-
db: Kysely<Database>;
|
|
2120
|
-
close(): Promise<void>;
|
|
2121
|
-
}
|
|
2122
|
-
interface SessionCleanupResult {
|
|
2123
|
-
removedSessionIds: string[];
|
|
2124
|
-
removedPaths: string[];
|
|
2169
|
+
interface PortableTextImageBlock {
|
|
2170
|
+
_type: "image";
|
|
2171
|
+
_key: string;
|
|
2172
|
+
asset: {
|
|
2173
|
+
_ref: string;
|
|
2174
|
+
url?: string; /** Provider ID for external media (e.g., "image-cdn") */
|
|
2175
|
+
provider?: string;
|
|
2176
|
+
};
|
|
2177
|
+
alt?: string;
|
|
2178
|
+
caption?: string;
|
|
2179
|
+
/** Original image width */
|
|
2180
|
+
width?: number;
|
|
2181
|
+
/** Original image height */
|
|
2182
|
+
height?: number;
|
|
2183
|
+
/** Display width for this instance (overrides original) */
|
|
2184
|
+
displayWidth?: number;
|
|
2185
|
+
/** Display height for this instance (overrides original) */
|
|
2186
|
+
displayHeight?: number;
|
|
2125
2187
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2188
|
+
/**
|
|
2189
|
+
* Code block
|
|
2190
|
+
*/
|
|
2191
|
+
interface PortableTextCodeBlock {
|
|
2192
|
+
_type: "code";
|
|
2193
|
+
_key: string;
|
|
2194
|
+
code: string;
|
|
2195
|
+
language?: string;
|
|
2196
|
+
filename?: string;
|
|
2129
2197
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2198
|
+
/**
|
|
2199
|
+
* HTML block (raw HTML content)
|
|
2200
|
+
*/
|
|
2201
|
+
interface PortableTextHtmlBlock {
|
|
2202
|
+
_type: "htmlBlock";
|
|
2203
|
+
_key: string;
|
|
2204
|
+
html: string;
|
|
2132
2205
|
}
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2206
|
+
/**
|
|
2207
|
+
* Unknown/custom block (preserved for plugin compatibility)
|
|
2208
|
+
*/
|
|
2209
|
+
interface PortableTextUnknownBlock {
|
|
2210
|
+
_type: string;
|
|
2211
|
+
_key: string;
|
|
2212
|
+
[key: string]: unknown;
|
|
2139
2213
|
}
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2214
|
+
/**
|
|
2215
|
+
* Any Portable Text block
|
|
2216
|
+
*/
|
|
2217
|
+
type PortableTextBlock = PortableTextTextBlock | PortableTextImageBlock | PortableTextCodeBlock | PortableTextHtmlBlock | PortableTextUnknownBlock;
|
|
2218
|
+
/**
|
|
2219
|
+
* ProseMirror JSON types (simplified for TipTap)
|
|
2220
|
+
*/
|
|
2221
|
+
interface ProseMirrorMark {
|
|
2222
|
+
type: string;
|
|
2223
|
+
attrs?: Record<string, unknown>;
|
|
2145
2224
|
}
|
|
2146
|
-
|
|
2147
|
-
|
|
2225
|
+
interface ProseMirrorNode {
|
|
2226
|
+
type: string;
|
|
2227
|
+
attrs?: Record<string, unknown>;
|
|
2228
|
+
content?: ProseMirrorNode[];
|
|
2229
|
+
marks?: ProseMirrorMark[];
|
|
2230
|
+
text?: string;
|
|
2148
2231
|
}
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
private readonly sessionsDir;
|
|
2153
|
-
private readonly maxDiskBytes;
|
|
2154
|
-
constructor(options: FileSessionDatabaseFactoryOptions);
|
|
2155
|
-
open(input: SessionOpenOptions): Promise<SessionDatabaseHandle | null>;
|
|
2156
|
-
openOrCreate(input: SessionOpenOrCreateOptions): Promise<SessionDatabaseHandle>;
|
|
2157
|
-
destroy(id: string): Promise<boolean>;
|
|
2158
|
-
cleanup(now?: number): Promise<SessionCleanupResult>;
|
|
2159
|
-
close(): Promise<void>;
|
|
2160
|
-
private createHandle;
|
|
2161
|
-
private getSessionRow;
|
|
2162
|
-
private toSessionInfo;
|
|
2163
|
-
private deleteSession;
|
|
2164
|
-
private getActiveDiskBytes;
|
|
2165
|
-
private getDbPath;
|
|
2166
|
-
private getManagedPaths;
|
|
2167
|
-
private listSessionRows;
|
|
2168
|
-
private listDbPathRows;
|
|
2232
|
+
interface ProseMirrorDocument {
|
|
2233
|
+
type: "doc";
|
|
2234
|
+
content: ProseMirrorNode[];
|
|
2169
2235
|
}
|
|
2170
2236
|
//#endregion
|
|
2171
|
-
//#region src/
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
cookieName?: string;
|
|
2177
|
-
snapshotPath?: string;
|
|
2178
|
-
maxSessionDiskBytes?: number;
|
|
2179
|
-
sessionFactory?: SessionDatabaseFactory;
|
|
2180
|
-
fetch?: typeof globalThis.fetch;
|
|
2181
|
-
}
|
|
2182
|
-
declare function createFilePreviewMiddleware(config: FilePreviewMiddlewareConfig): MiddlewareHandler;
|
|
2237
|
+
//#region src/content/converters/prosemirror-to-portable-text.d.ts
|
|
2238
|
+
/**
|
|
2239
|
+
* Convert ProseMirror document to Portable Text
|
|
2240
|
+
*/
|
|
2241
|
+
declare function prosemirrorToPortableText(doc: ProseMirrorDocument): PortableTextBlock[];
|
|
2183
2242
|
//#endregion
|
|
2184
|
-
//#region src/
|
|
2243
|
+
//#region src/content/converters/portable-text-to-prosemirror.d.ts
|
|
2185
2244
|
/**
|
|
2186
|
-
*
|
|
2245
|
+
* Convert Portable Text to ProseMirror document
|
|
2246
|
+
*/
|
|
2247
|
+
declare function portableTextToProsemirror(blocks: PortableTextBlock[]): ProseMirrorDocument;
|
|
2248
|
+
//#endregion
|
|
2249
|
+
//#region src/utils/hash.d.ts
|
|
2250
|
+
/**
|
|
2251
|
+
* SHA-256 hash of a string, truncated to 16 hex chars (64 bits).
|
|
2252
|
+
* For cache invalidation / ETags — not for security.
|
|
2253
|
+
*/
|
|
2254
|
+
declare function hashString(content: string): Promise<string>;
|
|
2255
|
+
/**
|
|
2256
|
+
* Compute content hash using Web Crypto API
|
|
2187
2257
|
*
|
|
2188
|
-
*
|
|
2189
|
-
*
|
|
2258
|
+
* Uses SHA-1 which is the fastest option in SubtleCrypto.
|
|
2259
|
+
* SHA-1 is cryptographically weak but fine for content deduplication
|
|
2260
|
+
* where we only need to detect identical files, not resist attacks.
|
|
2190
2261
|
*
|
|
2191
|
-
*
|
|
2192
|
-
|
|
2193
|
-
|
|
2262
|
+
* Returns hex string prefixed with "sha1:" for future-proofing
|
|
2263
|
+
*/
|
|
2264
|
+
declare function computeContentHash(content: Uint8Array | ArrayBuffer): Promise<string>;
|
|
2265
|
+
//#endregion
|
|
2266
|
+
//#region src/utils/url.d.ts
|
|
2267
|
+
/**
|
|
2268
|
+
* URL scheme validation utilities
|
|
2194
2269
|
*
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
*
|
|
2200
|
-
* },
|
|
2201
|
-
* },
|
|
2202
|
-
* },
|
|
2203
|
-
* routes: {
|
|
2204
|
-
* status: {
|
|
2205
|
-
* handler: async (routeCtx, ctx) => ({ ok: true }),
|
|
2206
|
-
* },
|
|
2207
|
-
* },
|
|
2208
|
-
* });
|
|
2209
|
-
* ```
|
|
2270
|
+
* Prevents XSS via dangerous URL schemes (javascript:, data:, vbscript:, etc.)
|
|
2271
|
+
* by allowlisting known-safe schemes before rendering into href attributes.
|
|
2272
|
+
*/
|
|
2273
|
+
/**
|
|
2274
|
+
* Returns the URL unchanged if it uses a safe scheme, otherwise returns "#".
|
|
2210
2275
|
*
|
|
2211
|
-
*
|
|
2212
|
-
*
|
|
2276
|
+
* Use this at the render layer as the primary defense against XSS via
|
|
2277
|
+
* dangerous URL schemes like `javascript:`, `data:`, or `vbscript:`.
|
|
2213
2278
|
*
|
|
2214
2279
|
* @example
|
|
2215
|
-
* ```
|
|
2216
|
-
*
|
|
2217
|
-
*
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
2222
|
-
*
|
|
2223
|
-
* "content:beforeSave": async (event, ctx) => {
|
|
2224
|
-
* ctx.log.info("Saving content", { collection: event.collection });
|
|
2225
|
-
* return event.content;
|
|
2226
|
-
* }
|
|
2227
|
-
* },
|
|
2228
|
-
* routes: {
|
|
2229
|
-
* "sync": {
|
|
2230
|
-
* handler: async (ctx) => {
|
|
2231
|
-
* return { status: "ok" };
|
|
2232
|
-
* }
|
|
2233
|
-
* }
|
|
2234
|
-
* }
|
|
2235
|
-
* });
|
|
2280
|
+
* ```ts
|
|
2281
|
+
* sanitizeHref("https://example.com") // "https://example.com"
|
|
2282
|
+
* sanitizeHref("/about") // "/about"
|
|
2283
|
+
* sanitizeHref("#section") // "#section"
|
|
2284
|
+
* sanitizeHref("mailto:a@b.com") // "mailto:a@b.com"
|
|
2285
|
+
* sanitizeHref("javascript:alert(1)") // "#"
|
|
2286
|
+
* sanitizeHref("data:text/html,<script>") // "#"
|
|
2287
|
+
* sanitizeHref("") // "#"
|
|
2236
2288
|
* ```
|
|
2237
2289
|
*/
|
|
2238
|
-
declare function
|
|
2239
|
-
|
|
2290
|
+
declare function sanitizeHref(url: string | undefined | null): string;
|
|
2291
|
+
/**
|
|
2292
|
+
* Returns true if the URL uses a safe scheme for rendering in href attributes.
|
|
2293
|
+
*/
|
|
2294
|
+
declare function isSafeHref(url: string): boolean;
|
|
2240
2295
|
//#endregion
|
|
2241
|
-
//#region src/
|
|
2296
|
+
//#region src/auth/rate-limit.d.ts
|
|
2242
2297
|
/**
|
|
2243
|
-
*
|
|
2298
|
+
* Result of a rate limit check.
|
|
2299
|
+
*/
|
|
2300
|
+
interface RateLimitResult {
|
|
2301
|
+
/** Whether the request is allowed (within limit). */
|
|
2302
|
+
allowed: boolean;
|
|
2303
|
+
/** Current request count in this window. */
|
|
2304
|
+
count: number;
|
|
2305
|
+
/** Maximum requests allowed in this window. */
|
|
2306
|
+
limit: number;
|
|
2307
|
+
}
|
|
2308
|
+
/**
|
|
2309
|
+
* Check (and increment) the rate limit for a given IP + endpoint.
|
|
2244
2310
|
*
|
|
2245
|
-
*
|
|
2311
|
+
* If `ip` is null (no trusted IP available), rate limiting is skipped
|
|
2312
|
+
* and the request is allowed. There's no meaningful key to rate limit
|
|
2313
|
+
* on when the IP is unknown.
|
|
2314
|
+
*
|
|
2315
|
+
* Returns whether the request is allowed. The counter is always
|
|
2316
|
+
* incremented — even when the limit is exceeded — so that repeated
|
|
2317
|
+
* abuse doesn't reset the window.
|
|
2318
|
+
*
|
|
2319
|
+
* Piggybacks cleanup of expired entries with a 1% probability
|
|
2320
|
+
* to prevent unbounded table growth.
|
|
2246
2321
|
*/
|
|
2247
|
-
declare
|
|
2248
|
-
id: z$1.ZodString;
|
|
2249
|
-
version: z$1.ZodString;
|
|
2250
|
-
capabilities: z$1.ZodArray<z$1.ZodEnum<{
|
|
2251
|
-
"network:request": "network:request";
|
|
2252
|
-
"network:request:unrestricted": "network:request:unrestricted";
|
|
2253
|
-
"content:read": "content:read";
|
|
2254
|
-
"content:write": "content:write";
|
|
2255
|
-
"media:read": "media:read";
|
|
2256
|
-
"media:write": "media:write";
|
|
2257
|
-
"users:read": "users:read";
|
|
2258
|
-
"email:send": "email:send";
|
|
2259
|
-
"hooks.email-transport:register": "hooks.email-transport:register";
|
|
2260
|
-
"hooks.email-events:register": "hooks.email-events:register";
|
|
2261
|
-
"hooks.page-fragments:register": "hooks.page-fragments:register";
|
|
2262
|
-
}>>;
|
|
2263
|
-
allowedHosts: z$1.ZodArray<z$1.ZodString>;
|
|
2264
|
-
storage: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
2265
|
-
indexes: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodArray<z$1.ZodString>]>>;
|
|
2266
|
-
uniqueIndexes: z$1.ZodOptional<z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodArray<z$1.ZodString>]>>>;
|
|
2267
|
-
}, z$1.core.$strip>>;
|
|
2268
|
-
hooks: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodEnum<{
|
|
2269
|
-
"plugin:install": "plugin:install";
|
|
2270
|
-
"plugin:activate": "plugin:activate";
|
|
2271
|
-
"plugin:deactivate": "plugin:deactivate";
|
|
2272
|
-
"plugin:uninstall": "plugin:uninstall";
|
|
2273
|
-
"content:beforeSave": "content:beforeSave";
|
|
2274
|
-
"content:afterSave": "content:afterSave";
|
|
2275
|
-
"content:beforeDelete": "content:beforeDelete";
|
|
2276
|
-
"content:afterDelete": "content:afterDelete";
|
|
2277
|
-
"content:afterPublish": "content:afterPublish";
|
|
2278
|
-
"content:afterUnpublish": "content:afterUnpublish";
|
|
2279
|
-
"media:beforeUpload": "media:beforeUpload";
|
|
2280
|
-
"media:afterUpload": "media:afterUpload";
|
|
2281
|
-
cron: "cron";
|
|
2282
|
-
"email:beforeSend": "email:beforeSend";
|
|
2283
|
-
"email:deliver": "email:deliver";
|
|
2284
|
-
"email:afterSend": "email:afterSend";
|
|
2285
|
-
"comment:beforeCreate": "comment:beforeCreate";
|
|
2286
|
-
"comment:moderate": "comment:moderate";
|
|
2287
|
-
"comment:afterCreate": "comment:afterCreate";
|
|
2288
|
-
"comment:afterModerate": "comment:afterModerate";
|
|
2289
|
-
"page:metadata": "page:metadata";
|
|
2290
|
-
"page:fragments": "page:fragments";
|
|
2291
|
-
}>, z$1.ZodObject<{
|
|
2292
|
-
name: z$1.ZodEnum<{
|
|
2293
|
-
"plugin:install": "plugin:install";
|
|
2294
|
-
"plugin:activate": "plugin:activate";
|
|
2295
|
-
"plugin:deactivate": "plugin:deactivate";
|
|
2296
|
-
"plugin:uninstall": "plugin:uninstall";
|
|
2297
|
-
"content:beforeSave": "content:beforeSave";
|
|
2298
|
-
"content:afterSave": "content:afterSave";
|
|
2299
|
-
"content:beforeDelete": "content:beforeDelete";
|
|
2300
|
-
"content:afterDelete": "content:afterDelete";
|
|
2301
|
-
"content:afterPublish": "content:afterPublish";
|
|
2302
|
-
"content:afterUnpublish": "content:afterUnpublish";
|
|
2303
|
-
"media:beforeUpload": "media:beforeUpload";
|
|
2304
|
-
"media:afterUpload": "media:afterUpload";
|
|
2305
|
-
cron: "cron";
|
|
2306
|
-
"email:beforeSend": "email:beforeSend";
|
|
2307
|
-
"email:deliver": "email:deliver";
|
|
2308
|
-
"email:afterSend": "email:afterSend";
|
|
2309
|
-
"comment:beforeCreate": "comment:beforeCreate";
|
|
2310
|
-
"comment:moderate": "comment:moderate";
|
|
2311
|
-
"comment:afterCreate": "comment:afterCreate";
|
|
2312
|
-
"comment:afterModerate": "comment:afterModerate";
|
|
2313
|
-
"page:metadata": "page:metadata";
|
|
2314
|
-
"page:fragments": "page:fragments";
|
|
2315
|
-
}>;
|
|
2316
|
-
exclusive: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
2317
|
-
priority: z$1.ZodOptional<z$1.ZodNumber>;
|
|
2318
|
-
timeout: z$1.ZodOptional<z$1.ZodNumber>;
|
|
2319
|
-
}, z$1.core.$strip>]>>;
|
|
2320
|
-
routes: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodObject<{
|
|
2321
|
-
name: z$1.ZodString;
|
|
2322
|
-
public: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
2323
|
-
}, z$1.core.$strip>]>>;
|
|
2324
|
-
admin: z$1.ZodObject<{
|
|
2325
|
-
entry: z$1.ZodOptional<z$1.ZodString>;
|
|
2326
|
-
settingsSchema: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
|
|
2327
|
-
type: z$1.ZodLiteral<"string">;
|
|
2328
|
-
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2329
|
-
multiline: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
2330
|
-
label: z$1.ZodString;
|
|
2331
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2332
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2333
|
-
type: z$1.ZodLiteral<"number">;
|
|
2334
|
-
default: z$1.ZodOptional<z$1.ZodNumber>;
|
|
2335
|
-
min: z$1.ZodOptional<z$1.ZodNumber>;
|
|
2336
|
-
max: z$1.ZodOptional<z$1.ZodNumber>;
|
|
2337
|
-
label: z$1.ZodString;
|
|
2338
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2339
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2340
|
-
type: z$1.ZodLiteral<"boolean">;
|
|
2341
|
-
default: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
2342
|
-
label: z$1.ZodString;
|
|
2343
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2344
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2345
|
-
type: z$1.ZodLiteral<"select">;
|
|
2346
|
-
options: z$1.ZodArray<z$1.ZodObject<{
|
|
2347
|
-
value: z$1.ZodString;
|
|
2348
|
-
label: z$1.ZodString;
|
|
2349
|
-
}, z$1.core.$strip>>;
|
|
2350
|
-
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2351
|
-
label: z$1.ZodString;
|
|
2352
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2353
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2354
|
-
type: z$1.ZodLiteral<"secret">;
|
|
2355
|
-
label: z$1.ZodString;
|
|
2356
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2357
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2358
|
-
type: z$1.ZodLiteral<"url">;
|
|
2359
|
-
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2360
|
-
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
2361
|
-
label: z$1.ZodString;
|
|
2362
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2363
|
-
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
2364
|
-
type: z$1.ZodLiteral<"email">;
|
|
2365
|
-
default: z$1.ZodOptional<z$1.ZodString>;
|
|
2366
|
-
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
2367
|
-
label: z$1.ZodString;
|
|
2368
|
-
description: z$1.ZodOptional<z$1.ZodString>;
|
|
2369
|
-
}, z$1.core.$strip>], "type">>>;
|
|
2370
|
-
pages: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
2371
|
-
path: z$1.ZodString;
|
|
2372
|
-
label: z$1.ZodString;
|
|
2373
|
-
icon: z$1.ZodOptional<z$1.ZodString>;
|
|
2374
|
-
}, z$1.core.$strip>>>;
|
|
2375
|
-
widgets: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
2376
|
-
id: z$1.ZodString;
|
|
2377
|
-
size: z$1.ZodOptional<z$1.ZodEnum<{
|
|
2378
|
-
full: "full";
|
|
2379
|
-
half: "half";
|
|
2380
|
-
third: "third";
|
|
2381
|
-
}>>;
|
|
2382
|
-
title: z$1.ZodOptional<z$1.ZodString>;
|
|
2383
|
-
}, z$1.core.$strip>>>;
|
|
2384
|
-
fieldWidgets: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
2385
|
-
name: z$1.ZodString;
|
|
2386
|
-
label: z$1.ZodString;
|
|
2387
|
-
fieldTypes: z$1.ZodArray<z$1.ZodEnum<{
|
|
2388
|
-
string: "string";
|
|
2389
|
-
number: "number";
|
|
2390
|
-
boolean: "boolean";
|
|
2391
|
-
file: "file";
|
|
2392
|
-
image: "image";
|
|
2393
|
-
datetime: "datetime";
|
|
2394
|
-
slug: "slug";
|
|
2395
|
-
text: "text";
|
|
2396
|
-
integer: "integer";
|
|
2397
|
-
select: "select";
|
|
2398
|
-
multiSelect: "multiSelect";
|
|
2399
|
-
portableText: "portableText";
|
|
2400
|
-
reference: "reference";
|
|
2401
|
-
json: "json";
|
|
2402
|
-
repeater: "repeater";
|
|
2403
|
-
}>>;
|
|
2404
|
-
elements: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
2405
|
-
type: z$1.ZodString;
|
|
2406
|
-
action_id: z$1.ZodString;
|
|
2407
|
-
label: z$1.ZodOptional<z$1.ZodString>;
|
|
2408
|
-
}, z$1.core.$loose>>>;
|
|
2409
|
-
}, z$1.core.$strip>>>;
|
|
2410
|
-
}, z$1.core.$strip>;
|
|
2411
|
-
}, z$1.core.$strip>;
|
|
2412
|
-
type ValidatedPluginManifest = z$1.infer<typeof pluginManifestSchema>;
|
|
2322
|
+
declare function checkRateLimit(db: Kysely<Database>, ip: string | null, endpoint: string, maxRequests: number, windowSeconds: number): Promise<RateLimitResult>;
|
|
2413
2323
|
//#endregion
|
|
2414
|
-
//#region src/
|
|
2415
|
-
|
|
2324
|
+
//#region src/security/guest-access-tokens.d.ts
|
|
2325
|
+
interface GuestAccessTokenClaims {
|
|
2326
|
+
version: 1;
|
|
2327
|
+
tokenId: string;
|
|
2328
|
+
purpose: string;
|
|
2329
|
+
subjectType: string;
|
|
2330
|
+
subjectId: string;
|
|
2331
|
+
locationId: string;
|
|
2332
|
+
issuedAt: number;
|
|
2333
|
+
expiresAt: number;
|
|
2334
|
+
}
|
|
2335
|
+
interface IssueGuestAccessTokenOptions {
|
|
2336
|
+
secret: string;
|
|
2337
|
+
purpose: string;
|
|
2338
|
+
subjectType: string;
|
|
2339
|
+
subjectId: string;
|
|
2340
|
+
locationId: string;
|
|
2341
|
+
/** Reuses an already persisted identifier to reconstruct the exact same capability. */
|
|
2342
|
+
tokenId?: string;
|
|
2343
|
+
expiresIn?: string | number;
|
|
2344
|
+
now?: number;
|
|
2345
|
+
}
|
|
2346
|
+
interface IssuedGuestAccessToken {
|
|
2347
|
+
token: string;
|
|
2348
|
+
tokenHash: string;
|
|
2349
|
+
claims: GuestAccessTokenClaims;
|
|
2350
|
+
}
|
|
2351
|
+
interface GuestAccessExpectedScope {
|
|
2352
|
+
purpose: string;
|
|
2353
|
+
subjectType: string;
|
|
2354
|
+
subjectId?: string;
|
|
2355
|
+
locationId?: string;
|
|
2356
|
+
}
|
|
2357
|
+
interface VerifyGuestAccessTokenOptions {
|
|
2358
|
+
token: string | null | undefined;
|
|
2359
|
+
/** Primary secret first, followed by retained rotation secrets. */
|
|
2360
|
+
secrets: string | readonly string[];
|
|
2361
|
+
expected: GuestAccessExpectedScope;
|
|
2362
|
+
now?: number;
|
|
2363
|
+
}
|
|
2364
|
+
type VerifyGuestAccessTokenResult = {
|
|
2365
|
+
valid: true;
|
|
2366
|
+
claims: GuestAccessTokenClaims;
|
|
2367
|
+
tokenHash: string;
|
|
2368
|
+
} | {
|
|
2369
|
+
valid: false;
|
|
2370
|
+
error: "none" | "malformed" | "invalid" | "expired" | "scope_mismatch";
|
|
2371
|
+
};
|
|
2372
|
+
declare class GuestAccessTokenConfigurationError extends Error {
|
|
2373
|
+
readonly code: "INVALID_GUEST_TOKEN_SECRET" | "INVALID_GUEST_TOKEN_INPUT";
|
|
2374
|
+
readonly name = "GuestAccessTokenConfigurationError";
|
|
2375
|
+
constructor(message: string, code: "INVALID_GUEST_TOKEN_SECRET" | "INVALID_GUEST_TOKEN_INPUT");
|
|
2376
|
+
}
|
|
2416
2377
|
/**
|
|
2417
|
-
*
|
|
2378
|
+
* Issues an expiring capability for one guest purpose and one restaurant target.
|
|
2379
|
+
* Persist only tokenHash/tokenId and revocation metadata; never persist or log token.
|
|
2418
2380
|
*/
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2381
|
+
declare function issueGuestAccessToken(options: IssueGuestAccessTokenOptions): Promise<IssuedGuestAccessToken>;
|
|
2382
|
+
/**
|
|
2383
|
+
* Verifies signature, expiry, and the caller-declared purpose/target scope.
|
|
2384
|
+
* A valid result still requires the plugin to check its revocation record by tokenHash.
|
|
2385
|
+
*/
|
|
2386
|
+
declare function verifyGuestAccessToken(options: VerifyGuestAccessTokenOptions): Promise<VerifyGuestAccessTokenResult>;
|
|
2387
|
+
/** Returns the non-reversible identifier stored for revocation and lookup. */
|
|
2388
|
+
declare function hashGuestAccessToken(token: string): Promise<string>;
|
|
2389
|
+
//#endregion
|
|
2390
|
+
//#region src/visual-editing/editable.d.ts
|
|
2391
|
+
/**
|
|
2392
|
+
* Visual editing annotation system
|
|
2393
|
+
*
|
|
2394
|
+
* Creates Proxy objects that emit data-dineway-ref attributes when spread onto elements.
|
|
2395
|
+
*/
|
|
2396
|
+
interface CMSAnnotation {
|
|
2397
|
+
collection: string;
|
|
2398
|
+
id: string;
|
|
2399
|
+
field?: string;
|
|
2400
|
+
/** Entry status — only present on entry-level annotations (not field-level) */
|
|
2401
|
+
status?: string;
|
|
2402
|
+
/** Whether the entry has unpublished draft changes */
|
|
2403
|
+
hasDraft?: boolean;
|
|
2404
|
+
}
|
|
2405
|
+
/** The shape returned when spreading an edit annotation onto an element */
|
|
2406
|
+
interface FieldAnnotation {
|
|
2407
|
+
"data-dineway-ref": string;
|
|
2408
|
+
}
|
|
2409
|
+
interface EditableOptions {
|
|
2410
|
+
/** Entry status: "draft", "published", "scheduled" */
|
|
2411
|
+
status?: string;
|
|
2412
|
+
/** true when draftRevisionId exists and differs from liveRevisionId */
|
|
2413
|
+
hasDraft?: boolean;
|
|
2425
2414
|
}
|
|
2426
2415
|
/**
|
|
2427
|
-
*
|
|
2416
|
+
* Create an editable proxy for an entry.
|
|
2417
|
+
*
|
|
2418
|
+
* Usage:
|
|
2419
|
+
* - `{...entry.edit}` - entry-level annotation (includes status/hasDraft)
|
|
2420
|
+
* - `{...entry.edit.title}` - field-level annotation
|
|
2421
|
+
* - `{...entry.edit['nested.field']}` - nested field (bracket notation)
|
|
2428
2422
|
*/
|
|
2429
|
-
declare
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
private sortHooks;
|
|
2493
|
-
/**
|
|
2494
|
-
* Execute a hook with timeout
|
|
2495
|
-
*/
|
|
2496
|
-
private executeWithTimeout;
|
|
2497
|
-
/**
|
|
2498
|
-
* Run plugin:install hooks
|
|
2499
|
-
*/
|
|
2500
|
-
runPluginInstall(pluginId: string): Promise<HookResult<void>[]>;
|
|
2501
|
-
/**
|
|
2502
|
-
* Run plugin:activate hooks
|
|
2503
|
-
*/
|
|
2504
|
-
runPluginActivate(pluginId: string): Promise<HookResult<void>[]>;
|
|
2505
|
-
/**
|
|
2506
|
-
* Run plugin:deactivate hooks
|
|
2507
|
-
*/
|
|
2508
|
-
runPluginDeactivate(pluginId: string): Promise<HookResult<void>[]>;
|
|
2509
|
-
/**
|
|
2510
|
-
* Run plugin:uninstall hooks
|
|
2511
|
-
*/
|
|
2512
|
-
runPluginUninstall(pluginId: string, deleteData: boolean): Promise<HookResult<void>[]>;
|
|
2513
|
-
private runLifecycleHook;
|
|
2514
|
-
/**
|
|
2515
|
-
* Run content:beforeSave hooks
|
|
2516
|
-
* Returns modified content from the pipeline
|
|
2517
|
-
*/
|
|
2518
|
-
runContentBeforeSave(content: Record<string, unknown>, collection: string, isNew: boolean): Promise<{
|
|
2519
|
-
content: Record<string, unknown>;
|
|
2520
|
-
results: HookResult<Record<string, unknown>>[];
|
|
2521
|
-
}>;
|
|
2522
|
-
/**
|
|
2523
|
-
* Run content:afterSave hooks
|
|
2524
|
-
*/
|
|
2525
|
-
runContentAfterSave(content: Record<string, unknown>, collection: string, isNew: boolean): Promise<HookResult<void>[]>;
|
|
2526
|
-
/**
|
|
2527
|
-
* Run content:beforeDelete hooks
|
|
2528
|
-
* Returns whether deletion is allowed
|
|
2529
|
-
*/
|
|
2530
|
-
runContentBeforeDelete(id: string, collection: string): Promise<{
|
|
2531
|
-
allowed: boolean;
|
|
2532
|
-
results: HookResult<boolean>[];
|
|
2533
|
-
}>;
|
|
2534
|
-
/**
|
|
2535
|
-
* Run content:afterDelete hooks
|
|
2536
|
-
*/
|
|
2537
|
-
runContentAfterDelete(id: string, collection: string, permanent: boolean): Promise<HookResult<void>[]>;
|
|
2538
|
-
/**
|
|
2539
|
-
* Run content:afterPublish hooks (fire-and-forget).
|
|
2540
|
-
*/
|
|
2541
|
-
runContentAfterPublish(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
2542
|
-
/**
|
|
2543
|
-
* Run content:afterUnpublish hooks (fire-and-forget).
|
|
2544
|
-
*/
|
|
2545
|
-
runContentAfterUnpublish(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
2546
|
-
/**
|
|
2547
|
-
* Run media:beforeUpload hooks
|
|
2548
|
-
*/
|
|
2549
|
-
runMediaBeforeUpload(file: {
|
|
2550
|
-
name: string;
|
|
2551
|
-
type: string;
|
|
2552
|
-
size: number;
|
|
2553
|
-
}): Promise<{
|
|
2554
|
-
file: {
|
|
2555
|
-
name: string;
|
|
2556
|
-
type: string;
|
|
2557
|
-
size: number;
|
|
2558
|
-
};
|
|
2559
|
-
results: HookResult<{
|
|
2560
|
-
name: string;
|
|
2561
|
-
type: string;
|
|
2562
|
-
size: number;
|
|
2563
|
-
}>[];
|
|
2564
|
-
}>;
|
|
2565
|
-
/**
|
|
2566
|
-
* Run media:afterUpload hooks
|
|
2567
|
-
*/
|
|
2568
|
-
runMediaAfterUpload(media: {
|
|
2569
|
-
id: string;
|
|
2570
|
-
filename: string;
|
|
2571
|
-
mimeType: string;
|
|
2572
|
-
size: number | null;
|
|
2573
|
-
url: string;
|
|
2574
|
-
createdAt: string;
|
|
2575
|
-
}): Promise<HookResult<void>[]>;
|
|
2576
|
-
/**
|
|
2577
|
-
* Invoke the cron hook for a specific plugin.
|
|
2578
|
-
*
|
|
2579
|
-
* Unlike other hooks which broadcast to all plugins, the cron hook is
|
|
2580
|
-
* dispatched only to the target plugin — the one that owns the task.
|
|
2581
|
-
*/
|
|
2582
|
-
invokeCronHook(pluginId: string, event: CronEvent): Promise<HookResult<void>>;
|
|
2583
|
-
/**
|
|
2584
|
-
* Run email:beforeSend hooks (middleware pipeline).
|
|
2585
|
-
*
|
|
2586
|
-
* Each handler receives the message and returns a modified message or
|
|
2587
|
-
* `false` to cancel delivery. The pipeline chains message transformations —
|
|
2588
|
-
* each handler receives the output of the previous one.
|
|
2589
|
-
*/
|
|
2590
|
-
runEmailBeforeSend(message: EmailMessage, source: string): Promise<{
|
|
2591
|
-
message: EmailMessage | false;
|
|
2592
|
-
results: HookResult<EmailMessage | false>[];
|
|
2593
|
-
}>;
|
|
2594
|
-
/**
|
|
2595
|
-
* Run email:afterSend hooks (fire-and-forget).
|
|
2596
|
-
*
|
|
2597
|
-
* Errors are logged but don't propagate — they don't affect the caller.
|
|
2598
|
-
*/
|
|
2599
|
-
runEmailAfterSend(message: EmailMessage, source: string): Promise<HookResult<void>[]>;
|
|
2423
|
+
declare function createEditable(collection: string, id: string, options?: EditableOptions): EditProxy;
|
|
2424
|
+
/**
|
|
2425
|
+
* Create a noop proxy for production mode.
|
|
2426
|
+
* Spreading this produces no attributes.
|
|
2427
|
+
*/
|
|
2428
|
+
declare function createNoop(): EditProxy;
|
|
2429
|
+
/**
|
|
2430
|
+
* Visual editing proxy type.
|
|
2431
|
+
*
|
|
2432
|
+
* Spread directly onto elements for entry-level annotations: `{...entry.edit}`
|
|
2433
|
+
* Access a field for field-level annotations: `{...entry.edit.title}`
|
|
2434
|
+
*
|
|
2435
|
+
* In production, spreading produces no attributes (noop).
|
|
2436
|
+
*/
|
|
2437
|
+
type EditProxy = {
|
|
2438
|
+
readonly [field: string]: Partial<FieldAnnotation>;
|
|
2439
|
+
};
|
|
2440
|
+
//#endregion
|
|
2441
|
+
//#region src/query.d.ts
|
|
2442
|
+
/**
|
|
2443
|
+
* Collection type registry for type-safe queries.
|
|
2444
|
+
*
|
|
2445
|
+
* This interface is extended by the generated dineway-env.d.ts file
|
|
2446
|
+
* to provide type inference for collection names and their data shapes.
|
|
2447
|
+
*
|
|
2448
|
+
* @example
|
|
2449
|
+
* ```ts
|
|
2450
|
+
* // In dineway-env.d.ts (generated):
|
|
2451
|
+
* declare module "dineway" {
|
|
2452
|
+
* interface DinewayCollections {
|
|
2453
|
+
* posts: { title: string; content: PortableTextBlock[]; };
|
|
2454
|
+
* pages: { title: string; body: PortableTextBlock[]; };
|
|
2455
|
+
* }
|
|
2456
|
+
* }
|
|
2457
|
+
*
|
|
2458
|
+
* // Then in your code:
|
|
2459
|
+
* const { entries } = await getDinewayCollection("posts");
|
|
2460
|
+
* // entries[0].data.title is typed as string
|
|
2461
|
+
* ```
|
|
2462
|
+
*/
|
|
2463
|
+
interface DinewayCollections {}
|
|
2464
|
+
/**
|
|
2465
|
+
* Helper type to infer the data type for a collection.
|
|
2466
|
+
* Returns the registered type if known, otherwise falls back to Record<string, unknown>.
|
|
2467
|
+
*/
|
|
2468
|
+
type InferCollectionData<T extends string> = T extends keyof DinewayCollections ? DinewayCollections[T] : Record<string, unknown>;
|
|
2469
|
+
/**
|
|
2470
|
+
* Sort direction
|
|
2471
|
+
*/
|
|
2472
|
+
type SortDirection = "asc" | "desc";
|
|
2473
|
+
/**
|
|
2474
|
+
* Order by specification - field name to direction
|
|
2475
|
+
* @example { created_at: "desc" } - Sort by created_at descending
|
|
2476
|
+
* @example { title: "asc" } - Sort by title ascending
|
|
2477
|
+
* @example { published_at: "desc", title: "asc" } - Multi-field sort
|
|
2478
|
+
*/
|
|
2479
|
+
type OrderBySpec = Record<string, SortDirection>;
|
|
2480
|
+
/**
|
|
2481
|
+
* Fields shared by every collection query, independent of pagination mode.
|
|
2482
|
+
*/
|
|
2483
|
+
interface CollectionFilterBase {
|
|
2484
|
+
status?: "draft" | "published" | "archived";
|
|
2485
|
+
limit?: number;
|
|
2600
2486
|
/**
|
|
2601
|
-
*
|
|
2487
|
+
* Filter by field values, taxonomy terms, byline credits, or ranges.
|
|
2602
2488
|
*
|
|
2603
|
-
*
|
|
2604
|
-
* `
|
|
2605
|
-
*
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
/**
|
|
2609
|
-
* Run comment:afterCreate hooks (fire-and-forget).
|
|
2489
|
+
* Taxonomy names are detected automatically and filtered by term.
|
|
2490
|
+
* The reserved `byline` key filters by byline credit in any position,
|
|
2491
|
+
* not just the primary credit. It accepts one or more byline translation
|
|
2492
|
+
* groups, or concrete byline row IDs.
|
|
2493
|
+
* Other keys are treated as content table column filters.
|
|
2610
2494
|
*
|
|
2611
|
-
*
|
|
2495
|
+
* @example { category: 'news' } - Filter by taxonomy term
|
|
2496
|
+
* @example { category: ['news', 'featured'] } - Filter by multiple terms (OR)
|
|
2497
|
+
* @example { byline: '01HXYZ...' } - Entries credited to a byline (any position)
|
|
2498
|
+
* @example { byline: ['01HXYZ...', '01HABC...'] } - Credited to any of these bylines (OR)
|
|
2499
|
+
* @example { series: 'main' } - Exact match on a content field
|
|
2500
|
+
* @example { published_at: { gte: '2024-01-01', lt: '2025-01-01' } } - Date range
|
|
2612
2501
|
*/
|
|
2613
|
-
|
|
2502
|
+
where?: Record<string, WhereValue>;
|
|
2614
2503
|
/**
|
|
2615
|
-
*
|
|
2504
|
+
* Case-insensitive substring search across selected content fields.
|
|
2616
2505
|
*
|
|
2617
|
-
*
|
|
2618
|
-
|
|
2619
|
-
runCommentAfterModerate(event: CommentAfterModerateEvent): Promise<void>;
|
|
2620
|
-
/**
|
|
2621
|
-
* Run page:metadata hooks. Each handler returns contributions that are
|
|
2622
|
-
* merged by the metadata collector. Errors are logged but don't propagate.
|
|
2623
|
-
*/
|
|
2624
|
-
runPageMetadata(event: PageMetadataEvent): Promise<Array<{
|
|
2625
|
-
pluginId: string;
|
|
2626
|
-
contributions: PageMetadataContribution[];
|
|
2627
|
-
}>>;
|
|
2628
|
-
/**
|
|
2629
|
-
* Run page:fragments hooks. Only trusted plugins should be registered
|
|
2630
|
-
* for this hook. Errors are logged but don't propagate.
|
|
2631
|
-
*/
|
|
2632
|
-
runPageFragments(event: PageFragmentEvent): Promise<Array<{
|
|
2633
|
-
pluginId: string;
|
|
2634
|
-
contributions: PageFragmentContribution[];
|
|
2635
|
-
}>>;
|
|
2636
|
-
/**
|
|
2637
|
-
* Check if any hooks are registered for a given name
|
|
2638
|
-
*/
|
|
2639
|
-
hasHooks(name: HookNameV2): boolean;
|
|
2640
|
-
/**
|
|
2641
|
-
* Get hook count for debugging
|
|
2642
|
-
*/
|
|
2643
|
-
getHookCount(name: HookNameV2): number;
|
|
2644
|
-
/**
|
|
2645
|
-
* Get all registered hook names
|
|
2646
|
-
*/
|
|
2647
|
-
getRegisteredHooks(): HookNameV2[];
|
|
2648
|
-
/**
|
|
2649
|
-
* Returns hook names where at least one handler declared exclusive: true
|
|
2506
|
+
* `searchColumns` must contain concrete field slugs or system column names.
|
|
2507
|
+
* When `q` is present without `searchColumns`, no search condition is applied.
|
|
2650
2508
|
*/
|
|
2651
|
-
|
|
2509
|
+
q?: string;
|
|
2510
|
+
searchColumns?: string[];
|
|
2652
2511
|
/**
|
|
2653
|
-
*
|
|
2512
|
+
* Order results by field(s)
|
|
2513
|
+
* @default { created_at: "desc" }
|
|
2514
|
+
* @example { created_at: "desc" } - Sort by created_at descending (default)
|
|
2515
|
+
* @example { title: "asc" } - Sort by title ascending
|
|
2516
|
+
* @example { published_at: "desc", title: "asc" } - Multi-field sort
|
|
2654
2517
|
*/
|
|
2655
|
-
|
|
2518
|
+
orderBy?: OrderBySpec;
|
|
2656
2519
|
/**
|
|
2657
|
-
*
|
|
2658
|
-
*
|
|
2520
|
+
* Filter by locale. When set, only returns entries in this locale.
|
|
2521
|
+
* Only relevant when i18n is configured.
|
|
2522
|
+
* @example "en" — English entries only
|
|
2523
|
+
* @example "fr" — French entries only
|
|
2659
2524
|
*/
|
|
2660
|
-
|
|
2525
|
+
locale?: string;
|
|
2526
|
+
}
|
|
2527
|
+
/** Keyset-paginated query filter. Cannot also carry an offset. */
|
|
2528
|
+
interface CursorCollectionFilter extends CollectionFilterBase {
|
|
2661
2529
|
/**
|
|
2662
|
-
*
|
|
2530
|
+
* Opaque cursor for keyset pagination.
|
|
2531
|
+
* Pass the `nextCursor` value from a previous result to fetch the next page.
|
|
2532
|
+
* @example
|
|
2533
|
+
* ```ts
|
|
2534
|
+
* const cursor = Astro.url.searchParams.get("cursor") ?? undefined;
|
|
2535
|
+
* const { entries, nextCursor } = await getDinewayCollection("posts", {
|
|
2536
|
+
* limit: 10,
|
|
2537
|
+
* cursor,
|
|
2538
|
+
* });
|
|
2539
|
+
* ```
|
|
2663
2540
|
*/
|
|
2664
|
-
|
|
2541
|
+
cursor?: string;
|
|
2542
|
+
offset?: never;
|
|
2543
|
+
}
|
|
2544
|
+
/** Offset-paginated query filter. Cannot also carry a cursor. */
|
|
2545
|
+
interface OffsetCollectionFilter extends CollectionFilterBase {
|
|
2665
2546
|
/**
|
|
2666
|
-
*
|
|
2547
|
+
* Skip this many entries before returning results. Use with `limit` for
|
|
2548
|
+
* numbered archive routes, for example `offset = (page - 1) * perPage`.
|
|
2667
2549
|
*/
|
|
2668
|
-
|
|
2550
|
+
offset?: number;
|
|
2551
|
+
cursor?: never;
|
|
2552
|
+
}
|
|
2553
|
+
type CollectionFilter = CursorCollectionFilter | OffsetCollectionFilter;
|
|
2554
|
+
interface ContentEntry<T = Record<string, unknown>> {
|
|
2555
|
+
id: string;
|
|
2556
|
+
data: T;
|
|
2557
|
+
/** Visual editing annotations. Spread onto elements: {...entry.edit.title} */
|
|
2558
|
+
edit: EditProxy;
|
|
2559
|
+
}
|
|
2560
|
+
/** Cache hint returned by the content loader for route caching */
|
|
2561
|
+
interface CacheHint {
|
|
2562
|
+
tags?: string[];
|
|
2563
|
+
lastModified?: Date;
|
|
2564
|
+
}
|
|
2565
|
+
/**
|
|
2566
|
+
* Result from getDinewayCollection
|
|
2567
|
+
*/
|
|
2568
|
+
interface CollectionResult<T> {
|
|
2569
|
+
/** The entries (empty array if error or none found) */
|
|
2570
|
+
entries: ContentEntry<T>[];
|
|
2571
|
+
/** Error if the query failed */
|
|
2572
|
+
error?: Error;
|
|
2573
|
+
/** Cache hint for route caching (pass to Astro.cache.set()) */
|
|
2574
|
+
cacheHint: CacheHint;
|
|
2669
2575
|
/**
|
|
2670
|
-
*
|
|
2576
|
+
* Opaque cursor for the next page.
|
|
2577
|
+
* Undefined when there are no more results.
|
|
2578
|
+
* Pass this as `cursor` in the next query to get the next page.
|
|
2671
2579
|
*/
|
|
2672
|
-
|
|
2673
|
-
pluginId: string;
|
|
2674
|
-
}>;
|
|
2580
|
+
nextCursor?: string;
|
|
2675
2581
|
/**
|
|
2676
|
-
*
|
|
2677
|
-
*
|
|
2582
|
+
* Whether more entries exist beyond this page. Set whenever `limit` is
|
|
2583
|
+
* provided, including offset-paginated numbered archives.
|
|
2678
2584
|
*/
|
|
2679
|
-
|
|
2680
|
-
pluginId: string;
|
|
2681
|
-
}>;
|
|
2585
|
+
hasMore?: boolean;
|
|
2682
2586
|
/**
|
|
2683
|
-
*
|
|
2684
|
-
* Returns null if no provider is selected or if the selected hook
|
|
2685
|
-
* is not found in the pipeline.
|
|
2686
|
-
*
|
|
2687
|
-
* This is a generic dispatch used by the email pipeline and other
|
|
2688
|
-
* exclusive hook consumers. The handler type is unknown — callers
|
|
2689
|
-
* must know the expected signature.
|
|
2690
|
-
*
|
|
2691
|
-
* Errors are isolated: a failing handler returns an error result
|
|
2692
|
-
* instead of propagating the exception to the caller.
|
|
2587
|
+
* Total number of entries matching the current filter, excluding cursor and limit.
|
|
2693
2588
|
*/
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2589
|
+
total?: number;
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Result from getDinewayEntry
|
|
2593
|
+
*/
|
|
2594
|
+
interface EntryResult<T> {
|
|
2595
|
+
/** The entry, or null if not found */
|
|
2596
|
+
entry: ContentEntry<T> | null;
|
|
2597
|
+
/** Error if the query failed (not set for "not found", only for actual errors) */
|
|
2598
|
+
error?: Error;
|
|
2599
|
+
/** Whether we're in preview mode (valid token was provided) */
|
|
2600
|
+
isPreview: boolean;
|
|
2601
|
+
/** Set when a fallback locale was used instead of the requested locale */
|
|
2602
|
+
fallbackLocale?: string;
|
|
2603
|
+
/** Cache hint for route caching (pass to Astro.cache.set()) */
|
|
2604
|
+
cacheHint: CacheHint;
|
|
2605
|
+
}
|
|
2606
|
+
/** Edit metadata attached to PT arrays in edit mode */
|
|
2607
|
+
interface EditFieldMeta {
|
|
2608
|
+
collection: string;
|
|
2609
|
+
id: string;
|
|
2610
|
+
field: string;
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Read edit metadata from a value (returns undefined if not tagged).
|
|
2614
|
+
* Uses Object.getOwnPropertyDescriptor to access Symbol-keyed property
|
|
2615
|
+
* without an unsafe type assertion.
|
|
2616
|
+
*/
|
|
2617
|
+
declare function getEditMeta(value: unknown): EditFieldMeta | undefined;
|
|
2618
|
+
/**
|
|
2619
|
+
* Get all entries of a content type
|
|
2620
|
+
*
|
|
2621
|
+
* Returns { entries, error } for graceful error handling.
|
|
2622
|
+
*
|
|
2623
|
+
* When dineway-env.d.ts is generated, the collection name will be
|
|
2624
|
+
* type-checked and the return type will be inferred automatically.
|
|
2625
|
+
*
|
|
2626
|
+
* @example
|
|
2627
|
+
* ```ts
|
|
2628
|
+
* import { getDinewayCollection } from "dineway";
|
|
2629
|
+
*
|
|
2630
|
+
* const { entries: posts, error } = await getDinewayCollection("posts");
|
|
2631
|
+
* if (error) {
|
|
2632
|
+
* console.error("Failed to load posts:", error);
|
|
2633
|
+
* return;
|
|
2634
|
+
* }
|
|
2635
|
+
* // posts[0].data.title is typed (if dineway-env.d.ts exists)
|
|
2636
|
+
*
|
|
2637
|
+
* // With filters
|
|
2638
|
+
* const { entries: drafts } = await getDinewayCollection("posts", { status: "draft" });
|
|
2639
|
+
* ```
|
|
2640
|
+
*/
|
|
2641
|
+
declare function getDinewayCollection<T extends string, D = InferCollectionData<T>>(type: T, filter?: CollectionFilter): Promise<CollectionResult<D>>;
|
|
2642
|
+
/**
|
|
2643
|
+
* Get a single entry by type and ID/slug
|
|
2644
|
+
*
|
|
2645
|
+
* Returns { entry, error, isPreview } for graceful error handling.
|
|
2646
|
+
* - entry is null if not found (not an error)
|
|
2647
|
+
* - error is set only for actual errors (db issues, etc.)
|
|
2648
|
+
*
|
|
2649
|
+
* Preview mode is detected automatically from request context (ALS).
|
|
2650
|
+
* When the URL has a valid `_preview` token, the middleware sets preview
|
|
2651
|
+
* context and this function serves draft revision data if available.
|
|
2652
|
+
*
|
|
2653
|
+
* @example
|
|
2654
|
+
* ```ts
|
|
2655
|
+
* import { getDinewayEntry } from "dineway";
|
|
2656
|
+
*
|
|
2657
|
+
* // Simple usage — preview just works via middleware
|
|
2658
|
+
* const { entry: post, isPreview, error } = await getDinewayEntry("posts", "my-slug");
|
|
2659
|
+
* if (!post) return Astro.redirect("/404");
|
|
2660
|
+
* ```
|
|
2661
|
+
*/
|
|
2662
|
+
declare function getDinewayEntry<T extends string, D = InferCollectionData<T>>(type: T, id: string, options?: {
|
|
2663
|
+
locale?: string;
|
|
2664
|
+
}): Promise<EntryResult<D>>;
|
|
2665
|
+
/**
|
|
2666
|
+
* Translation summary for a single locale variant
|
|
2667
|
+
*/
|
|
2668
|
+
interface TranslationSummary {
|
|
2669
|
+
/** Content item ID */
|
|
2670
|
+
id: string;
|
|
2671
|
+
/** Locale code (e.g. "en", "fr") */
|
|
2672
|
+
locale: string;
|
|
2673
|
+
/** URL slug */
|
|
2674
|
+
slug: string | null;
|
|
2675
|
+
/** Current status */
|
|
2676
|
+
status: string;
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Result from getTranslations
|
|
2680
|
+
*/
|
|
2681
|
+
interface TranslationsResult {
|
|
2682
|
+
/** The translation group ID (shared across locales) */
|
|
2683
|
+
translationGroup: string;
|
|
2684
|
+
/** All locale variants in this group */
|
|
2685
|
+
translations: TranslationSummary[];
|
|
2686
|
+
/** Error if the query failed */
|
|
2687
|
+
error?: Error;
|
|
2688
|
+
}
|
|
2689
|
+
/**
|
|
2690
|
+
* Get all translations of a content item.
|
|
2691
|
+
*
|
|
2692
|
+
* Given a content entry, returns all locale variants that share the same
|
|
2693
|
+
* translation group. This is useful for building language switcher UI.
|
|
2694
|
+
*
|
|
2695
|
+
* @example
|
|
2696
|
+
* ```ts
|
|
2697
|
+
* import { getDinewayEntry, getTranslations } from "dineway";
|
|
2698
|
+
*
|
|
2699
|
+
* const { entry: post } = await getDinewayEntry("posts", "hello-world", { locale: "en" });
|
|
2700
|
+
* const { translations } = await getTranslations("posts", post.data.id);
|
|
2701
|
+
* // translations = [{ id: "...", locale: "en", slug: "hello-world", status: "published" }, ...]
|
|
2702
|
+
* ```
|
|
2703
|
+
*/
|
|
2704
|
+
declare function getTranslations(type: string, id: string): Promise<TranslationsResult>;
|
|
2705
|
+
/**
|
|
2706
|
+
* Result from resolveDinewayPath
|
|
2707
|
+
*/
|
|
2708
|
+
interface ResolvePathResult<T = Record<string, unknown>> {
|
|
2709
|
+
/** The matched entry */
|
|
2710
|
+
entry: ContentEntry<T>;
|
|
2711
|
+
/** The collection slug that matched */
|
|
2712
|
+
collection: string;
|
|
2713
|
+
/** Extracted parameters from the URL pattern (e.g. { slug: "my-post" }) */
|
|
2714
|
+
params: Record<string, string>;
|
|
2715
|
+
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Resolve a URL path to a content entry by matching against collection URL patterns.
|
|
2718
|
+
*
|
|
2719
|
+
* Loads all collections with a `urlPattern` set, converts each pattern to a regex,
|
|
2720
|
+
* and tests the given path. On match, extracts the slug and fetches the entry.
|
|
2721
|
+
*
|
|
2722
|
+
* @example
|
|
2723
|
+
* ```ts
|
|
2724
|
+
* import { resolveDinewayPath } from "dineway";
|
|
2725
|
+
*
|
|
2726
|
+
* // Given pages with urlPattern "/{slug}" and posts with "/blog/{slug}":
|
|
2727
|
+
* const result = await resolveDinewayPath("/blog/hello-world");
|
|
2728
|
+
* if (result) {
|
|
2729
|
+
* console.log(result.collection); // "posts"
|
|
2730
|
+
* console.log(result.params.slug); // "hello-world"
|
|
2731
|
+
* console.log(result.entry.data); // post data
|
|
2732
|
+
* }
|
|
2733
|
+
* ```
|
|
2734
|
+
*/
|
|
2735
|
+
declare function resolveDinewayPath<T = Record<string, unknown>>(path: string): Promise<ResolvePathResult<T> | null>;
|
|
2736
|
+
//#endregion
|
|
2737
|
+
//#region src/after.d.ts
|
|
2738
|
+
/**
|
|
2739
|
+
* Defer work past the current synchronous path.
|
|
2740
|
+
*
|
|
2741
|
+
* Use this for best-effort bookkeeping that should not block runtime
|
|
2742
|
+
* initialization or response handling. Node keeps the process alive for
|
|
2743
|
+
* pending work; callers that need stronger durability should await their own
|
|
2744
|
+
* operation instead of using this helper.
|
|
2745
|
+
*/
|
|
2746
|
+
type AfterCallback = () => void | Promise<void>;
|
|
2747
|
+
declare function after(fn: AfterCallback): void;
|
|
2748
|
+
//#endregion
|
|
2749
|
+
//#region src/object-cache/index.d.ts
|
|
2750
|
+
/** Options for {@link cachedQuery}. */
|
|
2751
|
+
interface CachedQueryOptions<T> {
|
|
2752
|
+
/**
|
|
2753
|
+
* Invalidation namespace(s). A single string for self-contained data
|
|
2754
|
+
* (`settings`, `menus`), or several when the cached value depends on data
|
|
2755
|
+
* owned by other namespaces — e.g. a content entry hydrates bylines and
|
|
2756
|
+
* taxonomy terms, so it caches under
|
|
2757
|
+
* `[content:posts, "bylines", "taxonomies"]` and is invalidated when *any*
|
|
2758
|
+
* of them is bumped. Every namespace's epoch is folded into the key.
|
|
2759
|
+
*/
|
|
2760
|
+
namespace: string | readonly string[];
|
|
2761
|
+
/** Stable, fully-qualifying cache key *within* the namespace. */
|
|
2762
|
+
key: string;
|
|
2763
|
+
/** Loader run on a miss (or when caching is disabled/bypassed). */
|
|
2764
|
+
load: () => Promise<T>;
|
|
2765
|
+
/** TTL override in seconds. Falls back to the configured `defaultTtl`. */
|
|
2766
|
+
ttl?: number;
|
|
2767
|
+
/**
|
|
2768
|
+
* Predicate gating whether a freshly-loaded value is stored. Defaults to
|
|
2769
|
+
* always-cache. Use it to skip caching error/empty sentinels.
|
|
2770
|
+
*/
|
|
2771
|
+
cacheable?: (value: T) => boolean;
|
|
2772
|
+
}
|
|
2773
|
+
/**
|
|
2774
|
+
* Distributed read-through cache around `load`.
|
|
2775
|
+
*
|
|
2776
|
+
* `T` must be the value as it should be *stored* — i.e. JSON-serializable with
|
|
2777
|
+
* the codec's `Date` support, carrying no functions or symbol-keyed props.
|
|
2778
|
+
* Callers caching richer objects (content entries) reduce to a serializable
|
|
2779
|
+
* snapshot here and rebuild on the way out; see `query.ts`.
|
|
2780
|
+
*
|
|
2781
|
+
* On a miss or when the cache is disabled/bypassed, this is equivalent to
|
|
2782
|
+
* `await load()`. Backend errors never propagate: a failing `get` is a miss, a
|
|
2783
|
+
* failing `set` is dropped.
|
|
2784
|
+
*/
|
|
2785
|
+
declare function cachedQuery<T>(options: CachedQueryOptions<T>): Promise<T>;
|
|
2786
|
+
/** Whether object-cache reads are active for the current request. */
|
|
2787
|
+
declare function isObjectCacheActive(): Promise<boolean>;
|
|
2788
|
+
/**
|
|
2789
|
+
* Invalidate every cached value in `namespace` by bumping its epoch.
|
|
2790
|
+
*
|
|
2791
|
+
* Sync and non-blocking: the local epoch is stamped immediately (so the
|
|
2792
|
+
* writing isolate is instantly consistent) and the backend write is deferred
|
|
2793
|
+
* via `after`. Other isolates pick up the new epoch within their `revalidate`
|
|
2794
|
+
* window. No-ops when the cache is disabled.
|
|
2795
|
+
*/
|
|
2796
|
+
declare function invalidateObjectCache(namespace: string): void;
|
|
2797
|
+
/**
|
|
2798
|
+
* Fixed namespaces for data shared across collections. Content reads fold the
|
|
2799
|
+
* `BYLINES` and `TAXONOMIES` epochs into their keys (via {@link cachedQuery})
|
|
2800
|
+
* because entries hydrate byline and taxonomy-term data — so renaming an
|
|
2801
|
+
* author or a category correctly invalidates every cached entry that displays
|
|
2802
|
+
* it, without tracking which collections reference it.
|
|
2803
|
+
*/
|
|
2804
|
+
declare const CacheNamespace: {
|
|
2805
|
+
readonly SETTINGS: "settings";
|
|
2806
|
+
readonly MENUS: "menus";
|
|
2807
|
+
readonly TAXONOMIES: "taxonomies";
|
|
2808
|
+
readonly BYLINES: "bylines"; /** Collection schema/metadata (label, supports, commentsEnabled, fields). */
|
|
2809
|
+
readonly SCHEMA: "schema"; /** Public (approved) comments. */
|
|
2810
|
+
readonly COMMENTS: "comments";
|
|
2811
|
+
};
|
|
2812
|
+
/** Namespace for a content collection's cached queries. */
|
|
2813
|
+
declare function contentNamespace(collection: string): string;
|
|
2814
|
+
/**
|
|
2815
|
+
* Namespaces a content read depends on: the collection itself plus the shared
|
|
2816
|
+
* byline/taxonomy data folded into each entry.
|
|
2817
|
+
*/
|
|
2818
|
+
declare function contentNamespaces(collection: string): readonly string[];
|
|
2819
|
+
/**
|
|
2820
|
+
* Invalidate all cached reads (list + entry) for a content collection.
|
|
2821
|
+
* Call from every write path that mutates rows in `ec_<collection>`.
|
|
2822
|
+
*/
|
|
2823
|
+
declare function invalidateCollectionCache(collection: string): void;
|
|
2824
|
+
/** Invalidate cached taxonomy definitions/terms and all content that hydrates them. */
|
|
2825
|
+
declare function invalidateTaxonomyObjectCache(): void;
|
|
2826
|
+
/** Invalidate cached bylines and all content that hydrates them. */
|
|
2827
|
+
declare function invalidateBylineObjectCache(): void;
|
|
2828
|
+
/** Invalidate cached navigation menus. */
|
|
2829
|
+
declare function invalidateMenuObjectCache(): void;
|
|
2830
|
+
/** Invalidate cached collection schema/metadata reads (e.g. getCollectionInfo). */
|
|
2831
|
+
declare function invalidateSchemaObjectCache(): void;
|
|
2832
|
+
/** Invalidate cached public comment reads. */
|
|
2833
|
+
declare function invalidateCommentObjectCache(): void;
|
|
2834
|
+
//#endregion
|
|
2835
|
+
//#region src/i18n/config.d.ts
|
|
2836
|
+
/**
|
|
2837
|
+
* Dineway i18n Configuration
|
|
2838
|
+
*
|
|
2839
|
+
* Reads locale configuration from the virtual module (sourced from Astro config).
|
|
2840
|
+
* Initialized during runtime startup, then available via getI18nConfig().
|
|
2841
|
+
*/
|
|
2842
|
+
interface I18nConfig {
|
|
2843
|
+
defaultLocale: string;
|
|
2844
|
+
locales: string[];
|
|
2845
|
+
fallback?: Record<string, string>;
|
|
2846
|
+
prefixDefaultLocale?: boolean;
|
|
2700
2847
|
}
|
|
2701
2848
|
/**
|
|
2702
|
-
*
|
|
2849
|
+
* Get the current i18n config.
|
|
2850
|
+
* Returns null if i18n is not configured.
|
|
2703
2851
|
*/
|
|
2704
|
-
declare function
|
|
2852
|
+
declare function getI18nConfig(): I18nConfig | null;
|
|
2853
|
+
/**
|
|
2854
|
+
* Check if i18n is enabled.
|
|
2855
|
+
* Returns true when multiple locales are configured.
|
|
2856
|
+
*/
|
|
2857
|
+
declare function isI18nEnabled(): boolean;
|
|
2858
|
+
/**
|
|
2859
|
+
* Resolve fallback locale chain for a given locale.
|
|
2860
|
+
* Returns array of locales to try, from most preferred to least.
|
|
2861
|
+
* Always ends with defaultLocale.
|
|
2862
|
+
*/
|
|
2863
|
+
declare function getFallbackChain(locale: string): string[];
|
|
2705
2864
|
//#endregion
|
|
2706
|
-
//#region src/
|
|
2865
|
+
//#region src/preview/sidecar-client.d.ts
|
|
2707
2866
|
/**
|
|
2708
|
-
*
|
|
2867
|
+
* Preview sidecar protocol helpers.
|
|
2709
2868
|
*
|
|
2710
|
-
*
|
|
2711
|
-
*
|
|
2712
|
-
* 2. email:deliver — exclusive hook dispatching to the selected provider
|
|
2713
|
-
* 3. email:afterSend — fire-and-forget hooks for logging/analytics
|
|
2869
|
+
* These utilities define the signed URL and snapshot-auth contract shared
|
|
2870
|
+
* by preview sidecars and the source site serving snapshot exports.
|
|
2714
2871
|
*/
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2872
|
+
interface PreviewSidecarSignature {
|
|
2873
|
+
source: string;
|
|
2874
|
+
exp: number;
|
|
2875
|
+
sig: string;
|
|
2876
|
+
}
|
|
2877
|
+
interface PreviewSidecarClient {
|
|
2878
|
+
signPreviewUrl(previewBase: string, source: string, secret: string, ttl?: number): Promise<string>;
|
|
2879
|
+
buildSnapshotSignatureHeader(signature: PreviewSidecarSignature): string;
|
|
2880
|
+
}
|
|
2881
|
+
declare function signPreviewUrl(previewBase: string, source: string, secret: string, ttl?: number): Promise<string>;
|
|
2882
|
+
declare function buildPreviewSignatureHeader(signature: PreviewSidecarSignature): string;
|
|
2883
|
+
declare function parsePreviewSignatureHeader(header: string): PreviewSidecarSignature | null;
|
|
2884
|
+
declare function verifyPreviewSignature(source: string, exp: number, sig: string, secret: string): Promise<boolean>;
|
|
2885
|
+
declare const defaultPreviewSidecarClient: PreviewSidecarClient;
|
|
2886
|
+
//#endregion
|
|
2887
|
+
//#region src/preview/session-database-factory.d.ts
|
|
2888
|
+
interface SessionDatabaseInfo {
|
|
2889
|
+
id: string;
|
|
2890
|
+
dbPath: string;
|
|
2891
|
+
createdAt: number;
|
|
2892
|
+
expiresAt: number;
|
|
2893
|
+
lastTouchedAt: number;
|
|
2894
|
+
}
|
|
2895
|
+
interface SessionDatabaseHandle {
|
|
2896
|
+
created: boolean;
|
|
2897
|
+
session: SessionDatabaseInfo;
|
|
2898
|
+
db: Kysely<Database>;
|
|
2899
|
+
close(): Promise<void>;
|
|
2900
|
+
}
|
|
2901
|
+
interface SessionCleanupResult {
|
|
2902
|
+
removedSessionIds: string[];
|
|
2903
|
+
removedPaths: string[];
|
|
2904
|
+
}
|
|
2905
|
+
interface SessionOpenOptions {
|
|
2906
|
+
id: string;
|
|
2907
|
+
now?: number;
|
|
2908
|
+
}
|
|
2909
|
+
interface SessionOpenOrCreateOptions extends SessionOpenOptions {
|
|
2910
|
+
ttlMs: number;
|
|
2911
|
+
}
|
|
2912
|
+
interface SessionDatabaseFactory {
|
|
2913
|
+
open(input: SessionOpenOptions): Promise<SessionDatabaseHandle | null>;
|
|
2914
|
+
openOrCreate(input: SessionOpenOrCreateOptions): Promise<SessionDatabaseHandle>;
|
|
2915
|
+
destroy(id: string): Promise<boolean>;
|
|
2916
|
+
cleanup(now?: number): Promise<SessionCleanupResult>;
|
|
2917
|
+
close(): Promise<void>;
|
|
2918
|
+
}
|
|
2919
|
+
interface FileSessionDatabaseFactoryOptions {
|
|
2920
|
+
rootDir: string;
|
|
2921
|
+
maxDiskBytes?: number;
|
|
2922
|
+
registryFileName?: string;
|
|
2923
|
+
sessionsDirName?: string;
|
|
2924
|
+
}
|
|
2925
|
+
declare class SessionDatabaseLimitError extends Error {
|
|
2926
|
+
constructor(message?: string);
|
|
2927
|
+
}
|
|
2928
|
+
declare class FileSessionDatabaseFactory implements SessionDatabaseFactory {
|
|
2929
|
+
private readonly options;
|
|
2930
|
+
private readonly registry;
|
|
2931
|
+
private readonly sessionsDir;
|
|
2932
|
+
private readonly maxDiskBytes;
|
|
2933
|
+
constructor(options: FileSessionDatabaseFactoryOptions);
|
|
2934
|
+
open(input: SessionOpenOptions): Promise<SessionDatabaseHandle | null>;
|
|
2935
|
+
openOrCreate(input: SessionOpenOrCreateOptions): Promise<SessionDatabaseHandle>;
|
|
2936
|
+
destroy(id: string): Promise<boolean>;
|
|
2937
|
+
cleanup(now?: number): Promise<SessionCleanupResult>;
|
|
2938
|
+
close(): Promise<void>;
|
|
2939
|
+
private createHandle;
|
|
2940
|
+
private getSessionRow;
|
|
2941
|
+
private toSessionInfo;
|
|
2942
|
+
private deleteSession;
|
|
2943
|
+
private getActiveDiskBytes;
|
|
2944
|
+
private getDbPath;
|
|
2945
|
+
private getManagedPaths;
|
|
2946
|
+
private listSessionRows;
|
|
2947
|
+
private listDbPathRows;
|
|
2948
|
+
}
|
|
2949
|
+
//#endregion
|
|
2950
|
+
//#region src/preview/middleware.d.ts
|
|
2951
|
+
interface FilePreviewMiddlewareConfig {
|
|
2952
|
+
rootDir?: string;
|
|
2953
|
+
secret: string;
|
|
2954
|
+
ttlSeconds?: number;
|
|
2955
|
+
cookieName?: string;
|
|
2956
|
+
snapshotPath?: string;
|
|
2957
|
+
maxSessionDiskBytes?: number;
|
|
2958
|
+
sessionFactory?: SessionDatabaseFactory;
|
|
2959
|
+
fetch?: typeof globalThis.fetch;
|
|
2748
2960
|
}
|
|
2961
|
+
declare function createFilePreviewMiddleware(config: FilePreviewMiddlewareConfig): MiddlewareHandler;
|
|
2962
|
+
//#endregion
|
|
2963
|
+
//#region src/plugins/define-plugin.d.ts
|
|
2964
|
+
/**
|
|
2965
|
+
* Define a Dineway plugin.
|
|
2966
|
+
*
|
|
2967
|
+
* **Standard format** -- the canonical format for plugins that work in both
|
|
2968
|
+
* trusted and sandboxed modes. No id/version -- those come from the descriptor.
|
|
2969
|
+
*
|
|
2970
|
+
* @example
|
|
2971
|
+
* ```typescript
|
|
2972
|
+
* import { definePlugin } from "dineway";
|
|
2973
|
+
*
|
|
2974
|
+
* export default definePlugin({
|
|
2975
|
+
* hooks: {
|
|
2976
|
+
* "content:afterSave": {
|
|
2977
|
+
* handler: async (event, ctx) => {
|
|
2978
|
+
* await ctx.kv.set("lastSave", Date.now());
|
|
2979
|
+
* },
|
|
2980
|
+
* },
|
|
2981
|
+
* },
|
|
2982
|
+
* routes: {
|
|
2983
|
+
* status: {
|
|
2984
|
+
* handler: async (routeCtx, ctx) => ({ ok: true }),
|
|
2985
|
+
* },
|
|
2986
|
+
* },
|
|
2987
|
+
* });
|
|
2988
|
+
* ```
|
|
2989
|
+
*
|
|
2990
|
+
* **Native format** -- for plugins that need React admin, direct DB access,
|
|
2991
|
+
* or other capabilities not available in the sandbox.
|
|
2992
|
+
*
|
|
2993
|
+
* @example
|
|
2994
|
+
* ```typescript
|
|
2995
|
+
* import { definePlugin } from "dineway";
|
|
2996
|
+
*
|
|
2997
|
+
* export default definePlugin({
|
|
2998
|
+
* id: "my-plugin",
|
|
2999
|
+
* version: "1.0.0",
|
|
3000
|
+
* capabilities: ["content:read"],
|
|
3001
|
+
* hooks: {
|
|
3002
|
+
* "content:beforeSave": async (event, ctx) => {
|
|
3003
|
+
* ctx.log.info("Saving content", { collection: event.collection });
|
|
3004
|
+
* return event.content;
|
|
3005
|
+
* }
|
|
3006
|
+
* },
|
|
3007
|
+
* routes: {
|
|
3008
|
+
* "sync": {
|
|
3009
|
+
* handler: async (ctx) => {
|
|
3010
|
+
* return { status: "ok" };
|
|
3011
|
+
* }
|
|
3012
|
+
* }
|
|
3013
|
+
* }
|
|
3014
|
+
* });
|
|
3015
|
+
* ```
|
|
3016
|
+
*/
|
|
3017
|
+
declare function definePlugin<TStorage extends PluginStorageConfig>(definition: PluginDefinition<TStorage>): ResolvedPlugin<TStorage>;
|
|
3018
|
+
declare function definePlugin(definition: StandardPluginDefinition): StandardPluginDefinition;
|
|
3019
|
+
//#endregion
|
|
3020
|
+
//#region src/plugins/manifest-schema.d.ts
|
|
3021
|
+
/**
|
|
3022
|
+
* Zod schema matching the PluginManifest interface from types.ts.
|
|
3023
|
+
*
|
|
3024
|
+
* Every JSON.parse of a manifest.json should validate through this.
|
|
3025
|
+
*/
|
|
3026
|
+
declare const pluginManifestSchema: z$1.ZodObject<{
|
|
3027
|
+
id: z$1.ZodString;
|
|
3028
|
+
version: z$1.ZodString;
|
|
3029
|
+
declaredAccess: z$1.ZodOptional<z$1.ZodObject<{
|
|
3030
|
+
content: z$1.ZodOptional<z$1.ZodObject<{
|
|
3031
|
+
read: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3032
|
+
write: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3033
|
+
}, z$1.core.$strip>>;
|
|
3034
|
+
media: z$1.ZodOptional<z$1.ZodObject<{
|
|
3035
|
+
read: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3036
|
+
write: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3037
|
+
}, z$1.core.$strip>>;
|
|
3038
|
+
network: z$1.ZodOptional<z$1.ZodObject<{
|
|
3039
|
+
request: z$1.ZodOptional<z$1.ZodObject<{
|
|
3040
|
+
allowedHosts: z$1.ZodOptional<z$1.ZodArray<z$1.ZodString>>;
|
|
3041
|
+
}, z$1.core.$strip>>;
|
|
3042
|
+
}, z$1.core.$strip>>;
|
|
3043
|
+
email: z$1.ZodOptional<z$1.ZodObject<{
|
|
3044
|
+
send: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3045
|
+
events: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3046
|
+
transport: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3047
|
+
}, z$1.core.$strip>>;
|
|
3048
|
+
page: z$1.ZodOptional<z$1.ZodObject<{
|
|
3049
|
+
fragments: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3050
|
+
}, z$1.core.$strip>>;
|
|
3051
|
+
users: z$1.ZodOptional<z$1.ZodObject<{
|
|
3052
|
+
read: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodUnknown>>;
|
|
3053
|
+
}, z$1.core.$strip>>;
|
|
3054
|
+
}, z$1.core.$strip>>;
|
|
3055
|
+
capabilities: z$1.ZodArray<z$1.ZodEnum<{
|
|
3056
|
+
"network:request": "network:request";
|
|
3057
|
+
"network:request:unrestricted": "network:request:unrestricted";
|
|
3058
|
+
"content:read": "content:read";
|
|
3059
|
+
"content:write": "content:write";
|
|
3060
|
+
"media:read": "media:read";
|
|
3061
|
+
"media:write": "media:write";
|
|
3062
|
+
"users:read": "users:read";
|
|
3063
|
+
"email:send": "email:send";
|
|
3064
|
+
"hooks.email-transport:register": "hooks.email-transport:register";
|
|
3065
|
+
"hooks.email-events:register": "hooks.email-events:register";
|
|
3066
|
+
"hooks.page-fragments:register": "hooks.page-fragments:register";
|
|
3067
|
+
}>>;
|
|
3068
|
+
allowedHosts: z$1.ZodArray<z$1.ZodString>;
|
|
3069
|
+
storage: z$1.ZodRecord<z$1.ZodString, z$1.ZodObject<{
|
|
3070
|
+
indexes: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodArray<z$1.ZodString>]>>;
|
|
3071
|
+
uniqueIndexes: z$1.ZodOptional<z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodArray<z$1.ZodString>]>>>;
|
|
3072
|
+
}, z$1.core.$strip>>;
|
|
3073
|
+
hooks: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodEnum<{
|
|
3074
|
+
"plugin:install": "plugin:install";
|
|
3075
|
+
"plugin:activate": "plugin:activate";
|
|
3076
|
+
"plugin:deactivate": "plugin:deactivate";
|
|
3077
|
+
"plugin:uninstall": "plugin:uninstall";
|
|
3078
|
+
"content:beforeSave": "content:beforeSave";
|
|
3079
|
+
"content:afterSave": "content:afterSave";
|
|
3080
|
+
"content:beforeDelete": "content:beforeDelete";
|
|
3081
|
+
"content:afterDelete": "content:afterDelete";
|
|
3082
|
+
"content:afterPublish": "content:afterPublish";
|
|
3083
|
+
"content:afterUnpublish": "content:afterUnpublish";
|
|
3084
|
+
"content:afterRestore": "content:afterRestore";
|
|
3085
|
+
"content:afterSchedule": "content:afterSchedule";
|
|
3086
|
+
"content:afterUnschedule": "content:afterUnschedule";
|
|
3087
|
+
"media:beforeUpload": "media:beforeUpload";
|
|
3088
|
+
"media:afterUpload": "media:afterUpload";
|
|
3089
|
+
cron: "cron";
|
|
3090
|
+
"email:beforeSend": "email:beforeSend";
|
|
3091
|
+
"email:deliver": "email:deliver";
|
|
3092
|
+
"email:afterSend": "email:afterSend";
|
|
3093
|
+
"comment:beforeCreate": "comment:beforeCreate";
|
|
3094
|
+
"comment:moderate": "comment:moderate";
|
|
3095
|
+
"comment:afterCreate": "comment:afterCreate";
|
|
3096
|
+
"comment:afterModerate": "comment:afterModerate";
|
|
3097
|
+
"page:metadata": "page:metadata";
|
|
3098
|
+
"page:fragments": "page:fragments";
|
|
3099
|
+
}>, z$1.ZodObject<{
|
|
3100
|
+
name: z$1.ZodEnum<{
|
|
3101
|
+
"plugin:install": "plugin:install";
|
|
3102
|
+
"plugin:activate": "plugin:activate";
|
|
3103
|
+
"plugin:deactivate": "plugin:deactivate";
|
|
3104
|
+
"plugin:uninstall": "plugin:uninstall";
|
|
3105
|
+
"content:beforeSave": "content:beforeSave";
|
|
3106
|
+
"content:afterSave": "content:afterSave";
|
|
3107
|
+
"content:beforeDelete": "content:beforeDelete";
|
|
3108
|
+
"content:afterDelete": "content:afterDelete";
|
|
3109
|
+
"content:afterPublish": "content:afterPublish";
|
|
3110
|
+
"content:afterUnpublish": "content:afterUnpublish";
|
|
3111
|
+
"content:afterRestore": "content:afterRestore";
|
|
3112
|
+
"content:afterSchedule": "content:afterSchedule";
|
|
3113
|
+
"content:afterUnschedule": "content:afterUnschedule";
|
|
3114
|
+
"media:beforeUpload": "media:beforeUpload";
|
|
3115
|
+
"media:afterUpload": "media:afterUpload";
|
|
3116
|
+
cron: "cron";
|
|
3117
|
+
"email:beforeSend": "email:beforeSend";
|
|
3118
|
+
"email:deliver": "email:deliver";
|
|
3119
|
+
"email:afterSend": "email:afterSend";
|
|
3120
|
+
"comment:beforeCreate": "comment:beforeCreate";
|
|
3121
|
+
"comment:moderate": "comment:moderate";
|
|
3122
|
+
"comment:afterCreate": "comment:afterCreate";
|
|
3123
|
+
"comment:afterModerate": "comment:afterModerate";
|
|
3124
|
+
"page:metadata": "page:metadata";
|
|
3125
|
+
"page:fragments": "page:fragments";
|
|
3126
|
+
}>;
|
|
3127
|
+
exclusive: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
3128
|
+
priority: z$1.ZodOptional<z$1.ZodNumber>;
|
|
3129
|
+
timeout: z$1.ZodOptional<z$1.ZodNumber>;
|
|
3130
|
+
}, z$1.core.$strip>]>>;
|
|
3131
|
+
routes: z$1.ZodArray<z$1.ZodUnion<readonly [z$1.ZodString, z$1.ZodObject<{
|
|
3132
|
+
name: z$1.ZodString;
|
|
3133
|
+
public: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
3134
|
+
}, z$1.core.$strip>]>>;
|
|
3135
|
+
admin: z$1.ZodObject<{
|
|
3136
|
+
entry: z$1.ZodOptional<z$1.ZodString>;
|
|
3137
|
+
settingsSchema: z$1.ZodOptional<z$1.ZodRecord<z$1.ZodString, z$1.ZodDiscriminatedUnion<[z$1.ZodObject<{
|
|
3138
|
+
type: z$1.ZodLiteral<"string">;
|
|
3139
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
3140
|
+
multiline: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
3141
|
+
label: z$1.ZodString;
|
|
3142
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3143
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3144
|
+
type: z$1.ZodLiteral<"number">;
|
|
3145
|
+
default: z$1.ZodOptional<z$1.ZodNumber>;
|
|
3146
|
+
min: z$1.ZodOptional<z$1.ZodNumber>;
|
|
3147
|
+
max: z$1.ZodOptional<z$1.ZodNumber>;
|
|
3148
|
+
label: z$1.ZodString;
|
|
3149
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3150
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3151
|
+
type: z$1.ZodLiteral<"boolean">;
|
|
3152
|
+
default: z$1.ZodOptional<z$1.ZodBoolean>;
|
|
3153
|
+
label: z$1.ZodString;
|
|
3154
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3155
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3156
|
+
type: z$1.ZodLiteral<"select">;
|
|
3157
|
+
options: z$1.ZodArray<z$1.ZodObject<{
|
|
3158
|
+
value: z$1.ZodString;
|
|
3159
|
+
label: z$1.ZodString;
|
|
3160
|
+
}, z$1.core.$strip>>;
|
|
3161
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
3162
|
+
label: z$1.ZodString;
|
|
3163
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3164
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3165
|
+
type: z$1.ZodLiteral<"secret">;
|
|
3166
|
+
label: z$1.ZodString;
|
|
3167
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3168
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3169
|
+
type: z$1.ZodLiteral<"url">;
|
|
3170
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
3171
|
+
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
3172
|
+
label: z$1.ZodString;
|
|
3173
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3174
|
+
}, z$1.core.$strip>, z$1.ZodObject<{
|
|
3175
|
+
type: z$1.ZodLiteral<"email">;
|
|
3176
|
+
default: z$1.ZodOptional<z$1.ZodString>;
|
|
3177
|
+
placeholder: z$1.ZodOptional<z$1.ZodString>;
|
|
3178
|
+
label: z$1.ZodString;
|
|
3179
|
+
description: z$1.ZodOptional<z$1.ZodString>;
|
|
3180
|
+
}, z$1.core.$strip>], "type">>>;
|
|
3181
|
+
pages: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
3182
|
+
path: z$1.ZodString;
|
|
3183
|
+
label: z$1.ZodString;
|
|
3184
|
+
icon: z$1.ZodOptional<z$1.ZodString>;
|
|
3185
|
+
}, z$1.core.$strip>>>;
|
|
3186
|
+
widgets: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
3187
|
+
id: z$1.ZodString;
|
|
3188
|
+
size: z$1.ZodOptional<z$1.ZodEnum<{
|
|
3189
|
+
full: "full";
|
|
3190
|
+
half: "half";
|
|
3191
|
+
third: "third";
|
|
3192
|
+
}>>;
|
|
3193
|
+
title: z$1.ZodOptional<z$1.ZodString>;
|
|
3194
|
+
}, z$1.core.$strip>>>;
|
|
3195
|
+
fieldWidgets: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
3196
|
+
name: z$1.ZodString;
|
|
3197
|
+
label: z$1.ZodString;
|
|
3198
|
+
fieldTypes: z$1.ZodArray<z$1.ZodEnum<{
|
|
3199
|
+
string: "string";
|
|
3200
|
+
number: "number";
|
|
3201
|
+
boolean: "boolean";
|
|
3202
|
+
file: "file";
|
|
3203
|
+
slug: "slug";
|
|
3204
|
+
text: "text";
|
|
3205
|
+
integer: "integer";
|
|
3206
|
+
datetime: "datetime";
|
|
3207
|
+
select: "select";
|
|
3208
|
+
multiSelect: "multiSelect";
|
|
3209
|
+
portableText: "portableText";
|
|
3210
|
+
image: "image";
|
|
3211
|
+
reference: "reference";
|
|
3212
|
+
json: "json";
|
|
3213
|
+
repeater: "repeater";
|
|
3214
|
+
}>>;
|
|
3215
|
+
elements: z$1.ZodOptional<z$1.ZodArray<z$1.ZodObject<{
|
|
3216
|
+
type: z$1.ZodString;
|
|
3217
|
+
action_id: z$1.ZodString;
|
|
3218
|
+
label: z$1.ZodOptional<z$1.ZodString>;
|
|
3219
|
+
}, z$1.core.$loose>>>;
|
|
3220
|
+
}, z$1.core.$strip>>>;
|
|
3221
|
+
}, z$1.core.$strip>;
|
|
3222
|
+
}, z$1.core.$strip>;
|
|
3223
|
+
type ValidatedPluginManifest = z$1.infer<typeof pluginManifestSchema>;
|
|
2749
3224
|
//#endregion
|
|
2750
|
-
//#region src/
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
interface PluginContextFactoryOptions {
|
|
2763
|
-
db: Kysely<Database>;
|
|
2764
|
-
/**
|
|
2765
|
-
* Storage backend for direct media uploads.
|
|
2766
|
-
* If not provided, upload() will throw.
|
|
2767
|
-
*/
|
|
2768
|
-
storage?: Storage;
|
|
2769
|
-
/**
|
|
2770
|
-
* Function to generate upload URLs for media.
|
|
2771
|
-
* If not provided, media write operations will throw.
|
|
2772
|
-
*/
|
|
2773
|
-
getUploadUrl?: (filename: string, contentType: string) => Promise<{
|
|
2774
|
-
uploadUrl: string;
|
|
2775
|
-
mediaId: string;
|
|
2776
|
-
}>;
|
|
2777
|
-
/**
|
|
2778
|
-
* Site information for ctx.site and ctx.url().
|
|
2779
|
-
* If not provided, site info will have empty defaults.
|
|
2780
|
-
*/
|
|
2781
|
-
siteInfo?: SiteInfoOptions;
|
|
2782
|
-
/**
|
|
2783
|
-
* Callback to notify the cron scheduler that the next due time may have changed.
|
|
2784
|
-
* If not provided, ctx.cron will not be available.
|
|
2785
|
-
*/
|
|
2786
|
-
cronReschedule?: () => void;
|
|
2787
|
-
/**
|
|
2788
|
-
* Email pipeline instance for ctx.email.
|
|
2789
|
-
* If not provided (or no provider configured), ctx.email will be undefined.
|
|
2790
|
-
*/
|
|
2791
|
-
emailPipeline?: EmailPipeline;
|
|
2792
|
-
/**
|
|
2793
|
-
* Trusted reverse-proxy headers for request metadata IP extraction.
|
|
2794
|
-
*/
|
|
2795
|
-
trustedProxyHeaders?: string[];
|
|
3225
|
+
//#region src/config/secrets.d.ts
|
|
3226
|
+
interface ParsedEncryptionKey {
|
|
3227
|
+
kid: string;
|
|
3228
|
+
key: Uint8Array;
|
|
3229
|
+
raw: string;
|
|
3230
|
+
}
|
|
3231
|
+
interface SecretsEnv {
|
|
3232
|
+
DINEWAY_ENCRYPTION_KEY?: string;
|
|
3233
|
+
DINEWAY_PREVIEW_SECRET?: string;
|
|
3234
|
+
PREVIEW_SECRET?: string;
|
|
3235
|
+
DINEWAY_IP_SALT?: string;
|
|
3236
|
+
IP_SALT?: string;
|
|
2796
3237
|
}
|
|
2797
3238
|
//#endregion
|
|
2798
|
-
//#region src/plugins/
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
message: string;
|
|
2808
|
-
details?: unknown;
|
|
2809
|
-
};
|
|
2810
|
-
status: number;
|
|
3239
|
+
//#region src/plugins/secrets.d.ts
|
|
3240
|
+
interface PluginSecretStatus {
|
|
3241
|
+
pluginId: string;
|
|
3242
|
+
name: string;
|
|
3243
|
+
present: true;
|
|
3244
|
+
fingerprint: string;
|
|
3245
|
+
keyId: string;
|
|
3246
|
+
createdAt: string;
|
|
3247
|
+
updatedAt: string;
|
|
2811
3248
|
}
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
interface InvokeRouteOptions {
|
|
2816
|
-
/** The original request */
|
|
2817
|
-
request: Request;
|
|
2818
|
-
/** Request body (already parsed) */
|
|
2819
|
-
body?: unknown;
|
|
3249
|
+
interface PluginSecretStoreOptions {
|
|
3250
|
+
env?: Pick<SecretsEnv, "DINEWAY_ENCRYPTION_KEY">;
|
|
3251
|
+
keys?: readonly ParsedEncryptionKey[];
|
|
2820
3252
|
}
|
|
2821
3253
|
/**
|
|
2822
|
-
*
|
|
2823
|
-
*
|
|
3254
|
+
* Encrypted storage for trusted plugin credentials.
|
|
3255
|
+
*
|
|
3256
|
+
* Management surfaces must use set/status/list/delete and never echo the value
|
|
3257
|
+
* passed to set. resolveForRuntime is reserved for trusted server-side provider
|
|
3258
|
+
* calls and must not be exposed through plugin routes, MCP, logs, or audit data.
|
|
2824
3259
|
*/
|
|
2825
|
-
declare class
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
* Create an unauthorized error (401)
|
|
2836
|
-
*/
|
|
2837
|
-
static unauthorized(message?: string): PluginRouteError;
|
|
2838
|
-
/**
|
|
2839
|
-
* Create a forbidden error (403)
|
|
2840
|
-
*/
|
|
2841
|
-
static forbidden(message?: string): PluginRouteError;
|
|
2842
|
-
/**
|
|
2843
|
-
* Create a not found error (404)
|
|
2844
|
-
*/
|
|
2845
|
-
static notFound(message?: string): PluginRouteError;
|
|
2846
|
-
/**
|
|
2847
|
-
* Create a conflict error (409)
|
|
2848
|
-
*/
|
|
2849
|
-
static conflict(message: string, details?: unknown): PluginRouteError;
|
|
2850
|
-
/**
|
|
2851
|
-
* Create an internal error (500)
|
|
2852
|
-
*/
|
|
2853
|
-
static internal(message?: string): PluginRouteError;
|
|
3260
|
+
declare class PluginSecretStore {
|
|
3261
|
+
private readonly repository;
|
|
3262
|
+
private readonly keysPromise;
|
|
3263
|
+
constructor(db: Kysely<Database> | Transaction<Database>, options?: PluginSecretStoreOptions);
|
|
3264
|
+
set(pluginId: string, name: string, value: string): Promise<PluginSecretStatus>;
|
|
3265
|
+
status(pluginId: string, name: string): Promise<PluginSecretStatus | null>;
|
|
3266
|
+
list(pluginId: string): Promise<PluginSecretStatus[]>;
|
|
3267
|
+
delete(pluginId: string, name: string): Promise<boolean>;
|
|
3268
|
+
resolveForRuntime(pluginId: string, name: string): Promise<string | null>;
|
|
3269
|
+
private requireKeys;
|
|
2854
3270
|
}
|
|
2855
3271
|
//#endregion
|
|
3272
|
+
//#region src/plugins/mcp-reviewed-executor.d.ts
|
|
3273
|
+
declare function createReviewedPluginMcpCommandExecutor(): PluginMcpCommandExecutor;
|
|
3274
|
+
//#endregion
|
|
2856
3275
|
//#region src/plugins/manager.d.ts
|
|
2857
3276
|
/**
|
|
2858
3277
|
* Plugin state in the manager
|
|
@@ -2952,6 +3371,18 @@ declare class PluginManager {
|
|
|
2952
3371
|
* Run content:afterUnpublish hooks across all active plugins
|
|
2953
3372
|
*/
|
|
2954
3373
|
runContentAfterUnpublish(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
3374
|
+
/**
|
|
3375
|
+
* Run content:afterRestore hooks across all active plugins
|
|
3376
|
+
*/
|
|
3377
|
+
runContentAfterRestore(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
3378
|
+
/**
|
|
3379
|
+
* Run content:afterSchedule hooks across all active plugins
|
|
3380
|
+
*/
|
|
3381
|
+
runContentAfterSchedule(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
3382
|
+
/**
|
|
3383
|
+
* Run content:afterUnschedule hooks across all active plugins
|
|
3384
|
+
*/
|
|
3385
|
+
runContentAfterUnschedule(content: Record<string, unknown>, collection: string): Promise<HookResult<void>[]>;
|
|
2955
3386
|
/**
|
|
2956
3387
|
* Run media:beforeUpload hooks across all active plugins
|
|
2957
3388
|
*/
|
|
@@ -3108,12 +3539,6 @@ declare class NoopSandboxRunner implements SandboxRunner {
|
|
|
3108
3539
|
*/
|
|
3109
3540
|
declare function createNoopSandboxRunner(_options?: SandboxOptions): SandboxRunner;
|
|
3110
3541
|
//#endregion
|
|
3111
|
-
//#region src/plugins/sandbox/runtime-options.d.ts
|
|
3112
|
-
interface SandboxRunnerRuntimeOptions extends SandboxOptions {
|
|
3113
|
-
mediaStorage?: Storage;
|
|
3114
|
-
cronReschedule?: () => void;
|
|
3115
|
-
}
|
|
3116
|
-
//#endregion
|
|
3117
3542
|
//#region src/plugins/sandbox/node.d.ts
|
|
3118
3543
|
declare class NodeSandboxRunner implements SandboxRunner {
|
|
3119
3544
|
private readonly options;
|
|
@@ -3457,6 +3882,8 @@ interface GetCommentsOptions {
|
|
|
3457
3882
|
collection: string;
|
|
3458
3883
|
contentId: string;
|
|
3459
3884
|
threaded?: boolean;
|
|
3885
|
+
reactions?: boolean;
|
|
3886
|
+
sort?: "oldest" | "best";
|
|
3460
3887
|
}
|
|
3461
3888
|
interface GetCommentsResult {
|
|
3462
3889
|
items: PublicComment[];
|
|
@@ -3915,6 +4342,8 @@ interface Suggestion {
|
|
|
3915
4342
|
collection: string;
|
|
3916
4343
|
/** Entry ID */
|
|
3917
4344
|
id: string;
|
|
4345
|
+
/** Entry slug, when available */
|
|
4346
|
+
slug?: string | null;
|
|
3918
4347
|
/** Entry title */
|
|
3919
4348
|
title: string;
|
|
3920
4349
|
}
|
|
@@ -4262,6 +4691,13 @@ interface PluginDescriptor<TOptions = Record<string, unknown>> {
|
|
|
4262
4691
|
adminPages?: PluginAdminPage[];
|
|
4263
4692
|
/** Dashboard widgets */
|
|
4264
4693
|
adminWidgets?: PluginDashboardWidget[];
|
|
4694
|
+
/**
|
|
4695
|
+
* Portable Text block types this plugin contributes to the editor.
|
|
4696
|
+
* Declarative Block Kit config consumed from the admin manifest.
|
|
4697
|
+
*/
|
|
4698
|
+
portableTextBlocks?: PortableTextBlockConfig[];
|
|
4699
|
+
/** Field widget types this plugin contributes for schema-field editing UIs. */
|
|
4700
|
+
fieldWidgets?: FieldWidgetConfig[];
|
|
4265
4701
|
/**
|
|
4266
4702
|
* Capabilities the plugin requests.
|
|
4267
4703
|
* For standard-format plugins, capabilities are enforced in both trusted and
|
|
@@ -4317,6 +4753,33 @@ interface DinewayConfig {
|
|
|
4317
4753
|
* Storage configuration (for media)
|
|
4318
4754
|
*/
|
|
4319
4755
|
storage?: StorageDescriptor;
|
|
4756
|
+
/**
|
|
4757
|
+
* Optional object cache for public query results.
|
|
4758
|
+
*
|
|
4759
|
+
* This cache is disabled by default. When configured, it sits beneath
|
|
4760
|
+
* request-scoped caching and above the database for anonymous, non-preview,
|
|
4761
|
+
* non-edit reads. Preview, visual editing, and isolated playground databases
|
|
4762
|
+
* bypass it so editors always see live data.
|
|
4763
|
+
*
|
|
4764
|
+
* @example
|
|
4765
|
+
* ```ts
|
|
4766
|
+
* import { memoryCache } from "dineway/astro";
|
|
4767
|
+
*
|
|
4768
|
+
* dineway({
|
|
4769
|
+
* objectCache: memoryCache({ defaultTtl: 600 }),
|
|
4770
|
+
* })
|
|
4771
|
+
* ```
|
|
4772
|
+
*/
|
|
4773
|
+
objectCache?: ObjectCacheDescriptor;
|
|
4774
|
+
/**
|
|
4775
|
+
* Image optimization.
|
|
4776
|
+
*
|
|
4777
|
+
* By default Dineway wraps Astro's image endpoint so storage-backed media can
|
|
4778
|
+
* be optimized through the normal `<Image>` / `getImage` pipeline while
|
|
4779
|
+
* loading source bytes directly from the storage adapter. Set to `false` to
|
|
4780
|
+
* leave Astro's image endpoint untouched.
|
|
4781
|
+
*/
|
|
4782
|
+
images?: boolean;
|
|
4320
4783
|
/**
|
|
4321
4784
|
* Trusted plugins to load (run in main isolate)
|
|
4322
4785
|
*
|
|
@@ -4615,4 +5078,4 @@ declare global {
|
|
|
4615
5078
|
var __dinewayConfig: DinewayConfig | undefined;
|
|
4616
5079
|
}
|
|
4617
5080
|
//#endregion
|
|
4618
|
-
export { CreateMenuItemInput as $,
|
|
5081
|
+
export { CreateMenuItemInput as $, EntryData as $i, createEditable as $n, SandboxedPluginEntry as $r, FileSessionDatabaseFactory as $t, UpdateWidgetInput as A, handleContentTranslations as Ai, invalidateTaxonomyObjectCache as An, getSection as Ar, GeneratePreviewTokenOptions as At, getTerm as B, ImageValue as Bi, EntryResult as Bn, MediaListResponse as Br, SandboxNotAvailableError as Bt, getWidgetArea as C, handleContentGetIncludingTrashed as Ci, contentNamespaces as Cn, PortableTextMarkDef as Cr, renderPreviewLoadingPage as Ct, CreateWidgetInput as D, handleContentPublish as Di, invalidateMenuObjectCache as Dn, ProseMirrorDocument as Dr, GetPreviewUrlOptions as Dt, CreateWidgetAreaInput as E, handleContentPermanentDelete as Ei, invalidateCommentObjectCache as En, PortableTextUnknownBlock as Er, isPreviewRequest as Et, getEntriesByTerm as F, reference as Fi, CollectionFilter as Fn, SectionSource as Fr, parseContentId as Ft, TaxonomyTermRow as G, RelationRepository as Gi, getDinewayCollection as Gn, handleMediaList as Gr, PluginSecretStatus as Gt, CreateTermInput as H, ContentReference as Hi, ResolvePathResult as Hn, handleMediaCreate as Hr, PluginManager as Ht, getEntryTerms as I, image as Ii, CollectionResult as In, UpdateSectionInput as Ir, verifyPreviewToken as It, getBylineBySlug as J, CreateMediaInput as Ji, getTranslations as Jn, RevisionResponse as Jr, ValidatedPluginManifest as Jt, UpdateTermInput as K, UpdateRelationInput as Ki, getDinewayEntry as Kn, handleMediaUpdate as Kr, PluginSecretStore as Kt, getTaxonomyDef as L, FieldDefinition as Li, ContentEntry as Ln, getCollectionInfo as Lr, NodeSandboxRunner as Lt, WidgetArea as M, handleContentUnschedule as Mi, AfterCallback as Mn, CreateSectionInput as Mr, VerifyPreviewTokenOptions as Mt, WidgetComponentDef as N, handleContentUpdate as Ni, after as Nn, GetSectionsOptions as Nr, VerifyPreviewTokenResult as Nt, PropDef as O, handleContentRestore as Oi, invalidateObjectCache as On, ProseMirrorMark as Or, buildPreviewUrl as Ot, WidgetType as P, portableText as Pi, CacheHint as Pn, Section as Pr, generatePreviewToken as Pt, CreateMenuInput as Q, CollectionFilter$1 as Qi, FieldAnnotation as Qn, generateManifest as Qr, createFilePreviewMiddleware as Qt, getTaxonomyDefs as R, FieldUIHints as Ri, DinewayCollections as Rn, SchemaError as Rr, createNodeSandboxRunner as Rt, Suggestion as S, handleContentGet as Si, contentNamespace as Sn, PortableTextLinkMark as Sr, Snapshot as St, getWidgetComponents as T, handleContentListTrashed as Ti, invalidateCollectionCache as Tn, PortableTextTextBlock as Tr, getPreviewToken as Tt, TaxonomyDef as U, CreateRelationInput as Ui, TranslationSummary as Un, handleMediaDelete as Ur, createPluginManager as Ut, getTermsForEntries as V, PortableTextBlock$1 as Vi, InferCollectionData as Vn, MediaResponse as Vr, createNoopSandboxRunner as Vt, TaxonomyTerm as W, Relation as Wi, TranslationsResult as Wn, handleMediaGet as Wr, createReviewedPluginMcpCommandExecutor as Wt, getMenu as X, MediaRepository as Xi, CMSAnnotation as Xn, handleRevisionList as Xr, definePlugin as Xt, getEntriesByByline as Y, MediaItem as Yi, resolveDinewayPath as Yn, handleRevisionGet as Yr, pluginManifestSchema as Yt, getMenus as Z, ContentRepository as Zi, EditProxy as Zn, handleRevisionRestore as Zr, FilePreviewMiddlewareConfig as Zt, SearchOptions as _, ContentResponse as _a, handleContentCountTrashed as _i, getI18nConfig as _n, portableTextToProsemirror as _r, AppliedSnapshotMeta as _t, S3StorageConfig as a, DatabaseConfig as aa, SandboxRunnerFactory as ai, SessionDatabaseLimitError as an, IssuedGuestAccessToken as ar, UpdateMenuItemInput as at, SearchStats as b, ManifestResponse as ba, handleContentDiscardDraft as bi, CachedQueryOptions as bn, PortableTextHtmlBlock as br, dropSessionDatabaseTables as bt, extractSearchableFields as c, ParseResult as ca, PluginMcpRegistry as ci, PreviewSidecarClient as cn, hashGuestAccessToken as cr, getCommentCount as ct, search as d, parseQuery as da, HookResult as di, defaultPreviewSidecarClient as dn, RateLimitResult as dr, getPluginSettings as dt, EntryFilter as ea, PluginRouteError as ei, FileSessionDatabaseFactoryOptions as en, createNoop as er, Menu as et, searchCollection as f, apiError as fa, createHookPipeline as fi, parsePreviewSignatureHeader as fn, checkRateLimit as fr, getSiteSetting as ft, SearchConfig as g, ContentListResponse as ga, handleContentCountScheduled as gi, getFallbackChain as gn, hashString as gr, renderPreviewToolbar as gt, CollectionSearchOptions as h, ApiContext as ha, handleContentCompare as hi, I18nConfig as hn, computeContentHash as hr, PreviewToolbarConfig as ht, LocalStorageConfig as i, getDb as ia, SandboxRunner as ii, SessionDatabaseInfo as in, IssueGuestAccessTokenOptions as ir, UpdateMenuInput as it, Widget as j, handleContentUnpublish as ji, isObjectCacheActive as jn, getSections as jr, PreviewTokenPayload as jt, ReorderWidgetsInput as k, handleContentSchedule as ki, invalidateSchemaObjectCache as kn, ProseMirrorNode as kr, getPreviewUrl as kt, getSearchStats as l, isParseError as la, PluginMcpTargetAuthorizer as li, PreviewSidecarSignature as ln, issueGuestAccessToken as lr, getComments as lt, FTSManager as m, handleError as ma, handleContentAuthors as mi, verifyPreviewSignature as mn, sanitizeHref as mr, setSiteSettings as mt, PluginDescriptor as n, WhereValue as na, SandboxEmailSendCallback as ni, SessionDatabaseFactory as nn, GuestAccessTokenClaims as nr, MenuItemType as nt, StorageDescriptor as o, DinewayDatabaseError as oa, SandboxedPlugin as oi, SessionOpenOptions as on, VerifyGuestAccessTokenOptions as or, GetCommentsOptions as ot, searchWithDb as p, apiSuccess as pa, EmailPipeline as pi, signPreviewUrl as pn, isSafeHref as pr, getSiteSettings as pt, getByline as q, PublicComment as qi, getEditMeta as qn, RevisionListResponse as qr, PluginSecretStoreOptions as qt, getStoredConfig as r, dinewayLoader as ra, SandboxOptions as ri, SessionDatabaseHandle as rn, GuestAccessTokenConfigurationError as rr, ReorderMenuItemsInput as rt, extractPlainText as s, OptionsRepository as sa, SerializedRequest as si, SessionOpenOrCreateOptions as sn, VerifyGuestAccessTokenResult as sr, GetCommentsResult as st, DinewayConfig as t, WhereRange as ta, SandboxEmailMessage as ti, SessionCleanupResult as tn, GuestAccessExpectedScope as tr, MenuItem as tt, getSuggestions as u, parseBody as ua, HookPipeline as ui, buildPreviewSignatureHeader as un, verifyGuestAccessToken as ur, getPluginSetting as ut, SearchResponse as v, FieldDescriptor as va, handleContentCreate as vi, isI18nEnabled as vn, prosemirrorToPortableText as vr, ApplySnapshotToDatabaseOptions as vt, getWidgetAreas as w, handleContentList as wi, invalidateBylineObjectCache as wn, PortableTextSpan as wr, isBlockedInPreview as wt, SuggestOptions as x, handleContentDuplicate as xi, cachedQuery as xn, PortableTextImageBlock as xr, getAppliedSnapshotMeta as xt, SearchResult as y, ListResponse as ya, handleContentDelete as yi, CacheNamespace as yn, PortableTextCodeBlock as yr, applySnapshotToDatabase as yt, getTaxonomyTerms as z, FileValue as zi, EditFieldMeta as zn, SchemaRegistry as zr, NoopSandboxRunner as zt };
|