@krantho/api 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/dist/active-locales.d.ts +11 -0
- package/dist/active-locales.d.ts.map +1 -0
- package/dist/active-locales.js +31 -0
- package/dist/active-locales.js.map +1 -0
- package/dist/assistant/access.d.ts +25 -0
- package/dist/assistant/access.d.ts.map +1 -0
- package/dist/assistant/access.js +35 -0
- package/dist/assistant/access.js.map +1 -0
- package/dist/assistant/agent-loop.d.ts +31 -0
- package/dist/assistant/agent-loop.d.ts.map +1 -0
- package/dist/assistant/agent-loop.js +183 -0
- package/dist/assistant/agent-loop.js.map +1 -0
- package/dist/assistant/call-handler.d.ts +15 -0
- package/dist/assistant/call-handler.d.ts.map +1 -0
- package/dist/assistant/call-handler.js +24 -0
- package/dist/assistant/call-handler.js.map +1 -0
- package/dist/assistant/chat-handler.d.ts +8 -0
- package/dist/assistant/chat-handler.d.ts.map +1 -0
- package/dist/assistant/chat-handler.js +79 -0
- package/dist/assistant/chat-handler.js.map +1 -0
- package/dist/assistant/chat-request.d.ts +16 -0
- package/dist/assistant/chat-request.d.ts.map +1 -0
- package/dist/assistant/chat-request.js +59 -0
- package/dist/assistant/chat-request.js.map +1 -0
- package/dist/assistant/confirm-handler.d.ts +3 -0
- package/dist/assistant/confirm-handler.d.ts.map +1 -0
- package/dist/assistant/confirm-handler.js +39 -0
- package/dist/assistant/confirm-handler.js.map +1 -0
- package/dist/assistant/document-change.d.ts +22 -0
- package/dist/assistant/document-change.d.ts.map +1 -0
- package/dist/assistant/document-change.js +74 -0
- package/dist/assistant/document-change.js.map +1 -0
- package/dist/assistant/document-lock.d.ts +12 -0
- package/dist/assistant/document-lock.d.ts.map +1 -0
- package/dist/assistant/document-lock.js +14 -0
- package/dist/assistant/document-lock.js.map +1 -0
- package/dist/assistant/execute-action.d.ts +19 -0
- package/dist/assistant/execute-action.d.ts.map +1 -0
- package/dist/assistant/execute-action.js +167 -0
- package/dist/assistant/execute-action.js.map +1 -0
- package/dist/assistant/pending-action.d.ts +86 -0
- package/dist/assistant/pending-action.d.ts.map +1 -0
- package/dist/assistant/pending-action.js +104 -0
- package/dist/assistant/pending-action.js.map +1 -0
- package/dist/assistant/protocol.d.ts +120 -0
- package/dist/assistant/protocol.d.ts.map +1 -0
- package/dist/assistant/protocol.js +2 -0
- package/dist/assistant/protocol.js.map +1 -0
- package/dist/assistant/routes.d.ts +4 -0
- package/dist/assistant/routes.d.ts.map +1 -0
- package/dist/assistant/routes.js +10 -0
- package/dist/assistant/routes.js.map +1 -0
- package/dist/assistant/sse-stream.d.ts +15 -0
- package/dist/assistant/sse-stream.d.ts.map +1 -0
- package/dist/assistant/sse-stream.js +61 -0
- package/dist/assistant/sse-stream.js.map +1 -0
- package/dist/assistant/status-handler.d.ts +8 -0
- package/dist/assistant/status-handler.d.ts.map +1 -0
- package/dist/assistant/status-handler.js +39 -0
- package/dist/assistant/status-handler.js.map +1 -0
- package/dist/assistant/system-prompt.d.ts +18 -0
- package/dist/assistant/system-prompt.d.ts.map +1 -0
- package/dist/assistant/system-prompt.js +48 -0
- package/dist/assistant/system-prompt.js.map +1 -0
- package/dist/assistant/tool-registry.d.ts +19 -0
- package/dist/assistant/tool-registry.d.ts.map +1 -0
- package/dist/assistant/tool-registry.js +69 -0
- package/dist/assistant/tool-registry.js.map +1 -0
- package/dist/assistant/tools/action-tools.d.ts +4 -0
- package/dist/assistant/tools/action-tools.d.ts.map +1 -0
- package/dist/assistant/tools/action-tools.js +132 -0
- package/dist/assistant/tools/action-tools.js.map +1 -0
- package/dist/assistant/tools/aeo-tools.d.ts +4 -0
- package/dist/assistant/tools/aeo-tools.d.ts.map +1 -0
- package/dist/assistant/tools/aeo-tools.js +162 -0
- package/dist/assistant/tools/aeo-tools.js.map +1 -0
- package/dist/assistant/tools/define-tool.d.ts +55 -0
- package/dist/assistant/tools/define-tool.d.ts.map +1 -0
- package/dist/assistant/tools/define-tool.js +5 -0
- package/dist/assistant/tools/define-tool.js.map +1 -0
- package/dist/assistant/tools/draft-tools.d.ts +7 -0
- package/dist/assistant/tools/draft-tools.d.ts.map +1 -0
- package/dist/assistant/tools/draft-tools.js +105 -0
- package/dist/assistant/tools/draft-tools.js.map +1 -0
- package/dist/assistant/tools/draft-write.d.ts +49 -0
- package/dist/assistant/tools/draft-write.d.ts.map +1 -0
- package/dist/assistant/tools/draft-write.js +122 -0
- package/dist/assistant/tools/draft-write.js.map +1 -0
- package/dist/assistant/tools/faq-fit.d.ts +32 -0
- package/dist/assistant/tools/faq-fit.d.ts.map +1 -0
- package/dist/assistant/tools/faq-fit.js +96 -0
- package/dist/assistant/tools/faq-fit.js.map +1 -0
- package/dist/assistant/tools/read-tools.d.ts +13 -0
- package/dist/assistant/tools/read-tools.d.ts.map +1 -0
- package/dist/assistant/tools/read-tools.js +242 -0
- package/dist/assistant/tools/read-tools.js.map +1 -0
- package/dist/assistant/tools/seo-tools.d.ts +4 -0
- package/dist/assistant/tools/seo-tools.d.ts.map +1 -0
- package/dist/assistant/tools/seo-tools.js +152 -0
- package/dist/assistant/tools/seo-tools.js.map +1 -0
- package/dist/assistant/tools/support.d.ts +35 -0
- package/dist/assistant/tools/support.d.ts.map +1 -0
- package/dist/assistant/tools/support.js +63 -0
- package/dist/assistant/tools/support.js.map +1 -0
- package/dist/assistant/untrusted.d.ts +15 -0
- package/dist/assistant/untrusted.d.ts.map +1 -0
- package/dist/assistant/untrusted.js +27 -0
- package/dist/assistant/untrusted.js.map +1 -0
- package/dist/assistant/write-policy.d.ts +20 -0
- package/dist/assistant/write-policy.d.ts.map +1 -0
- package/dist/assistant/write-policy.js +32 -0
- package/dist/assistant/write-policy.js.map +1 -0
- package/dist/auth-tokens.d.ts +31 -0
- package/dist/auth-tokens.d.ts.map +1 -0
- package/dist/auth-tokens.js +35 -0
- package/dist/auth-tokens.js.map +1 -0
- package/dist/content-change.d.ts +16 -0
- package/dist/content-change.d.ts.map +1 -0
- package/dist/content-change.js +34 -0
- package/dist/content-change.js.map +1 -0
- package/dist/content-locks.d.ts +27 -0
- package/dist/content-locks.d.ts.map +1 -0
- package/dist/content-locks.js +40 -0
- package/dist/content-locks.js.map +1 -0
- package/dist/cookies.d.ts +19 -0
- package/dist/cookies.d.ts.map +1 -0
- package/dist/cookies.js +52 -0
- package/dist/cookies.js.map +1 -0
- package/dist/create-api-handlers.d.ts +128 -0
- package/dist/create-api-handlers.d.ts.map +1 -0
- package/dist/create-api-handlers.js +384 -0
- package/dist/create-api-handlers.js.map +1 -0
- package/dist/document-actions.d.ts +25 -0
- package/dist/document-actions.d.ts.map +1 -0
- package/dist/document-actions.js +157 -0
- package/dist/document-actions.js.map +1 -0
- package/dist/document-seo.d.ts +15 -0
- package/dist/document-seo.d.ts.map +1 -0
- package/dist/document-seo.js +41 -0
- package/dist/document-seo.js.map +1 -0
- package/dist/group-by-collection.d.ts +6 -0
- package/dist/group-by-collection.d.ts.map +1 -0
- package/dist/group-by-collection.js +11 -0
- package/dist/group-by-collection.js.map +1 -0
- package/dist/handlers/apply-metadata-defaults.d.ts +4 -0
- package/dist/handlers/apply-metadata-defaults.d.ts.map +1 -0
- package/dist/handlers/apply-metadata-defaults.js +108 -0
- package/dist/handlers/apply-metadata-defaults.js.map +1 -0
- package/dist/handlers/auth-callback.d.ts +4 -0
- package/dist/handlers/auth-callback.d.ts.map +1 -0
- package/dist/handlers/auth-callback.js +217 -0
- package/dist/handlers/auth-callback.js.map +1 -0
- package/dist/handlers/auth-capabilities.d.ts +4 -0
- package/dist/handlers/auth-capabilities.d.ts.map +1 -0
- package/dist/handlers/auth-capabilities.js +19 -0
- package/dist/handlers/auth-capabilities.js.map +1 -0
- package/dist/handlers/auth-login.d.ts +4 -0
- package/dist/handlers/auth-login.d.ts.map +1 -0
- package/dist/handlers/auth-login.js +60 -0
- package/dist/handlers/auth-login.js.map +1 -0
- package/dist/handlers/auth-logout.d.ts +4 -0
- package/dist/handlers/auth-logout.d.ts.map +1 -0
- package/dist/handlers/auth-logout.js +40 -0
- package/dist/handlers/auth-logout.js.map +1 -0
- package/dist/handlers/auth-me.d.ts +4 -0
- package/dist/handlers/auth-me.d.ts.map +1 -0
- package/dist/handlers/auth-me.js +54 -0
- package/dist/handlers/auth-me.js.map +1 -0
- package/dist/handlers/auth-oidc-login.d.ts +4 -0
- package/dist/handlers/auth-oidc-login.d.ts.map +1 -0
- package/dist/handlers/auth-oidc-login.js +51 -0
- package/dist/handlers/auth-oidc-login.js.map +1 -0
- package/dist/handlers/auth-refresh.d.ts +15 -0
- package/dist/handlers/auth-refresh.d.ts.map +1 -0
- package/dist/handlers/auth-refresh.js +82 -0
- package/dist/handlers/auth-refresh.js.map +1 -0
- package/dist/handlers/bulk-delete.d.ts +8 -0
- package/dist/handlers/bulk-delete.d.ts.map +1 -0
- package/dist/handlers/bulk-delete.js +72 -0
- package/dist/handlers/bulk-delete.js.map +1 -0
- package/dist/handlers/bulk-publish.d.ts +8 -0
- package/dist/handlers/bulk-publish.d.ts.map +1 -0
- package/dist/handlers/bulk-publish.js +48 -0
- package/dist/handlers/bulk-publish.js.map +1 -0
- package/dist/handlers/capabilities.d.ts +4 -0
- package/dist/handlers/capabilities.d.ts.map +1 -0
- package/dist/handlers/capabilities.js +44 -0
- package/dist/handlers/capabilities.js.map +1 -0
- package/dist/handlers/content-changes.d.ts +28 -0
- package/dist/handlers/content-changes.d.ts.map +1 -0
- package/dist/handlers/content-changes.js +160 -0
- package/dist/handlers/content-changes.js.map +1 -0
- package/dist/handlers/content-lock.d.ts +13 -0
- package/dist/handlers/content-lock.d.ts.map +1 -0
- package/dist/handlers/content-lock.js +109 -0
- package/dist/handlers/content-lock.js.map +1 -0
- package/dist/handlers/content-tree.d.ts +11 -0
- package/dist/handlers/content-tree.d.ts.map +1 -0
- package/dist/handlers/content-tree.js +28 -0
- package/dist/handlers/content-tree.js.map +1 -0
- package/dist/handlers/create-content.d.ts +4 -0
- package/dist/handlers/create-content.d.ts.map +1 -0
- package/dist/handlers/create-content.js +49 -0
- package/dist/handlers/create-content.js.map +1 -0
- package/dist/handlers/delete-content.d.ts +4 -0
- package/dist/handlers/delete-content.d.ts.map +1 -0
- package/dist/handlers/delete-content.js +17 -0
- package/dist/handlers/delete-content.js.map +1 -0
- package/dist/handlers/delete-runtime-field.d.ts +4 -0
- package/dist/handlers/delete-runtime-field.d.ts.map +1 -0
- package/dist/handlers/delete-runtime-field.js +43 -0
- package/dist/handlers/delete-runtime-field.js.map +1 -0
- package/dist/handlers/export-bundle.d.ts +13 -0
- package/dist/handlers/export-bundle.d.ts.map +1 -0
- package/dist/handlers/export-bundle.js +99 -0
- package/dist/handlers/export-bundle.js.map +1 -0
- package/dist/handlers/export-content.d.ts +7 -0
- package/dist/handlers/export-content.d.ts.map +1 -0
- package/dist/handlers/export-content.js +69 -0
- package/dist/handlers/export-content.js.map +1 -0
- package/dist/handlers/export-schema.d.ts +4 -0
- package/dist/handlers/export-schema.d.ts.map +1 -0
- package/dist/handlers/export-schema.js +13 -0
- package/dist/handlers/export-schema.js.map +1 -0
- package/dist/handlers/get-content.d.ts +4 -0
- package/dist/handlers/get-content.d.ts.map +1 -0
- package/dist/handlers/get-content.js +65 -0
- package/dist/handlers/get-content.js.map +1 -0
- package/dist/handlers/get-runtime-schema.d.ts +4 -0
- package/dist/handlers/get-runtime-schema.d.ts.map +1 -0
- package/dist/handlers/get-runtime-schema.js +17 -0
- package/dist/handlers/get-runtime-schema.js.map +1 -0
- package/dist/handlers/get-schema.d.ts +4 -0
- package/dist/handlers/get-schema.d.ts.map +1 -0
- package/dist/handlers/get-schema.js +87 -0
- package/dist/handlers/get-schema.js.map +1 -0
- package/dist/handlers/get-version.d.ts +4 -0
- package/dist/handlers/get-version.d.ts.map +1 -0
- package/dist/handlers/get-version.js +26 -0
- package/dist/handlers/get-version.js.map +1 -0
- package/dist/handlers/import-bundle.d.ts +4 -0
- package/dist/handlers/import-bundle.d.ts.map +1 -0
- package/dist/handlers/import-bundle.js +55 -0
- package/dist/handlers/import-bundle.js.map +1 -0
- package/dist/handlers/import-content.d.ts +4 -0
- package/dist/handlers/import-content.d.ts.map +1 -0
- package/dist/handlers/import-content.js +152 -0
- package/dist/handlers/import-content.js.map +1 -0
- package/dist/handlers/index.d.ts +87 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +87 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/list-collection.d.ts +8 -0
- package/dist/handlers/list-collection.d.ts.map +1 -0
- package/dist/handlers/list-collection.js +14 -0
- package/dist/handlers/list-collection.js.map +1 -0
- package/dist/handlers/list-collections.d.ts +4 -0
- package/dist/handlers/list-collections.d.ts.map +1 -0
- package/dist/handlers/list-collections.js +17 -0
- package/dist/handlers/list-collections.js.map +1 -0
- package/dist/handlers/list-content.d.ts +8 -0
- package/dist/handlers/list-content.d.ts.map +1 -0
- package/dist/handlers/list-content.js +22 -0
- package/dist/handlers/list-content.js.map +1 -0
- package/dist/handlers/list-query.d.ts +7 -0
- package/dist/handlers/list-query.d.ts.map +1 -0
- package/dist/handlers/list-query.js +36 -0
- package/dist/handlers/list-query.js.map +1 -0
- package/dist/handlers/list-versions.d.ts +4 -0
- package/dist/handlers/list-versions.d.ts.map +1 -0
- package/dist/handlers/list-versions.js +19 -0
- package/dist/handlers/list-versions.js.map +1 -0
- package/dist/handlers/llm-credential.d.ts +46 -0
- package/dist/handlers/llm-credential.d.ts.map +1 -0
- package/dist/handlers/llm-credential.js +68 -0
- package/dist/handlers/llm-credential.js.map +1 -0
- package/dist/handlers/llm-resolve.d.ts +45 -0
- package/dist/handlers/llm-resolve.d.ts.map +1 -0
- package/dist/handlers/llm-resolve.js +126 -0
- package/dist/handlers/llm-resolve.js.map +1 -0
- package/dist/handlers/llm-settings.d.ts +19 -0
- package/dist/handlers/llm-settings.d.ts.map +1 -0
- package/dist/handlers/llm-settings.js +209 -0
- package/dist/handlers/llm-settings.js.map +1 -0
- package/dist/handlers/media-bulk-delete.d.ts +4 -0
- package/dist/handlers/media-bulk-delete.d.ts.map +1 -0
- package/dist/handlers/media-bulk-delete.js +19 -0
- package/dist/handlers/media-bulk-delete.js.map +1 -0
- package/dist/handlers/media-bulk-update.d.ts +4 -0
- package/dist/handlers/media-bulk-update.d.ts.map +1 -0
- package/dist/handlers/media-bulk-update.js +25 -0
- package/dist/handlers/media-bulk-update.js.map +1 -0
- package/dist/handlers/media-delete.d.ts +4 -0
- package/dist/handlers/media-delete.d.ts.map +1 -0
- package/dist/handlers/media-delete.js +27 -0
- package/dist/handlers/media-delete.js.map +1 -0
- package/dist/handlers/media-duplicate.d.ts +4 -0
- package/dist/handlers/media-duplicate.d.ts.map +1 -0
- package/dist/handlers/media-duplicate.js +20 -0
- package/dist/handlers/media-duplicate.js.map +1 -0
- package/dist/handlers/media-folders.d.ts +12 -0
- package/dist/handlers/media-folders.d.ts.map +1 -0
- package/dist/handlers/media-folders.js +119 -0
- package/dist/handlers/media-folders.js.map +1 -0
- package/dist/handlers/media-get.d.ts +4 -0
- package/dist/handlers/media-get.d.ts.map +1 -0
- package/dist/handlers/media-get.js +16 -0
- package/dist/handlers/media-get.js.map +1 -0
- package/dist/handlers/media-image-info.d.ts +4 -0
- package/dist/handlers/media-image-info.d.ts.map +1 -0
- package/dist/handlers/media-image-info.js +32 -0
- package/dist/handlers/media-image-info.js.map +1 -0
- package/dist/handlers/media-image.d.ts +11 -0
- package/dist/handlers/media-image.d.ts.map +1 -0
- package/dist/handlers/media-image.js +116 -0
- package/dist/handlers/media-image.js.map +1 -0
- package/dist/handlers/media-info.d.ts +4 -0
- package/dist/handlers/media-info.d.ts.map +1 -0
- package/dist/handlers/media-info.js +18 -0
- package/dist/handlers/media-info.js.map +1 -0
- package/dist/handlers/media-list.d.ts +4 -0
- package/dist/handlers/media-list.d.ts.map +1 -0
- package/dist/handlers/media-list.js +14 -0
- package/dist/handlers/media-list.js.map +1 -0
- package/dist/handlers/media-register.d.ts +4 -0
- package/dist/handlers/media-register.d.ts.map +1 -0
- package/dist/handlers/media-register.js +57 -0
- package/dist/handlers/media-register.js.map +1 -0
- package/dist/handlers/media-replace.d.ts +9 -0
- package/dist/handlers/media-replace.d.ts.map +1 -0
- package/dist/handlers/media-replace.js +53 -0
- package/dist/handlers/media-replace.js.map +1 -0
- package/dist/handlers/media-tags.d.ts +4 -0
- package/dist/handlers/media-tags.d.ts.map +1 -0
- package/dist/handlers/media-tags.js +9 -0
- package/dist/handlers/media-tags.js.map +1 -0
- package/dist/handlers/media-update.d.ts +4 -0
- package/dist/handlers/media-update.d.ts.map +1 -0
- package/dist/handlers/media-update.js +64 -0
- package/dist/handlers/media-update.js.map +1 -0
- package/dist/handlers/media-upload.d.ts +4 -0
- package/dist/handlers/media-upload.d.ts.map +1 -0
- package/dist/handlers/media-upload.js +26 -0
- package/dist/handlers/media-upload.js.map +1 -0
- package/dist/handlers/media-usage.d.ts +9 -0
- package/dist/handlers/media-usage.d.ts.map +1 -0
- package/dist/handlers/media-usage.js +36 -0
- package/dist/handlers/media-usage.js.map +1 -0
- package/dist/handlers/migration-conflicts.d.ts +13 -0
- package/dist/handlers/migration-conflicts.d.ts.map +1 -0
- package/dist/handlers/migration-conflicts.js +55 -0
- package/dist/handlers/migration-conflicts.js.map +1 -0
- package/dist/handlers/migration-status.d.ts +4 -0
- package/dist/handlers/migration-status.d.ts.map +1 -0
- package/dist/handlers/migration-status.js +34 -0
- package/dist/handlers/migration-status.js.map +1 -0
- package/dist/handlers/publish-content.d.ts +9 -0
- package/dist/handlers/publish-content.d.ts.map +1 -0
- package/dist/handlers/publish-content.js +47 -0
- package/dist/handlers/publish-content.js.map +1 -0
- package/dist/handlers/publish-impact.d.ts +11 -0
- package/dist/handlers/publish-impact.d.ts.map +1 -0
- package/dist/handlers/publish-impact.js +44 -0
- package/dist/handlers/publish-impact.js.map +1 -0
- package/dist/handlers/resolve-page.d.ts +9 -0
- package/dist/handlers/resolve-page.d.ts.map +1 -0
- package/dist/handlers/resolve-page.js +105 -0
- package/dist/handlers/resolve-page.js.map +1 -0
- package/dist/handlers/restore-version.d.ts +4 -0
- package/dist/handlers/restore-version.d.ts.map +1 -0
- package/dist/handlers/restore-version.js +69 -0
- package/dist/handlers/restore-version.js.map +1 -0
- package/dist/handlers/runtime-metadata.d.ts +6 -0
- package/dist/handlers/runtime-metadata.d.ts.map +1 -0
- package/dist/handlers/runtime-metadata.js +82 -0
- package/dist/handlers/runtime-metadata.js.map +1 -0
- package/dist/handlers/save-runtime-field.d.ts +4 -0
- package/dist/handlers/save-runtime-field.d.ts.map +1 -0
- package/dist/handlers/save-runtime-field.js +108 -0
- package/dist/handlers/save-runtime-field.js.map +1 -0
- package/dist/handlers/search-content.d.ts +9 -0
- package/dist/handlers/search-content.d.ts.map +1 -0
- package/dist/handlers/search-content.js +40 -0
- package/dist/handlers/search-content.js.map +1 -0
- package/dist/handlers/seo-config.d.ts +16 -0
- package/dist/handlers/seo-config.d.ts.map +1 -0
- package/dist/handlers/seo-config.js +250 -0
- package/dist/handlers/seo-config.js.map +1 -0
- package/dist/handlers/seo-document.d.ts +24 -0
- package/dist/handlers/seo-document.d.ts.map +1 -0
- package/dist/handlers/seo-document.js +119 -0
- package/dist/handlers/seo-document.js.map +1 -0
- package/dist/handlers/seo-enrich-archetype.d.ts +71 -0
- package/dist/handlers/seo-enrich-archetype.d.ts.map +1 -0
- package/dist/handlers/seo-enrich-archetype.js +250 -0
- package/dist/handlers/seo-enrich-archetype.js.map +1 -0
- package/dist/handlers/seo-enrich-meta.d.ts +40 -0
- package/dist/handlers/seo-enrich-meta.d.ts.map +1 -0
- package/dist/handlers/seo-enrich-meta.js +121 -0
- package/dist/handlers/seo-enrich-meta.js.map +1 -0
- package/dist/handlers/seo-enrich-runner.d.ts +65 -0
- package/dist/handlers/seo-enrich-runner.d.ts.map +1 -0
- package/dist/handlers/seo-enrich-runner.js +192 -0
- package/dist/handlers/seo-enrich-runner.js.map +1 -0
- package/dist/handlers/seo-enrich.d.ts +10 -0
- package/dist/handlers/seo-enrich.d.ts.map +1 -0
- package/dist/handlers/seo-enrich.js +166 -0
- package/dist/handlers/seo-enrich.js.map +1 -0
- package/dist/handlers/seo-generate.d.ts +4 -0
- package/dist/handlers/seo-generate.d.ts.map +1 -0
- package/dist/handlers/seo-generate.js +31 -0
- package/dist/handlers/seo-generate.js.map +1 -0
- package/dist/handlers/seo-impact.d.ts +36 -0
- package/dist/handlers/seo-impact.d.ts.map +1 -0
- package/dist/handlers/seo-impact.js +137 -0
- package/dist/handlers/seo-impact.js.map +1 -0
- package/dist/handlers/seo-indexnow.d.ts +11 -0
- package/dist/handlers/seo-indexnow.d.ts.map +1 -0
- package/dist/handlers/seo-indexnow.js +15 -0
- package/dist/handlers/seo-indexnow.js.map +1 -0
- package/dist/handlers/seo-llms-txt.d.ts +26 -0
- package/dist/handlers/seo-llms-txt.d.ts.map +1 -0
- package/dist/handlers/seo-llms-txt.js +99 -0
- package/dist/handlers/seo-llms-txt.js.map +1 -0
- package/dist/handlers/seo-preview.d.ts +8 -0
- package/dist/handlers/seo-preview.d.ts.map +1 -0
- package/dist/handlers/seo-preview.js +49 -0
- package/dist/handlers/seo-preview.js.map +1 -0
- package/dist/handlers/seo-robots.d.ts +22 -0
- package/dist/handlers/seo-robots.d.ts.map +1 -0
- package/dist/handlers/seo-robots.js +48 -0
- package/dist/handlers/seo-robots.js.map +1 -0
- package/dist/handlers/seo-sitemap.d.ts +68 -0
- package/dist/handlers/seo-sitemap.d.ts.map +1 -0
- package/dist/handlers/seo-sitemap.js +178 -0
- package/dist/handlers/seo-sitemap.js.map +1 -0
- package/dist/handlers/seo-status.d.ts +4 -0
- package/dist/handlers/seo-status.d.ts.map +1 -0
- package/dist/handlers/seo-status.js +61 -0
- package/dist/handlers/seo-status.js.map +1 -0
- package/dist/handlers/seo-structured-data.d.ts +4 -0
- package/dist/handlers/seo-structured-data.d.ts.map +1 -0
- package/dist/handlers/seo-structured-data.js +18 -0
- package/dist/handlers/seo-structured-data.js.map +1 -0
- package/dist/handlers/site-config.d.ts +8 -0
- package/dist/handlers/site-config.d.ts.map +1 -0
- package/dist/handlers/site-config.js +26 -0
- package/dist/handlers/site-config.js.map +1 -0
- package/dist/handlers/site-preview.d.ts +10 -0
- package/dist/handlers/site-preview.d.ts.map +1 -0
- package/dist/handlers/site-preview.js +54 -0
- package/dist/handlers/site-preview.js.map +1 -0
- package/dist/handlers/site-settings.d.ts +17 -0
- package/dist/handlers/site-settings.d.ts.map +1 -0
- package/dist/handlers/site-settings.js +75 -0
- package/dist/handlers/site-settings.js.map +1 -0
- package/dist/handlers/snapshot-create.d.ts +4 -0
- package/dist/handlers/snapshot-create.d.ts.map +1 -0
- package/dist/handlers/snapshot-create.js +15 -0
- package/dist/handlers/snapshot-create.js.map +1 -0
- package/dist/handlers/snapshot-delete.d.ts +4 -0
- package/dist/handlers/snapshot-delete.d.ts.map +1 -0
- package/dist/handlers/snapshot-delete.js +21 -0
- package/dist/handlers/snapshot-delete.js.map +1 -0
- package/dist/handlers/snapshot-get.d.ts +4 -0
- package/dist/handlers/snapshot-get.d.ts.map +1 -0
- package/dist/handlers/snapshot-get.js +17 -0
- package/dist/handlers/snapshot-get.js.map +1 -0
- package/dist/handlers/snapshot-list.d.ts +4 -0
- package/dist/handlers/snapshot-list.d.ts.map +1 -0
- package/dist/handlers/snapshot-list.js +9 -0
- package/dist/handlers/snapshot-list.js.map +1 -0
- package/dist/handlers/snapshot-restore.d.ts +4 -0
- package/dist/handlers/snapshot-restore.d.ts.map +1 -0
- package/dist/handlers/snapshot-restore.js +27 -0
- package/dist/handlers/snapshot-restore.js.map +1 -0
- package/dist/handlers/translation-status.d.ts +9 -0
- package/dist/handlers/translation-status.d.ts.map +1 -0
- package/dist/handlers/translation-status.js +68 -0
- package/dist/handlers/translation-status.js.map +1 -0
- package/dist/handlers/update-content.d.ts +4 -0
- package/dist/handlers/update-content.d.ts.map +1 -0
- package/dist/handlers/update-content.js +66 -0
- package/dist/handlers/update-content.js.map +1 -0
- package/dist/handlers/user-create.d.ts +4 -0
- package/dist/handlers/user-create.d.ts.map +1 -0
- package/dist/handlers/user-create.js +38 -0
- package/dist/handlers/user-create.js.map +1 -0
- package/dist/handlers/user-delete.d.ts +4 -0
- package/dist/handlers/user-delete.d.ts.map +1 -0
- package/dist/handlers/user-delete.js +25 -0
- package/dist/handlers/user-delete.js.map +1 -0
- package/dist/handlers/user-get.d.ts +4 -0
- package/dist/handlers/user-get.d.ts.map +1 -0
- package/dist/handlers/user-get.js +22 -0
- package/dist/handlers/user-get.js.map +1 -0
- package/dist/handlers/user-list.d.ts +4 -0
- package/dist/handlers/user-list.d.ts.map +1 -0
- package/dist/handlers/user-list.js +28 -0
- package/dist/handlers/user-list.js.map +1 -0
- package/dist/handlers/user-permissions.d.ts +6 -0
- package/dist/handlers/user-permissions.d.ts.map +1 -0
- package/dist/handlers/user-permissions.js +42 -0
- package/dist/handlers/user-permissions.js.map +1 -0
- package/dist/handlers/user-update.d.ts +4 -0
- package/dist/handlers/user-update.d.ts.map +1 -0
- package/dist/handlers/user-update.js +54 -0
- package/dist/handlers/user-update.js.map +1 -0
- package/dist/handlers/validate-all.d.ts +4 -0
- package/dist/handlers/validate-all.d.ts.map +1 -0
- package/dist/handlers/validate-all.js +14 -0
- package/dist/handlers/validate-all.js.map +1 -0
- package/dist/handlers/version-retention.d.ts +6 -0
- package/dist/handlers/version-retention.d.ts.map +1 -0
- package/dist/handlers/version-retention.js +40 -0
- package/dist/handlers/version-retention.js.map +1 -0
- package/dist/handlers/webhook-deliveries.d.ts +4 -0
- package/dist/handlers/webhook-deliveries.d.ts.map +1 -0
- package/dist/handlers/webhook-deliveries.js +24 -0
- package/dist/handlers/webhook-deliveries.js.map +1 -0
- package/dist/handlers/webhook-retry.d.ts +11 -0
- package/dist/handlers/webhook-retry.d.ts.map +1 -0
- package/dist/handlers/webhook-retry.js +69 -0
- package/dist/handlers/webhook-retry.js.map +1 -0
- package/dist/head.d.ts +9 -0
- package/dist/head.d.ts.map +1 -0
- package/dist/head.js +28 -0
- package/dist/head.js.map +1 -0
- package/dist/hooks.d.ts +34 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +19 -0
- package/dist/hooks.js.map +1 -0
- package/dist/image-cache.d.ts +47 -0
- package/dist/image-cache.d.ts.map +1 -0
- package/dist/image-cache.js +112 -0
- package/dist/image-cache.js.map +1 -0
- package/dist/image-dimensions.d.ts +12 -0
- package/dist/image-dimensions.d.ts.map +1 -0
- package/dist/image-dimensions.js +129 -0
- package/dist/image-dimensions.js.map +1 -0
- package/dist/image-optimizer.d.ts +86 -0
- package/dist/image-optimizer.d.ts.map +1 -0
- package/dist/image-optimizer.js +206 -0
- package/dist/image-optimizer.js.map +1 -0
- package/dist/image-presets.d.ts +17 -0
- package/dist/image-presets.d.ts.map +1 -0
- package/dist/image-presets.js +50 -0
- package/dist/image-presets.js.map +1 -0
- package/dist/image-url.d.ts +26 -0
- package/dist/image-url.d.ts.map +1 -0
- package/dist/image-url.js +47 -0
- package/dist/image-url.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +54 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +114 -0
- package/dist/jwt.js.map +1 -0
- package/dist/locale-fallback.d.ts +18 -0
- package/dist/locale-fallback.d.ts.map +1 -0
- package/dist/locale-fallback.js +42 -0
- package/dist/locale-fallback.js.map +1 -0
- package/dist/media-library.d.ts +46 -0
- package/dist/media-library.d.ts.map +1 -0
- package/dist/media-library.js +231 -0
- package/dist/media-library.js.map +1 -0
- package/dist/media-reference-updater.d.ts +24 -0
- package/dist/media-reference-updater.d.ts.map +1 -0
- package/dist/media-reference-updater.js +124 -0
- package/dist/media-reference-updater.js.map +1 -0
- package/dist/media-references.d.ts +14 -0
- package/dist/media-references.d.ts.map +1 -0
- package/dist/media-references.js +25 -0
- package/dist/media-references.js.map +1 -0
- package/dist/merged-schema.d.ts +10 -0
- package/dist/merged-schema.d.ts.map +1 -0
- package/dist/merged-schema.js +21 -0
- package/dist/merged-schema.js.map +1 -0
- package/dist/middleware/auth.d.ts +21 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +82 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/oidc-state.d.ts +42 -0
- package/dist/oidc-state.d.ts.map +1 -0
- package/dist/oidc-state.js +72 -0
- package/dist/oidc-state.js.map +1 -0
- package/dist/oidc.d.ts +83 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/oidc.js +226 -0
- package/dist/oidc.js.map +1 -0
- package/dist/openapi.d.ts +13 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +133 -0
- package/dist/openapi.js.map +1 -0
- package/dist/permissions.d.ts +37 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +69 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugins.d.ts +64 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +73 -0
- package/dist/plugins.js.map +1 -0
- package/dist/preview-token.d.ts +13 -0
- package/dist/preview-token.d.ts.map +1 -0
- package/dist/preview-token.js +45 -0
- package/dist/preview-token.js.map +1 -0
- package/dist/public-cache.d.ts +8 -0
- package/dist/public-cache.d.ts.map +1 -0
- package/dist/public-cache.js +8 -0
- package/dist/public-cache.js.map +1 -0
- package/dist/reference-resolver.d.ts +21 -0
- package/dist/reference-resolver.d.ts.map +1 -0
- package/dist/reference-resolver.js +128 -0
- package/dist/reference-resolver.js.map +1 -0
- package/dist/return-to.d.ts +7 -0
- package/dist/return-to.d.ts.map +1 -0
- package/dist/return-to.js +15 -0
- package/dist/return-to.js.map +1 -0
- package/dist/router.d.ts +14 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +51 -0
- package/dist/router.js.map +1 -0
- package/dist/runtime-field-checks.d.ts +11 -0
- package/dist/runtime-field-checks.d.ts.map +1 -0
- package/dist/runtime-field-checks.js +72 -0
- package/dist/runtime-field-checks.js.map +1 -0
- package/dist/save-document.d.ts +71 -0
- package/dist/save-document.d.ts.map +1 -0
- package/dist/save-document.js +213 -0
- package/dist/save-document.js.map +1 -0
- package/dist/seo-compose.d.ts +50 -0
- package/dist/seo-compose.d.ts.map +1 -0
- package/dist/seo-compose.js +104 -0
- package/dist/seo-compose.js.map +1 -0
- package/dist/seo-config-snapshot.d.ts +10 -0
- package/dist/seo-config-snapshot.d.ts.map +1 -0
- package/dist/seo-config-snapshot.js +16 -0
- package/dist/seo-config-snapshot.js.map +1 -0
- package/dist/seo-loader.d.ts +10 -0
- package/dist/seo-loader.d.ts.map +1 -0
- package/dist/seo-loader.js +14 -0
- package/dist/seo-loader.js.map +1 -0
- package/dist/seo-site-findings.d.ts +27 -0
- package/dist/seo-site-findings.d.ts.map +1 -0
- package/dist/seo-site-findings.js +87 -0
- package/dist/seo-site-findings.js.map +1 -0
- package/dist/seo-subsystem.d.ts +28 -0
- package/dist/seo-subsystem.d.ts.map +1 -0
- package/dist/seo-subsystem.js +62 -0
- package/dist/seo-subsystem.js.map +1 -0
- package/dist/seo-validation.d.ts +20 -0
- package/dist/seo-validation.d.ts.map +1 -0
- package/dist/seo-validation.js +96 -0
- package/dist/seo-validation.js.map +1 -0
- package/dist/types.d.ts +126 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/validators.d.ts +107 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +199 -0
- package/dist/validators.js.map +1 -0
- package/dist/webhooks.d.ts +29 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +123 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/workload-identity.d.ts +23 -0
- package/dist/workload-identity.d.ts.map +1 -0
- package/dist/workload-identity.js +145 -0
- package/dist/workload-identity.js.map +1 -0
- package/package.json +50 -3
- package/README.md +0 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection impact analysis handler.
|
|
3
|
+
*
|
|
4
|
+
* Evaluates the impact of changing a collection's archetype by scanning
|
|
5
|
+
* all documents and identifying orphaned properties (currently set but
|
|
6
|
+
* unsupported under the new archetype) and missing required properties
|
|
7
|
+
* (required under the new archetype but not currently set).
|
|
8
|
+
*
|
|
9
|
+
* GET /api/seo/collection/:name/impact?archetype=preset-name
|
|
10
|
+
*/
|
|
11
|
+
import type { ApiHandler } from '../types.js';
|
|
12
|
+
export interface ImpactResponse {
|
|
13
|
+
archetype: string;
|
|
14
|
+
totalDocuments: number;
|
|
15
|
+
affectedDocuments: Array<{
|
|
16
|
+
slug: string;
|
|
17
|
+
title: string;
|
|
18
|
+
orphanedProperties: Array<{
|
|
19
|
+
entityType: string;
|
|
20
|
+
property: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
}>;
|
|
23
|
+
missingRequired: Array<{
|
|
24
|
+
entityType: string;
|
|
25
|
+
property: string;
|
|
26
|
+
}>;
|
|
27
|
+
}>;
|
|
28
|
+
summary: {
|
|
29
|
+
documentsWithOrphans: number;
|
|
30
|
+
documentsWithMissingRequired: number;
|
|
31
|
+
totalOrphanedProperties: number;
|
|
32
|
+
totalMissingRequired: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export declare const seoCollectionImpact: ApiHandler;
|
|
36
|
+
//# sourceMappingURL=seo-impact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-impact.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-impact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,KAAK,CAAC;QACvB,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,kBAAkB,EAAE,KAAK,CAAC;YACxB,UAAU,EAAE,MAAM,CAAA;YAClB,QAAQ,EAAE,MAAM,CAAA;YAChB,KAAK,EAAE,OAAO,CAAA;SACf,CAAC,CAAA;QACF,eAAe,EAAE,KAAK,CAAC;YACrB,UAAU,EAAE,MAAM,CAAA;YAClB,QAAQ,EAAE,MAAM,CAAA;SACjB,CAAC,CAAA;KACH,CAAC,CAAA;IACF,OAAO,EAAE;QACP,oBAAoB,EAAE,MAAM,CAAA;QAC5B,4BAA4B,EAAE,MAAM,CAAA;QACpC,uBAAuB,EAAE,MAAM,CAAA;QAC/B,oBAAoB,EAAE,MAAM,CAAA;KAC7B,CAAA;CACF;AAED,eAAO,MAAM,mBAAmB,EAAE,UA4IjC,CAAA"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection impact analysis handler.
|
|
3
|
+
*
|
|
4
|
+
* Evaluates the impact of changing a collection's archetype by scanning
|
|
5
|
+
* all documents and identifying orphaned properties (currently set but
|
|
6
|
+
* unsupported under the new archetype) and missing required properties
|
|
7
|
+
* (required under the new archetype but not currently set).
|
|
8
|
+
*
|
|
9
|
+
* GET /api/seo/collection/:name/impact?archetype=preset-name
|
|
10
|
+
*/
|
|
11
|
+
import { canQuery } from '@krantho/persistence';
|
|
12
|
+
import { requireRole } from '../permissions.js';
|
|
13
|
+
import { loadSeoModule } from '../seo-loader.js';
|
|
14
|
+
import { loadSeo } from '../seo-subsystem.js';
|
|
15
|
+
export const seoCollectionImpact = async (req, ctx) => {
|
|
16
|
+
const denied = requireRole(ctx.auth, 'admin');
|
|
17
|
+
if (denied)
|
|
18
|
+
return denied;
|
|
19
|
+
if (!ctx.seoConfigAdapter) {
|
|
20
|
+
return { status: 501, body: { error: 'SEO configuration not available' } };
|
|
21
|
+
}
|
|
22
|
+
const collectionName = req.params['name'];
|
|
23
|
+
if (!collectionName) {
|
|
24
|
+
return { status: 400, body: { error: 'Collection name required' } };
|
|
25
|
+
}
|
|
26
|
+
const archetypeName = req.query['archetype'];
|
|
27
|
+
if (!archetypeName) {
|
|
28
|
+
return { status: 400, body: { error: 'Archetype query parameter required' } };
|
|
29
|
+
}
|
|
30
|
+
// Dynamically import to avoid bundling @krantho/seo in the API
|
|
31
|
+
const seo = await loadSeoModule();
|
|
32
|
+
const { readers } = await loadSeo(ctx.config);
|
|
33
|
+
// Build the set of entity types in the proposed archetype
|
|
34
|
+
// For now, accept a comma-separated list of types as the archetype parameter
|
|
35
|
+
const proposedTypes = archetypeName
|
|
36
|
+
.split(',')
|
|
37
|
+
.map((t) => t.trim())
|
|
38
|
+
.filter(Boolean);
|
|
39
|
+
if (proposedTypes.length === 0) {
|
|
40
|
+
return { status: 400, body: { error: 'No types specified in archetype' } };
|
|
41
|
+
}
|
|
42
|
+
const proposedTypeSet = new Set(proposedTypes);
|
|
43
|
+
// The properties any active reader's rule for each type requires
|
|
44
|
+
const requiredByType = new Map();
|
|
45
|
+
for (const type of proposedTypes) {
|
|
46
|
+
const required = new Set();
|
|
47
|
+
for (const id of readers) {
|
|
48
|
+
const profile = seo.getProfile(id);
|
|
49
|
+
const rule = profile ? seo.ruleFor(profile, type) : undefined;
|
|
50
|
+
if (rule?.status === 'active' || rule?.status === 'restricted') {
|
|
51
|
+
for (const property of rule.required ?? [])
|
|
52
|
+
required.add(property);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (required.size > 0)
|
|
56
|
+
requiredByType.set(type, [...required]);
|
|
57
|
+
}
|
|
58
|
+
// List all documents in the collection
|
|
59
|
+
if (!canQuery(ctx.adapter)) {
|
|
60
|
+
return { status: 501, body: { error: 'Collection listing not available' } };
|
|
61
|
+
}
|
|
62
|
+
const { items: documents } = await ctx.adapter.query({
|
|
63
|
+
state: 'current',
|
|
64
|
+
status: 'published',
|
|
65
|
+
projection: 'summary',
|
|
66
|
+
collections: [collectionName],
|
|
67
|
+
});
|
|
68
|
+
// Batch-load all document SEO configs for this collection in a single query
|
|
69
|
+
const docConfigs = await ctx.seoConfigAdapter.listConfigsByPrefix(`doc:${collectionName}/`);
|
|
70
|
+
const configBySlug = new Map();
|
|
71
|
+
for (const config of docConfigs) {
|
|
72
|
+
// Extract slug from config id: "doc:pages/home" → "home"
|
|
73
|
+
const slug = config.id.slice(`doc:${collectionName}/`.length);
|
|
74
|
+
configBySlug.set(slug, config);
|
|
75
|
+
}
|
|
76
|
+
const affectedDocuments = [];
|
|
77
|
+
for (const doc of documents) {
|
|
78
|
+
const docConfig = configBySlug.get(doc.meta.slug);
|
|
79
|
+
if (!docConfig)
|
|
80
|
+
continue;
|
|
81
|
+
const orphanedProperties = [];
|
|
82
|
+
const missingRequired = [];
|
|
83
|
+
// Find orphaned properties: properties on entities whose @type is not in the proposed archetype
|
|
84
|
+
for (const entity of docConfig.config.entities) {
|
|
85
|
+
if (!proposedTypeSet.has(entity['@type'])) {
|
|
86
|
+
// Entire entity is orphaned — list all its populated properties
|
|
87
|
+
for (const [prop, val] of Object.entries(entity.properties)) {
|
|
88
|
+
if (val !== undefined && val !== null && val !== '') {
|
|
89
|
+
orphanedProperties.push({
|
|
90
|
+
entityType: entity['@type'],
|
|
91
|
+
property: prop,
|
|
92
|
+
value: val,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Find missing required: required properties under the proposed types that are not set
|
|
99
|
+
for (const type of proposedTypes) {
|
|
100
|
+
const required = requiredByType.get(type);
|
|
101
|
+
if (!required)
|
|
102
|
+
continue;
|
|
103
|
+
// Find matching entity in the doc's config
|
|
104
|
+
const docEntity = docConfig.config.entities.find((e) => e['@type'] === type);
|
|
105
|
+
for (const prop of required) {
|
|
106
|
+
const value = docEntity?.properties[prop];
|
|
107
|
+
if (value === undefined || value === null || value === '') {
|
|
108
|
+
missingRequired.push({ entityType: type, property: prop });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (orphanedProperties.length > 0 || missingRequired.length > 0) {
|
|
113
|
+
const title = typeof doc.fields['title'] === 'string' ? doc.fields['title'] : doc.meta.slug;
|
|
114
|
+
affectedDocuments.push({
|
|
115
|
+
slug: doc.meta.slug,
|
|
116
|
+
title,
|
|
117
|
+
orphanedProperties,
|
|
118
|
+
missingRequired,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const summary = {
|
|
123
|
+
documentsWithOrphans: affectedDocuments.filter((d) => d.orphanedProperties.length > 0).length,
|
|
124
|
+
documentsWithMissingRequired: affectedDocuments.filter((d) => d.missingRequired.length > 0)
|
|
125
|
+
.length,
|
|
126
|
+
totalOrphanedProperties: affectedDocuments.reduce((sum, d) => sum + d.orphanedProperties.length, 0),
|
|
127
|
+
totalMissingRequired: affectedDocuments.reduce((sum, d) => sum + d.missingRequired.length, 0),
|
|
128
|
+
};
|
|
129
|
+
const response = {
|
|
130
|
+
archetype: archetypeName,
|
|
131
|
+
totalDocuments: documents.length,
|
|
132
|
+
affectedDocuments,
|
|
133
|
+
summary,
|
|
134
|
+
};
|
|
135
|
+
return { status: 200, body: response };
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=seo-impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-impact.js","sourceRoot":"","sources":["../../src/handlers/seo-impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ApiHandler } from '../types.js';
|
|
2
|
+
/** The API path of the IndexNow key file; a site serves it at `/<key>.txt` */
|
|
3
|
+
export declare const SEO_INDEXNOW_KEY_PATH = "/api/seo/indexnow/:key";
|
|
4
|
+
/**
|
|
5
|
+
* GET /api/seo/indexnow/:key — the IndexNow key file. IndexNow reads it at
|
|
6
|
+
* `<site.baseUrl>/<key>.txt` to confirm the site owns the key, so the site
|
|
7
|
+
* routes that address here. Answers the key as plain text when it matches
|
|
8
|
+
* `seo.indexNow.key`, and 404 otherwise.
|
|
9
|
+
*/
|
|
10
|
+
export declare const seoIndexNowKey: ApiHandler;
|
|
11
|
+
//# sourceMappingURL=seo-indexnow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-indexnow.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-indexnow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,2BAA2B,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,UAI5B,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** The API path of the IndexNow key file; a site serves it at `/<key>.txt` */
|
|
2
|
+
export const SEO_INDEXNOW_KEY_PATH = '/api/seo/indexnow/:key';
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/seo/indexnow/:key — the IndexNow key file. IndexNow reads it at
|
|
5
|
+
* `<site.baseUrl>/<key>.txt` to confirm the site owns the key, so the site
|
|
6
|
+
* routes that address here. Answers the key as plain text when it matches
|
|
7
|
+
* `seo.indexNow.key`, and 404 otherwise.
|
|
8
|
+
*/
|
|
9
|
+
export const seoIndexNowKey = async (req, ctx) => {
|
|
10
|
+
const key = ctx.config.seo.indexNow.key;
|
|
11
|
+
if (!key || req.params['key'] !== key)
|
|
12
|
+
return { status: 404, body: { error: 'Not found' } };
|
|
13
|
+
return { status: 200, body: key, headers: { 'content-type': 'text/plain; charset=utf-8' } };
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=seo-indexnow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-indexnow.js","sourceRoot":"","sources":["../../src/handlers/seo-indexnow.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAe,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IAC3D,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAA;IACvC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG;QAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAA;IAC3F,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,2BAA2B,EAAE,EAAE,CAAA;AAC7F,CAAC,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ApiContext, ApiHandler } from '../types.js';
|
|
2
|
+
/** The route serving the site's llms.txt */
|
|
3
|
+
export declare const SEO_LLMS_TXT_PATH = "/api/seo/llms.txt";
|
|
4
|
+
/** Site settings key holding the saved llms.txt snapshot */
|
|
5
|
+
export declare const LLMS_TXT_SETTING = "seo.llmsTxt";
|
|
6
|
+
/** Text that replaces the generated summary and link descriptions */
|
|
7
|
+
export interface LlmsTxtOverrides {
|
|
8
|
+
summary?: string | undefined;
|
|
9
|
+
/** Link descriptions keyed by `collection/slug` */
|
|
10
|
+
descriptions?: ReadonlyMap<string, string> | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build llms.txt (llmstxt.org) from the live documents: the site name, its
|
|
14
|
+
* summary, then one section per collection with pages (`rendersPages()`) listing each live,
|
|
15
|
+
* indexable document with its URL and description.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildLlmsTxt(ctx: ApiContext, overrides?: LlmsTxtOverrides): Promise<string>;
|
|
18
|
+
/** The saved llms.txt snapshot, or null when none is saved */
|
|
19
|
+
export declare function loadLlmsTxtSnapshot(ctx: ApiContext): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* GET /api/seo/llms.txt — the saved snapshot when there is one, else generated
|
|
22
|
+
* from the live documents, as text/plain. The `x-krantho-llms-origin` header
|
|
23
|
+
* says which: `snapshot` or `generated`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const seoLlmsTxt: ApiHandler;
|
|
26
|
+
//# sourceMappingURL=seo-llms-txt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-llms-txt.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-llms-txt.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGzD,4CAA4C;AAC5C,eAAO,MAAM,iBAAiB,sBAAsB,CAAA;AAEpD,4DAA4D;AAC5D,eAAO,MAAM,gBAAgB,gBAAgB,CAAA;AAE7C,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,mDAAmD;IACnD,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAA;CACvD;AAsDD;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,UAAU,EACf,SAAS,GAAE,gBAAqB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAcjB;AAED,8DAA8D;AAC9D,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGjF;AAKD;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,UAcxB,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { documentPath, rendersPages } from '@krantho/core';
|
|
2
|
+
import { canReadPublished } from '@krantho/persistence';
|
|
3
|
+
import { buildSeoFieldMap, resolveSeoField } from '@krantho/seo-shared';
|
|
4
|
+
import { PUBLIC_MACHINE_READ_CACHE_CONTROL } from '../public-cache.js';
|
|
5
|
+
import { isNoindex } from './seo-sitemap.js';
|
|
6
|
+
/** The route serving the site's llms.txt */
|
|
7
|
+
export const SEO_LLMS_TXT_PATH = '/api/seo/llms.txt';
|
|
8
|
+
/** Site settings key holding the saved llms.txt snapshot */
|
|
9
|
+
export const LLMS_TXT_SETTING = 'seo.llmsTxt';
|
|
10
|
+
/** One line of text: runs of whitespace, newlines included, become one space */
|
|
11
|
+
function oneLine(text) {
|
|
12
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
13
|
+
}
|
|
14
|
+
/** The site summary: the override, else the site SEO config's primary entity description */
|
|
15
|
+
async function siteSummary(ctx, overrides) {
|
|
16
|
+
if (overrides.summary !== undefined)
|
|
17
|
+
return oneLine(overrides.summary);
|
|
18
|
+
const config = await ctx.seoConfigAdapter?.getConfig('site');
|
|
19
|
+
const description = config?.config.entities[0]?.properties['description'];
|
|
20
|
+
return typeof description === 'string' ? oneLine(description) : '';
|
|
21
|
+
}
|
|
22
|
+
/** `- [title](url): description` for one live document, or null when it is not listed */
|
|
23
|
+
function documentLine(ctx, collection, doc, overrides) {
|
|
24
|
+
if (isNoindex(doc.fields))
|
|
25
|
+
return null;
|
|
26
|
+
const path = documentPath(collection, doc.meta.slug);
|
|
27
|
+
if (path === null)
|
|
28
|
+
return null;
|
|
29
|
+
const fieldMap = buildSeoFieldMap(Object.keys(doc.fields));
|
|
30
|
+
const title = oneLine(resolveSeoField(fieldMap, 'title', doc.fields)) || doc.meta.slug;
|
|
31
|
+
const override = overrides.descriptions?.get(`${collection.name}/${doc.meta.slug}`);
|
|
32
|
+
const description = oneLine(override ?? resolveSeoField(fieldMap, 'description', doc.fields));
|
|
33
|
+
const baseUrl = ctx.config.site.baseUrl.replace(/\/$/, '');
|
|
34
|
+
const link = `- [${title}](${baseUrl}${path})`;
|
|
35
|
+
return description ? `${link}: ${description}` : link;
|
|
36
|
+
}
|
|
37
|
+
/** The `## collection` block of one collection, or null when it lists nothing */
|
|
38
|
+
async function collectionBlock(ctx, adapter, collection, overrides) {
|
|
39
|
+
const { items: docs } = await adapter.query({
|
|
40
|
+
state: 'published',
|
|
41
|
+
projection: 'summary',
|
|
42
|
+
collections: [collection.name],
|
|
43
|
+
});
|
|
44
|
+
const lines = docs
|
|
45
|
+
.map((doc) => documentLine(ctx, collection, doc, overrides))
|
|
46
|
+
.filter((line) => line !== null);
|
|
47
|
+
if (lines.length === 0)
|
|
48
|
+
return null;
|
|
49
|
+
return [`## ${collection.name}`, '', ...lines].join('\n');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build llms.txt (llmstxt.org) from the live documents: the site name, its
|
|
53
|
+
* summary, then one section per collection with pages (`rendersPages()`) listing each live,
|
|
54
|
+
* indexable document with its URL and description.
|
|
55
|
+
*/
|
|
56
|
+
export async function buildLlmsTxt(ctx, overrides = {}) {
|
|
57
|
+
const blocks = [`# ${oneLine(ctx.config.site.name)}`];
|
|
58
|
+
const summary = await siteSummary(ctx, overrides);
|
|
59
|
+
if (summary)
|
|
60
|
+
blocks.push(`> ${summary}`);
|
|
61
|
+
if (canReadPublished(ctx.adapter)) {
|
|
62
|
+
for (const collection of ctx.contentConfig.collections.values()) {
|
|
63
|
+
if (!rendersPages(collection))
|
|
64
|
+
continue;
|
|
65
|
+
const block = await collectionBlock(ctx, ctx.adapter, collection, overrides);
|
|
66
|
+
if (block)
|
|
67
|
+
blocks.push(block);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return `${blocks.join('\n\n')}\n`;
|
|
71
|
+
}
|
|
72
|
+
/** The saved llms.txt snapshot, or null when none is saved */
|
|
73
|
+
export async function loadLlmsTxtSnapshot(ctx) {
|
|
74
|
+
const saved = await ctx.siteSettingsAdapter?.getSetting(LLMS_TXT_SETTING);
|
|
75
|
+
return saved ? saved : null;
|
|
76
|
+
}
|
|
77
|
+
/** The response header naming where the served llms.txt comes from */
|
|
78
|
+
const LLMS_TXT_ORIGIN_HEADER = 'x-krantho-llms-origin';
|
|
79
|
+
/**
|
|
80
|
+
* GET /api/seo/llms.txt — the saved snapshot when there is one, else generated
|
|
81
|
+
* from the live documents, as text/plain. The `x-krantho-llms-origin` header
|
|
82
|
+
* says which: `snapshot` or `generated`.
|
|
83
|
+
*/
|
|
84
|
+
export const seoLlmsTxt = async (_req, ctx) => {
|
|
85
|
+
if (!canReadPublished(ctx.adapter)) {
|
|
86
|
+
return { status: 501, body: { error: 'Adapter does not support reading published content' } };
|
|
87
|
+
}
|
|
88
|
+
const snapshot = await loadLlmsTxtSnapshot(ctx);
|
|
89
|
+
return {
|
|
90
|
+
status: 200,
|
|
91
|
+
body: snapshot ?? (await buildLlmsTxt(ctx)),
|
|
92
|
+
headers: {
|
|
93
|
+
'content-type': 'text/plain; charset=utf-8',
|
|
94
|
+
'cache-control': PUBLIC_MACHINE_READ_CACHE_CONTROL,
|
|
95
|
+
[LLMS_TXT_ORIGIN_HEADER]: snapshot === null ? 'generated' : 'snapshot',
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=seo-llms-txt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-llms-txt.js","sourceRoot":"","sources":["../../src/handlers/seo-llms-txt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ApiHandler } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* GET /api/seo/preview/:collection/:slug — compose the JSON-LD of the
|
|
4
|
+
* document's current version in its collection and locale (`?locale=`, the
|
|
5
|
+
* site's default when absent; 400 when it is not a locale code)
|
|
6
|
+
*/
|
|
7
|
+
export declare const seoPreview: ApiHandler;
|
|
8
|
+
//# sourceMappingURL=seo-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-preview.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-preview.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAG7C;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,UAuCxB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { documentPath } from '@krantho/core';
|
|
2
|
+
import { canGetContent } from '@krantho/persistence';
|
|
3
|
+
import { composePageJsonLd } from '../seo-compose.js';
|
|
4
|
+
import { parseLocaleParam, requireParam, validateCollectionParam } from '../validators.js';
|
|
5
|
+
/**
|
|
6
|
+
* GET /api/seo/preview/:collection/:slug — compose the JSON-LD of the
|
|
7
|
+
* document's current version in its collection and locale (`?locale=`, the
|
|
8
|
+
* site's default when absent; 400 when it is not a locale code)
|
|
9
|
+
*/
|
|
10
|
+
export const seoPreview = async (req, ctx) => {
|
|
11
|
+
const validated = validateCollectionParam(req.params['collection'], ctx);
|
|
12
|
+
if (!validated.isValid)
|
|
13
|
+
return validated.response;
|
|
14
|
+
const slugResult = requireParam(req.params, 'slug');
|
|
15
|
+
if (!slugResult.isValid)
|
|
16
|
+
return slugResult.response;
|
|
17
|
+
const slug = slugResult.value;
|
|
18
|
+
const collection = validated.collection;
|
|
19
|
+
const requestedLocale = req.query['locale'];
|
|
20
|
+
const locale = parseLocaleParam(requestedLocale);
|
|
21
|
+
if (requestedLocale !== undefined && locale === undefined) {
|
|
22
|
+
return {
|
|
23
|
+
status: 400,
|
|
24
|
+
body: { error: '"locale" must be a locale code, such as "en" or "nb-NO"' },
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (!canGetContent(ctx.adapter)) {
|
|
28
|
+
return { status: 501, body: { error: 'Adapter does not support reading a document' } };
|
|
29
|
+
}
|
|
30
|
+
const current = await ctx.adapter.getContent(collection, slug, locale);
|
|
31
|
+
if (!current) {
|
|
32
|
+
return {
|
|
33
|
+
status: 404,
|
|
34
|
+
body: { error: `Content "${slug}" not found in "${collection}"` },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const graph = await composePageJsonLd({
|
|
38
|
+
collection,
|
|
39
|
+
slug,
|
|
40
|
+
path: documentPath(validated.collectionDef, slug),
|
|
41
|
+
fields: current.fields,
|
|
42
|
+
metadata: current.metadata,
|
|
43
|
+
documentMeta: current.meta,
|
|
44
|
+
config: ctx.config,
|
|
45
|
+
seoConfigs: ctx.seoConfigAdapter,
|
|
46
|
+
});
|
|
47
|
+
return { status: 200, body: graph };
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=seo-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-preview.js","sourceRoot":"","sources":["../../src/handlers/seo-preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAA;AAE1F;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAe,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACvD,MAAM,SAAS,GAAG,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,GAAG,CAAC,CAAA;IACxE,IAAI,CAAC,SAAS,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC,QAAQ,CAAA;IAEjD,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnD,IAAI,CAAC,UAAU,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC,QAAQ,CAAA;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAA;IAC7B,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAA;IACvC,MAAM,eAAe,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,MAAM,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAA;IAChD,IAAI,eAAe,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1D,OAAO;YACL,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,yDAAyD,EAAE;SAC3E,CAAA;IACH,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,6CAA6C,EAAE,EAAE,CAAA;IACxF,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,YAAY,IAAI,mBAAmB,UAAU,GAAG,EAAE;SAClE,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC;QACpC,UAAU;QACV,IAAI;QACJ,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC;QACjD,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,YAAY,EAAE,OAAO,CAAC,IAAI;QAC1B,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,gBAAgB;KACjC,CAAC,CAAA;IACF,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AACrC,CAAC,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ApiContext, ApiHandler } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The seo_config id whose `robotsTxt` holds a saved robots.txt override: the
|
|
4
|
+
* site scope's configuration, beside its entities and never among them. An
|
|
5
|
+
* admin saves it through `PUT /api/seo/config/site`; while set, the handler
|
|
6
|
+
* serves it verbatim, otherwise the generated body.
|
|
7
|
+
*/
|
|
8
|
+
export declare const robotsOverrideConfigId: "site";
|
|
9
|
+
/** Build the default robots.txt body, naming the sitemap at the site's root (`/sitemap.xml`) */
|
|
10
|
+
export declare function buildDefaultRobotsBody(baseUrl: string): string;
|
|
11
|
+
/** Read a saved robots override from the site's seo_config, or null if none exists */
|
|
12
|
+
export declare function loadRobotsOverride(ctx: ApiContext): Promise<string | null>;
|
|
13
|
+
/**
|
|
14
|
+
* GET /api/seo/robots.txt — generate robots.txt with sitemap reference.
|
|
15
|
+
*
|
|
16
|
+
* If an override is stored in seo_config (the site scope's `robotsTxt`), it
|
|
17
|
+
* is returned verbatim. Otherwise a standard robots.txt that
|
|
18
|
+
* allows all crawlers and points to the sitemap is generated dynamically
|
|
19
|
+
* from the handler's site.baseUrl.
|
|
20
|
+
*/
|
|
21
|
+
export declare const seoRobots: ApiHandler;
|
|
22
|
+
//# sourceMappingURL=seo-robots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-robots.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-robots.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGzD;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAG,MAAe,CAAA;AAErD,gGAAgG;AAChG,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED,sFAAsF;AACtF,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAShF;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,UAYvB,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { PUBLIC_MACHINE_READ_CACHE_CONTROL } from '../public-cache.js';
|
|
2
|
+
import { SITEMAP_PUBLIC_PATH } from './seo-sitemap.js';
|
|
3
|
+
/**
|
|
4
|
+
* The seo_config id whose `robotsTxt` holds a saved robots.txt override: the
|
|
5
|
+
* site scope's configuration, beside its entities and never among them. An
|
|
6
|
+
* admin saves it through `PUT /api/seo/config/site`; while set, the handler
|
|
7
|
+
* serves it verbatim, otherwise the generated body.
|
|
8
|
+
*/
|
|
9
|
+
export const robotsOverrideConfigId = 'site';
|
|
10
|
+
/** Build the default robots.txt body, naming the sitemap at the site's root (`/sitemap.xml`) */
|
|
11
|
+
export function buildDefaultRobotsBody(baseUrl) {
|
|
12
|
+
const trimmed = baseUrl.replace(/\/$/, '');
|
|
13
|
+
return ['User-agent: *', 'Allow: /', '', `Sitemap: ${trimmed}${SITEMAP_PUBLIC_PATH}`].join('\n');
|
|
14
|
+
}
|
|
15
|
+
/** Read a saved robots override from the site's seo_config, or null if none exists */
|
|
16
|
+
export async function loadRobotsOverride(ctx) {
|
|
17
|
+
if (!ctx.seoConfigAdapter)
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const config = await ctx.seoConfigAdapter.getConfig(robotsOverrideConfigId);
|
|
21
|
+
const override = config?.config.robotsTxt;
|
|
22
|
+
return typeof override === 'string' && override.length > 0 ? override : null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* GET /api/seo/robots.txt — generate robots.txt with sitemap reference.
|
|
30
|
+
*
|
|
31
|
+
* If an override is stored in seo_config (the site scope's `robotsTxt`), it
|
|
32
|
+
* is returned verbatim. Otherwise a standard robots.txt that
|
|
33
|
+
* allows all crawlers and points to the sitemap is generated dynamically
|
|
34
|
+
* from the handler's site.baseUrl.
|
|
35
|
+
*/
|
|
36
|
+
export const seoRobots = async (_req, ctx) => {
|
|
37
|
+
const override = await loadRobotsOverride(ctx);
|
|
38
|
+
const body = override ?? buildDefaultRobotsBody(ctx.config.site.baseUrl);
|
|
39
|
+
return {
|
|
40
|
+
status: 200,
|
|
41
|
+
body,
|
|
42
|
+
headers: {
|
|
43
|
+
'content-type': 'text/plain; charset=utf-8',
|
|
44
|
+
'cache-control': PUBLIC_MACHINE_READ_CACHE_CONTROL,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=seo-robots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-robots.js","sourceRoot":"","sources":["../../src/handlers/seo-robots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAe,CAAA;AAErD,gGAAgG;AAChG,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IAC1C,OAAO,CAAC,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,OAAO,GAAG,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAClG,CAAC;AAED,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAe;IACtD,IAAI,CAAC,GAAG,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAA;IACtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC3E,MAAM,QAAQ,GAAG,MAAM,EAAE,MAAM,CAAC,SAAS,CAAA;QACzC,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAe,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAA;IAC9C,MAAM,IAAI,GAAG,QAAQ,IAAI,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAExE,OAAO;QACL,MAAM,EAAE,GAAG;QACX,IAAI;QACJ,OAAO,EAAE;YACP,cAAc,EAAE,2BAA2B;YAC3C,eAAe,EAAE,iCAAiC;SACnD;KACF,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ApiContext, ApiHandler } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical paths for the SEO routes registered in `create-api-handlers.ts`.
|
|
4
|
+
*
|
|
5
|
+
* Exported as constants so callers (e.g., the robots.txt handler) reference
|
|
6
|
+
* the same path the router registers, preventing drift if a route is renamed.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SEO_SITEMAP_PATH = "/api/seo/sitemap";
|
|
9
|
+
/** Where a site serves the sitemap — the address robots.txt names; the site routes it to SEO_SITEMAP_PATH */
|
|
10
|
+
export declare const SITEMAP_PUBLIC_PATH = "/sitemap.xml";
|
|
11
|
+
export declare const SEO_SITEMAP_JSON_PATH = "/api/seo/sitemap.json";
|
|
12
|
+
export declare const SEO_ROBOTS_PATH = "/api/seo/robots.txt";
|
|
13
|
+
/** A single URL entry in the sitemap output */
|
|
14
|
+
export interface SitemapUrl {
|
|
15
|
+
loc: string;
|
|
16
|
+
/** When the page last changed, as a W3C Datetime in UTC (`2026-09-30T22:17:06.000Z`) */
|
|
17
|
+
lastmod?: string | undefined;
|
|
18
|
+
changefreq: string;
|
|
19
|
+
priority: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Whether a document asks not to be indexed. The field name is resolved
|
|
23
|
+
* dynamically so CMS schemas with different conventions (e.g. `robots-index`
|
|
24
|
+
* vs `noindex`) all work.
|
|
25
|
+
*/
|
|
26
|
+
export declare function isNoindex(fields: Record<string, unknown>): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Build the list of sitemap URLs from the handler's content config.
|
|
29
|
+
*
|
|
30
|
+
* Pure: reads from the context, returns an array. No side effects. This is
|
|
31
|
+
* the shared core used by both `seoSitemap` (XML output) and `seoSitemapJson`
|
|
32
|
+
* (JSON output for the Studio preview), plus any future consumer that needs
|
|
33
|
+
* the url list.
|
|
34
|
+
*
|
|
35
|
+
* Iterates every published item in every collection that renders pages
|
|
36
|
+
* (`rendersPages()`), skips noindex pages (resolved via the dynamic field map
|
|
37
|
+
* so CMS field names can differ), and derives the URL with `documentPath()`
|
|
38
|
+
* from the collection's `path` — or, without one, `pages` items at the site
|
|
39
|
+
* root (the `home` page is the homepage) and other collections under their
|
|
40
|
+
* name (`/{name}/slug`). A path is listed once: the homepage, and a fixed-path
|
|
41
|
+
* collection whose documents share one page.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildSitemapUrls(ctx: ApiContext): Promise<SitemapUrl[]>;
|
|
44
|
+
/**
|
|
45
|
+
* Serialize a list of sitemap URLs to XML.
|
|
46
|
+
*
|
|
47
|
+
* Exported so tests can drive the serializer directly without needing to
|
|
48
|
+
* stub the full ApiContext. Also used by the XML handler below.
|
|
49
|
+
*/
|
|
50
|
+
export declare function serializeSitemapXml(urls: readonly SitemapUrl[]): string;
|
|
51
|
+
/**
|
|
52
|
+
* GET /api/seo/sitemap — generate sitemap XML dynamically from all collections.
|
|
53
|
+
*
|
|
54
|
+
* Lists all published content across the collections that render pages, at
|
|
55
|
+
* site.baseUrl + `documentPath()`. Excludes collections without pages and
|
|
56
|
+
* noindex pages.
|
|
57
|
+
*/
|
|
58
|
+
export declare const seoSitemap: ApiHandler;
|
|
59
|
+
/**
|
|
60
|
+
* GET /api/seo/sitemap.json — same url list as the XML handler, served as JSON.
|
|
61
|
+
*
|
|
62
|
+
* Used by Studio's Structure → Sitemap & Robots tab to render a sortable table
|
|
63
|
+
* without parsing XML client-side. Not intended as a public SEO endpoint —
|
|
64
|
+
* search engines consume the XML at `/api/seo/sitemap` (or wherever your
|
|
65
|
+
* framework rewrites it, e.g. `/sitemap.xml`).
|
|
66
|
+
*/
|
|
67
|
+
export declare const seoSitemapJson: ApiHandler;
|
|
68
|
+
//# sourceMappingURL=seo-sitemap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-sitemap.d.ts","sourceRoot":"","sources":["../../src/handlers/seo-sitemap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAClD,6GAA6G;AAC7G,eAAO,MAAM,mBAAmB,iBAAiB,CAAA;AACjD,eAAO,MAAM,qBAAqB,0BAA0B,CAAA;AAC5D,eAAO,MAAM,eAAe,wBAAwB,CAAA;AAEpD,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CASlE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA2C7E;AAyBD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAYvE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,UAUxB,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,EAAE,UAM5B,CAAA"}
|