@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
package/dist/jwt.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { createHmac, randomBytes } from 'node:crypto';
|
|
2
|
+
/** Base64url encode a buffer */
|
|
3
|
+
function base64url(data) {
|
|
4
|
+
return data.toString('base64url');
|
|
5
|
+
}
|
|
6
|
+
/** Base64url encode a string */
|
|
7
|
+
function base64urlStr(str) {
|
|
8
|
+
return base64url(Buffer.from(str, 'utf-8'));
|
|
9
|
+
}
|
|
10
|
+
/** Base64url decode to string */
|
|
11
|
+
function base64urlDecode(str) {
|
|
12
|
+
return Buffer.from(str, 'base64url').toString('utf-8');
|
|
13
|
+
}
|
|
14
|
+
const JWT_HEADER = base64urlStr(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
|
|
15
|
+
/**
|
|
16
|
+
* Sign a JWT with HS256.
|
|
17
|
+
*
|
|
18
|
+
* @param claims - Token claims (sub, email, name, roles)
|
|
19
|
+
* @param secret - HMAC secret (`config.auth.jwtSecret`)
|
|
20
|
+
* @param expiresInSeconds - Token lifetime in seconds (default: 900 = 15 minutes)
|
|
21
|
+
*/
|
|
22
|
+
export function signJwt(claims, secret, expiresInSeconds = 900) {
|
|
23
|
+
const now = Math.floor(Date.now() / 1000);
|
|
24
|
+
const payload = {
|
|
25
|
+
...claims,
|
|
26
|
+
iat: now,
|
|
27
|
+
exp: now + expiresInSeconds,
|
|
28
|
+
};
|
|
29
|
+
const payloadEncoded = base64urlStr(JSON.stringify(payload));
|
|
30
|
+
const data = `${JWT_HEADER}.${payloadEncoded}`;
|
|
31
|
+
const signature = createHmac('sha256', secret).update(data).digest();
|
|
32
|
+
return `${data}.${base64url(signature)}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Verify a JWT signature and check expiry.
|
|
36
|
+
*
|
|
37
|
+
* @param token - The full JWT string
|
|
38
|
+
* @param secret - HMAC secret (must match the signing secret)
|
|
39
|
+
*/
|
|
40
|
+
export function verifyJwt(token, secret) {
|
|
41
|
+
const parts = token.split('.');
|
|
42
|
+
if (parts.length !== 3) {
|
|
43
|
+
return { valid: false, error: 'Invalid JWT format' };
|
|
44
|
+
}
|
|
45
|
+
const [header, payload, signature] = parts;
|
|
46
|
+
// Verify signature
|
|
47
|
+
const data = `${header}.${payload}`;
|
|
48
|
+
const expectedSignature = createHmac('sha256', secret).update(data).digest();
|
|
49
|
+
const actualSignature = Buffer.from(signature, 'base64url');
|
|
50
|
+
if (!expectedSignature.equals(actualSignature)) {
|
|
51
|
+
return { valid: false, error: 'Invalid signature' };
|
|
52
|
+
}
|
|
53
|
+
// Decode and validate claims
|
|
54
|
+
let claims;
|
|
55
|
+
try {
|
|
56
|
+
claims = JSON.parse(base64urlDecode(payload));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return { valid: false, error: 'Invalid JWT payload' };
|
|
60
|
+
}
|
|
61
|
+
// Check expiry
|
|
62
|
+
const now = Math.floor(Date.now() / 1000);
|
|
63
|
+
if (typeof claims.exp !== 'number' || claims.exp <= now) {
|
|
64
|
+
return { valid: false, error: 'Token expired' };
|
|
65
|
+
}
|
|
66
|
+
// Validate required fields
|
|
67
|
+
if (typeof claims.sub !== 'string' || !claims.sub) {
|
|
68
|
+
return { valid: false, error: 'Missing sub claim' };
|
|
69
|
+
}
|
|
70
|
+
if (!Array.isArray(claims.roles) || claims.roles.length === 0) {
|
|
71
|
+
return { valid: false, error: 'Missing roles claim' };
|
|
72
|
+
}
|
|
73
|
+
return { valid: true, claims };
|
|
74
|
+
}
|
|
75
|
+
/** Generate a cryptographically random refresh token (64 hex chars) */
|
|
76
|
+
export function generateRefreshToken() {
|
|
77
|
+
return randomBytes(32).toString('hex');
|
|
78
|
+
}
|
|
79
|
+
/** Hash a refresh token for database storage */
|
|
80
|
+
export function hashRefreshToken(token, secret) {
|
|
81
|
+
return createHmac('sha256', secret).update(token).digest('hex');
|
|
82
|
+
}
|
|
83
|
+
/** Generate a random JWT secret (for dev mode when none is configured) */
|
|
84
|
+
export function generateJwtSecret() {
|
|
85
|
+
return randomBytes(32).toString('hex');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Where the process keeps its ephemeral secret: on `globalThis`, so every copy
|
|
89
|
+
* of this module a bundler may make (route handlers and pages) shares it
|
|
90
|
+
*/
|
|
91
|
+
const EPHEMERAL_SECRET = Symbol.for('krantho.ephemeralJwtSecret');
|
|
92
|
+
function processSecret() {
|
|
93
|
+
const store = globalThis;
|
|
94
|
+
store[EPHEMERAL_SECRET] ??= {};
|
|
95
|
+
return store[EPHEMERAL_SECRET];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The effective signing secret: the configured one (KRANTHO_JWT_SECRET beats a
|
|
99
|
+
* `jwtSecret` set in code, as the config tree resolves it), or, when neither is
|
|
100
|
+
* set, one ephemeral secret for the whole process — generated with a warning —
|
|
101
|
+
* so the API and the pages it serves (a signed preview link) agree on it.
|
|
102
|
+
*/
|
|
103
|
+
export function resolveJwtSecret(auth) {
|
|
104
|
+
if (auth.jwtSecret)
|
|
105
|
+
return auth.jwtSecret;
|
|
106
|
+
const secret = processSecret();
|
|
107
|
+
if (secret.value)
|
|
108
|
+
return secret.value;
|
|
109
|
+
// Dev mode: sessions and preview links do not survive restarts
|
|
110
|
+
secret.value = generateJwtSecret();
|
|
111
|
+
console.warn('[krantho] No KRANTHO_JWT_SECRET set — using ephemeral secret. Sessions will not survive restarts.');
|
|
112
|
+
return secret.value;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=jwt.js.map
|
package/dist/jwt.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../src/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAuBrD,gCAAgC;AAChC,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AACnC,CAAC;AAED,gCAAgC;AAChC,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED,iCAAiC;AACjC,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;AAE7E;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,MAAsC,EACtC,MAAc,EACd,gBAAgB,GAAG,GAAG;IAEtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACzC,MAAM,OAAO,GAAc;QACzB,GAAG,MAAM;QACT,GAAG,EAAE,GAAG;QACR,GAAG,EAAE,GAAG,GAAG,gBAAgB;KAC5B,CAAA;IAED,MAAM,cAAc,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IAC5D,MAAM,IAAI,GAAG,GAAG,UAAU,IAAI,cAAc,EAAE,CAAA;IAC9C,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAA;IAEpE,OAAO,GAAG,IAAI,IAAI,SAAS,CAAC,SAAS,CAAC,EAAE,CAAA;AAC1C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAc;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAA;IACtD,CAAC;IAED,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,GAAG,KAAiC,CAAA;IAEtE,mBAAmB;IACnB,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAA;IACnC,MAAM,iBAAiB,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAA;IAC5E,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IAE3D,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAA;IACrD,CAAC;IAED,6BAA6B;IAC7B,IAAI,MAAiB,CAAA;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAc,CAAA;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAA;IACvD,CAAC;IAED,eAAe;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IACzC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QACxD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAA;IACjD,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAClD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAA;IACrD,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAA;IACvD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AAChC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,oBAAoB;IAClC,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxC,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjE,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB;IAC/B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,gBAAgB,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAEjE,SAAS,aAAa;IACpB,MAAM,KAAK,GAAG,UAAwE,CAAA;IACtF,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAA;IAC9B,OAAO,KAAK,CAAC,gBAAgB,CAAC,CAAA;AAChC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAoC;IACnE,IAAI,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC,SAAS,CAAA;IACzC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAC9B,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC,KAAK,CAAA;IAErC,+DAA+D;IAC/D,MAAM,CAAC,KAAK,GAAG,iBAAiB,EAAE,CAAA;IAClC,OAAO,CAAC,IAAI,CACV,mGAAmG,CACpG,CAAA;IACD,OAAO,MAAM,CAAC,KAAK,CAAA;AACrB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SiteSection } from '@krantho/config';
|
|
2
|
+
import { type ContentDocument, type IPersistenceAdapter } from '@krantho/persistence';
|
|
3
|
+
/**
|
|
4
|
+
* Build a locale fallback chain from a requested locale.
|
|
5
|
+
*
|
|
6
|
+
* Example: 'es-MX' → ['es-MX', 'es', defaultLocale]
|
|
7
|
+
* Example: 'fr' → ['fr', defaultLocale]
|
|
8
|
+
* Example: 'en' (= default) → ['en']
|
|
9
|
+
*/
|
|
10
|
+
export declare function buildFallbackChain(requestedLocale: string, site: SiteSection): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Get content with locale fallback.
|
|
13
|
+
*
|
|
14
|
+
* Tries the requested locale first, then walks the fallback chain.
|
|
15
|
+
* Returns the first match, or null if no locale has the content.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getContentWithFallback(adapter: IPersistenceAdapter, collection: string, slug: string, locale: string, site: SiteSection): Promise<ContentDocument | null>;
|
|
18
|
+
//# sourceMappingURL=locale-fallback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale-fallback.d.ts","sourceRoot":"","sources":["../src/locale-fallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,KAAK,eAAe,EAAiB,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAEpG;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,CAkBvF;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAWjC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { canGetContent } from '@krantho/persistence';
|
|
2
|
+
/**
|
|
3
|
+
* Build a locale fallback chain from a requested locale.
|
|
4
|
+
*
|
|
5
|
+
* Example: 'es-MX' → ['es-MX', 'es', defaultLocale]
|
|
6
|
+
* Example: 'fr' → ['fr', defaultLocale]
|
|
7
|
+
* Example: 'en' (= default) → ['en']
|
|
8
|
+
*/
|
|
9
|
+
export function buildFallbackChain(requestedLocale, site) {
|
|
10
|
+
const defaultLocale = site.defaultLocale ?? site.language;
|
|
11
|
+
const chain = [requestedLocale];
|
|
12
|
+
// Add parent locale (e.g. 'es-MX' → 'es')
|
|
13
|
+
if (requestedLocale.includes('-')) {
|
|
14
|
+
const parent = requestedLocale.split('-')[0];
|
|
15
|
+
if (!chain.includes(parent)) {
|
|
16
|
+
chain.push(parent);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Add default locale as final fallback
|
|
20
|
+
if (!chain.includes(defaultLocale)) {
|
|
21
|
+
chain.push(defaultLocale);
|
|
22
|
+
}
|
|
23
|
+
return chain;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get content with locale fallback.
|
|
27
|
+
*
|
|
28
|
+
* Tries the requested locale first, then walks the fallback chain.
|
|
29
|
+
* Returns the first match, or null if no locale has the content.
|
|
30
|
+
*/
|
|
31
|
+
export async function getContentWithFallback(adapter, collection, slug, locale, site) {
|
|
32
|
+
if (!canGetContent(adapter))
|
|
33
|
+
return null;
|
|
34
|
+
const chain = buildFallbackChain(locale, site);
|
|
35
|
+
for (const loc of chain) {
|
|
36
|
+
const doc = await adapter.getContent(collection, slug, loc);
|
|
37
|
+
if (doc)
|
|
38
|
+
return doc;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=locale-fallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale-fallback.js","sourceRoot":"","sources":["../src/locale-fallback.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,aAAa,EAA4B,MAAM,sBAAsB,CAAA;AAEpG;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,eAAuB,EAAE,IAAiB;IAC3E,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,QAAQ,CAAA;IACzD,MAAM,KAAK,GAAa,CAAC,eAAe,CAAC,CAAA;IAEzC,0CAA0C;IAC1C,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAA;QAC7C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC3B,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAA4B,EAC5B,UAAkB,EAClB,IAAY,EACZ,MAAc,EACd,IAAiB;IAEjB,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAExC,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAE9C,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;QAC3D,IAAI,GAAG;YAAE,OAAO,GAAG,CAAA;IACrB,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { MediaSection } from '@krantho/config';
|
|
2
|
+
import type { BulkDeleteResult, IFileStore, IMediaMetadataAdapter, IMediaStorage, MediaItem, MediaListOptions, MediaStats, MediaUpdateData } from '@krantho/persistence';
|
|
3
|
+
/** The media settings the library enforces */
|
|
4
|
+
export type MediaLibrarySettings = Pick<MediaSection, 'maxFileSize' | 'allowedMimeTypes'>;
|
|
5
|
+
/** An externally uploaded file, as `register` accepts it */
|
|
6
|
+
type RegisteredFile = Parameters<IMediaStorage['register']>[0];
|
|
7
|
+
/**
|
|
8
|
+
* The media library: metadata in the configured persistence, bytes in the
|
|
9
|
+
* configured file store. Owns the rules — MIME and size limits, immutable
|
|
10
|
+
* object keys, dimension detection — and keeps the two in step: a file
|
|
11
|
+
* written for a failed insert is removed, and a superseded file is deleted
|
|
12
|
+
* once the metadata no longer points at it.
|
|
13
|
+
*/
|
|
14
|
+
export declare class MediaLibrary implements IMediaStorage {
|
|
15
|
+
private readonly metadata;
|
|
16
|
+
private readonly files;
|
|
17
|
+
private readonly settings;
|
|
18
|
+
private readonly allowedMimeTypes;
|
|
19
|
+
constructor(metadata: IMediaMetadataAdapter, files: IFileStore, settings: MediaLibrarySettings);
|
|
20
|
+
upload(file: Uint8Array, filename: string, mimeType: string): Promise<MediaItem>;
|
|
21
|
+
register(item: RegisteredFile): Promise<MediaItem>;
|
|
22
|
+
list(options?: MediaListOptions): Promise<{
|
|
23
|
+
items: MediaItem[];
|
|
24
|
+
total: number;
|
|
25
|
+
}>;
|
|
26
|
+
get(id: string): Promise<MediaItem | null>;
|
|
27
|
+
/** Metadata only: a rename changes the display name, never the key or url */
|
|
28
|
+
update(id: string, updates: MediaUpdateData): Promise<MediaItem | null>;
|
|
29
|
+
delete(id: string): Promise<void>;
|
|
30
|
+
bulkDelete(ids: string[]): Promise<BulkDeleteResult>;
|
|
31
|
+
bulkUpdateAltText(ids: string[], altText: string): Promise<number>;
|
|
32
|
+
/** Write the new file under a new key, point the record at it, then drop the old file */
|
|
33
|
+
replace(id: string, file: Uint8Array, filename: string, mimeType: string): Promise<MediaItem | null>;
|
|
34
|
+
duplicate(id: string): Promise<MediaItem | null>;
|
|
35
|
+
listTags(): Promise<string[]>;
|
|
36
|
+
stats(): Promise<MediaStats>;
|
|
37
|
+
/** Stored bytes from the file store; a registered item is fetched from its url */
|
|
38
|
+
readOriginal(id: string): Promise<Uint8Array | null>;
|
|
39
|
+
private assertAccepted;
|
|
40
|
+
/** Insert a record whose file was just written; the file goes when the insert fails */
|
|
41
|
+
private insertOrDiscard;
|
|
42
|
+
/** Append a version pointing at a just-written file; the file goes unless it is now current */
|
|
43
|
+
private appendOrDiscard;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=media-library.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-library.d.ts","sourceRoot":"","sources":["../src/media-library.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACV,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,gBAAgB,EAGhB,UAAU,EACV,eAAe,EAEhB,MAAM,sBAAsB,CAAA;AAG7B,8CAA8C;AAC9C,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,kBAAkB,CAAC,CAAA;AAEzF,4DAA4D;AAC5D,KAAK,cAAc,GAAG,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAE9D;;;;;;GAMG;AACH,qBAAa,YAAa,YAAW,aAAa;IAI9C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAL3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;gBAGnC,QAAQ,EAAE,qBAAqB,EAC/B,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,oBAAoB;IAK3C,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAsBhF,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;IAmBlD,IAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAKhF,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAKhD,6EAA6E;IACvE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAKvE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAcpD,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxE,yFAAyF;IACnF,OAAO,CACX,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAuBtB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAqBhD,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAI7B,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAIlC,kFAAkF;IAC5E,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAU1D,OAAO,CAAC,cAAc;IAStB,uFAAuF;YACzE,eAAe;IAS7B,+FAA+F;YACjF,eAAe;CAa9B"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { detectDimensions } from './image-dimensions.js';
|
|
3
|
+
/**
|
|
4
|
+
* The media library: metadata in the configured persistence, bytes in the
|
|
5
|
+
* configured file store. Owns the rules — MIME and size limits, immutable
|
|
6
|
+
* object keys, dimension detection — and keeps the two in step: a file
|
|
7
|
+
* written for a failed insert is removed, and a superseded file is deleted
|
|
8
|
+
* once the metadata no longer points at it.
|
|
9
|
+
*/
|
|
10
|
+
export class MediaLibrary {
|
|
11
|
+
metadata;
|
|
12
|
+
files;
|
|
13
|
+
settings;
|
|
14
|
+
allowedMimeTypes;
|
|
15
|
+
constructor(metadata, files, settings) {
|
|
16
|
+
this.metadata = metadata;
|
|
17
|
+
this.files = files;
|
|
18
|
+
this.settings = settings;
|
|
19
|
+
this.allowedMimeTypes = new Set(settings.allowedMimeTypes);
|
|
20
|
+
}
|
|
21
|
+
async upload(file, filename, mimeType) {
|
|
22
|
+
this.assertAccepted(file, mimeType);
|
|
23
|
+
const stored = await this.files.put(newKey(filename), file, mimeType);
|
|
24
|
+
const dimensions = detectDimensions(file);
|
|
25
|
+
const record = await this.insertOrDiscard(stored.key, {
|
|
26
|
+
id: randomUUID(),
|
|
27
|
+
filename,
|
|
28
|
+
storageKey: stored.key,
|
|
29
|
+
url: stored.url,
|
|
30
|
+
altText: '',
|
|
31
|
+
mimeType,
|
|
32
|
+
size: file.byteLength,
|
|
33
|
+
width: dimensions?.width ?? null,
|
|
34
|
+
height: dimensions?.height ?? null,
|
|
35
|
+
folder: null,
|
|
36
|
+
tags: [],
|
|
37
|
+
crop: null,
|
|
38
|
+
hotspot: null,
|
|
39
|
+
});
|
|
40
|
+
return toMediaItem(record);
|
|
41
|
+
}
|
|
42
|
+
async register(item) {
|
|
43
|
+
const record = await this.metadata.insert({
|
|
44
|
+
id: randomUUID(),
|
|
45
|
+
filename: item.filename,
|
|
46
|
+
storageKey: null,
|
|
47
|
+
url: item.url,
|
|
48
|
+
altText: item.altText ?? '',
|
|
49
|
+
mimeType: item.mimeType,
|
|
50
|
+
size: item.size,
|
|
51
|
+
width: item.width,
|
|
52
|
+
height: item.height,
|
|
53
|
+
folder: null,
|
|
54
|
+
tags: [],
|
|
55
|
+
crop: null,
|
|
56
|
+
hotspot: null,
|
|
57
|
+
});
|
|
58
|
+
return toMediaItem(record);
|
|
59
|
+
}
|
|
60
|
+
async list(options) {
|
|
61
|
+
const { items, total } = await this.metadata.list(options);
|
|
62
|
+
return { items: items.map(toMediaItem), total };
|
|
63
|
+
}
|
|
64
|
+
async get(id) {
|
|
65
|
+
const record = await this.metadata.get(id);
|
|
66
|
+
return record ? toMediaItem(record) : null;
|
|
67
|
+
}
|
|
68
|
+
/** Metadata only: a rename changes the display name, never the key or url */
|
|
69
|
+
async update(id, updates) {
|
|
70
|
+
const record = await this.metadata.appendVersion(id, metadataChanges(updates));
|
|
71
|
+
return record ? toMediaItem(record) : null;
|
|
72
|
+
}
|
|
73
|
+
async delete(id) {
|
|
74
|
+
const superseded = await this.metadata.markDeleted(id);
|
|
75
|
+
if (superseded?.storageKey)
|
|
76
|
+
await this.files.delete(superseded.storageKey);
|
|
77
|
+
}
|
|
78
|
+
async bulkDelete(ids) {
|
|
79
|
+
const deleted = [];
|
|
80
|
+
const skipped = [];
|
|
81
|
+
for (const id of ids) {
|
|
82
|
+
try {
|
|
83
|
+
await this.delete(id);
|
|
84
|
+
deleted.push(id);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
skipped.push({ id, reason: err instanceof Error ? err.message : 'Unknown error' });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { deleted, skipped };
|
|
91
|
+
}
|
|
92
|
+
async bulkUpdateAltText(ids, altText) {
|
|
93
|
+
let count = 0;
|
|
94
|
+
for (const id of ids) {
|
|
95
|
+
if (await this.update(id, { altText }))
|
|
96
|
+
count++;
|
|
97
|
+
}
|
|
98
|
+
return count;
|
|
99
|
+
}
|
|
100
|
+
/** Write the new file under a new key, point the record at it, then drop the old file */
|
|
101
|
+
async replace(id, file, filename, mimeType) {
|
|
102
|
+
const existing = await this.metadata.get(id);
|
|
103
|
+
if (!existing)
|
|
104
|
+
return null;
|
|
105
|
+
this.assertAccepted(file, mimeType);
|
|
106
|
+
const stored = await this.files.put(newKey(filename), file, mimeType);
|
|
107
|
+
const dimensions = detectDimensions(file);
|
|
108
|
+
const record = await this.appendOrDiscard(stored.key, id, {
|
|
109
|
+
filename,
|
|
110
|
+
storageKey: stored.key,
|
|
111
|
+
url: stored.url,
|
|
112
|
+
mimeType,
|
|
113
|
+
size: file.byteLength,
|
|
114
|
+
width: dimensions?.width ?? null,
|
|
115
|
+
height: dimensions?.height ?? null,
|
|
116
|
+
crop: null,
|
|
117
|
+
hotspot: null,
|
|
118
|
+
});
|
|
119
|
+
if (!record)
|
|
120
|
+
return null;
|
|
121
|
+
if (existing.storageKey)
|
|
122
|
+
await this.files.delete(existing.storageKey);
|
|
123
|
+
return toMediaItem(record);
|
|
124
|
+
}
|
|
125
|
+
async duplicate(id) {
|
|
126
|
+
const existing = await this.metadata.get(id);
|
|
127
|
+
if (!existing)
|
|
128
|
+
return null;
|
|
129
|
+
const { createdAt: _createdAt, ...copy } = existing;
|
|
130
|
+
const newRecord = { ...copy, id: randomUUID() };
|
|
131
|
+
if (!existing.storageKey)
|
|
132
|
+
return toMediaItem(await this.metadata.insert(newRecord));
|
|
133
|
+
const stored = await this.files.copy(existing.storageKey, newKey(existing.filename), existing.mimeType);
|
|
134
|
+
const record = await this.insertOrDiscard(stored.key, {
|
|
135
|
+
...newRecord,
|
|
136
|
+
storageKey: stored.key,
|
|
137
|
+
url: stored.url,
|
|
138
|
+
});
|
|
139
|
+
return toMediaItem(record);
|
|
140
|
+
}
|
|
141
|
+
async listTags() {
|
|
142
|
+
return this.metadata.listTags();
|
|
143
|
+
}
|
|
144
|
+
async stats() {
|
|
145
|
+
return this.metadata.stats();
|
|
146
|
+
}
|
|
147
|
+
/** Stored bytes from the file store; a registered item is fetched from its url */
|
|
148
|
+
async readOriginal(id) {
|
|
149
|
+
const record = await this.metadata.get(id);
|
|
150
|
+
if (!record)
|
|
151
|
+
return null;
|
|
152
|
+
if (record.storageKey)
|
|
153
|
+
return this.files.get(record.storageKey);
|
|
154
|
+
const response = await fetch(record.url);
|
|
155
|
+
if (!response.ok)
|
|
156
|
+
return null;
|
|
157
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
158
|
+
}
|
|
159
|
+
assertAccepted(file, mimeType) {
|
|
160
|
+
if (!this.allowedMimeTypes.has(mimeType)) {
|
|
161
|
+
throw new Error(`Unsupported file type: ${mimeType}`);
|
|
162
|
+
}
|
|
163
|
+
if (file.byteLength > this.settings.maxFileSize) {
|
|
164
|
+
throw new Error(`File too large: ${file.byteLength} bytes (max ${this.settings.maxFileSize})`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** Insert a record whose file was just written; the file goes when the insert fails */
|
|
168
|
+
async insertOrDiscard(key, record) {
|
|
169
|
+
try {
|
|
170
|
+
return await this.metadata.insert(record);
|
|
171
|
+
}
|
|
172
|
+
catch (err) {
|
|
173
|
+
await this.files.delete(key);
|
|
174
|
+
throw err;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/** Append a version pointing at a just-written file; the file goes unless it is now current */
|
|
178
|
+
async appendOrDiscard(key, id, changes) {
|
|
179
|
+
let record = null;
|
|
180
|
+
try {
|
|
181
|
+
record = await this.metadata.appendVersion(id, changes);
|
|
182
|
+
return record;
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
if (!record)
|
|
186
|
+
await this.files.delete(key);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** The public shape of a record: everything but the object key */
|
|
191
|
+
function toMediaItem(record) {
|
|
192
|
+
const { storageKey: _storageKey, ...item } = record;
|
|
193
|
+
return item;
|
|
194
|
+
}
|
|
195
|
+
/** Only the fields an update names; the rest of the record carries over */
|
|
196
|
+
function metadataChanges(updates) {
|
|
197
|
+
const changes = {};
|
|
198
|
+
if (updates.altText !== undefined)
|
|
199
|
+
changes.altText = updates.altText;
|
|
200
|
+
if (updates.folder !== undefined)
|
|
201
|
+
changes.folder = updates.folder;
|
|
202
|
+
if (updates.tags !== undefined)
|
|
203
|
+
changes.tags = updates.tags;
|
|
204
|
+
if (updates.crop !== undefined)
|
|
205
|
+
changes.crop = updates.crop;
|
|
206
|
+
if (updates.hotspot !== undefined)
|
|
207
|
+
changes.hotspot = updates.hotspot;
|
|
208
|
+
if (updates.filename !== undefined)
|
|
209
|
+
changes.filename = updates.filename;
|
|
210
|
+
return changes;
|
|
211
|
+
}
|
|
212
|
+
/** A fresh, never-reused, flat object key */
|
|
213
|
+
function newKey(filename) {
|
|
214
|
+
return `${Date.now()}-${randomUUID().slice(0, 8)}-${slugifyFilename(filename)}`;
|
|
215
|
+
}
|
|
216
|
+
/** Lowercase name and extension, every other run of characters a hyphen */
|
|
217
|
+
function slugifyFilename(filename) {
|
|
218
|
+
const dotIndex = filename.lastIndexOf('.');
|
|
219
|
+
const name = dotIndex > 0 ? filename.slice(0, dotIndex) : filename;
|
|
220
|
+
const ext = dotIndex > 0 ? filename.slice(dotIndex + 1) : '';
|
|
221
|
+
const slug = slugify(name) || 'file';
|
|
222
|
+
const extension = slugify(ext);
|
|
223
|
+
return extension ? `${slug}.${extension}` : slug;
|
|
224
|
+
}
|
|
225
|
+
function slugify(value) {
|
|
226
|
+
return value
|
|
227
|
+
.toLowerCase()
|
|
228
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
229
|
+
.replace(/^-|-$/g, '');
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=media-library.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-library.js","sourceRoot":"","sources":["../src/media-library.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type IPersistenceAdapter } from '@krantho/persistence';
|
|
2
|
+
import type { ContentConfig } from '@krantho/schema';
|
|
3
|
+
/** The outcome of a media reference update: documents rewritten, and the ones that could not be */
|
|
4
|
+
export interface MediaReferenceUpdate {
|
|
5
|
+
readonly updated: number;
|
|
6
|
+
readonly failed: ReadonlyArray<{
|
|
7
|
+
collection: string;
|
|
8
|
+
slug: string;
|
|
9
|
+
locale: string;
|
|
10
|
+
reason: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Scan all content for references to an old media URL and update them to the
|
|
15
|
+
* new URL. Each updated document gets a new version (append-only).
|
|
16
|
+
*
|
|
17
|
+
* Scans `fields`, the authored `metadata` (a sharing image, say) and the
|
|
18
|
+
* markdown `body`. Each write names the version it read and keeps the
|
|
19
|
+
* document's contract and provenance; a document edited meanwhile is read
|
|
20
|
+
* again and retried once. A document that still fails is reported, and the
|
|
21
|
+
* rest are updated all the same.
|
|
22
|
+
*/
|
|
23
|
+
export declare function updateMediaReferences(oldUrl: string, newUrl: string, adapter: IPersistenceAdapter, contentConfig: ContentConfig): Promise<MediaReferenceUpdate>;
|
|
24
|
+
//# sourceMappingURL=media-reference-updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-reference-updater.d.ts","sourceRoot":"","sources":["../src/media-reference-updater.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,mGAAmG;AACnG,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;QAC7B,UAAU,EAAE,MAAM,CAAA;QAClB,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;KACf,CAAC,CAAA;CACH;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,mBAAmB,EAC5B,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAkB/B"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ContentWriteConflict, canGetContent, canQuery, currentIsLive, } from '@krantho/persistence';
|
|
2
|
+
/**
|
|
3
|
+
* Scan all content for references to an old media URL and update them to the
|
|
4
|
+
* new URL. Each updated document gets a new version (append-only).
|
|
5
|
+
*
|
|
6
|
+
* Scans `fields`, the authored `metadata` (a sharing image, say) and the
|
|
7
|
+
* markdown `body`. Each write names the version it read and keeps the
|
|
8
|
+
* document's contract and provenance; a document edited meanwhile is read
|
|
9
|
+
* again and retried once. A document that still fails is reported, and the
|
|
10
|
+
* rest are updated all the same.
|
|
11
|
+
*/
|
|
12
|
+
export async function updateMediaReferences(oldUrl, newUrl, adapter, contentConfig) {
|
|
13
|
+
const collections = [...contentConfig.collections.keys()];
|
|
14
|
+
if (collections.length === 0 || !canQuery(adapter) || !adapter.writeContent)
|
|
15
|
+
return { updated: 0, failed: [] };
|
|
16
|
+
const writer = adapter;
|
|
17
|
+
let updated = 0;
|
|
18
|
+
const failed = [];
|
|
19
|
+
const { items } = await adapter.query({ state: 'current', projection: 'full', collections });
|
|
20
|
+
for (const item of items) {
|
|
21
|
+
try {
|
|
22
|
+
if (await rewriteDocument(writer, item, oldUrl, newUrl))
|
|
23
|
+
updated++;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const { collection, slug, locale } = item.meta;
|
|
27
|
+
const reason = error instanceof Error ? error.message : 'unknown error';
|
|
28
|
+
failed.push({ collection, slug, locale, reason });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return { updated, failed };
|
|
32
|
+
}
|
|
33
|
+
/** Write the document with the new URL; true when a version was written */
|
|
34
|
+
async function rewriteDocument(adapter, item, oldUrl, newUrl) {
|
|
35
|
+
let document = item;
|
|
36
|
+
for (let attempt = 1;; attempt++) {
|
|
37
|
+
const fields = replaceInFields(document.fields, oldUrl, newUrl);
|
|
38
|
+
const metadata = replaceInFields(document.metadata, oldUrl, newUrl);
|
|
39
|
+
const body = document.body.replaceAll(oldUrl, newUrl);
|
|
40
|
+
if (fields === document.fields && metadata === document.metadata && body === document.body)
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
// A live document in step with its page stays live with the new URL;
|
|
44
|
+
// one with changes ahead gets the new URL in its current version only
|
|
45
|
+
await adapter.writeContent({
|
|
46
|
+
collection: document.meta.collection,
|
|
47
|
+
slug: document.meta.slug,
|
|
48
|
+
locale: document.meta.locale,
|
|
49
|
+
fields,
|
|
50
|
+
body,
|
|
51
|
+
metadata,
|
|
52
|
+
contract: document.contract,
|
|
53
|
+
defaults: document.defaults,
|
|
54
|
+
repositoryBasis: document.repositoryBasis,
|
|
55
|
+
publication: currentIsLive(document.meta) ? 'publish' : undefined,
|
|
56
|
+
expectedVersion: document.meta.version,
|
|
57
|
+
}, 'media-replace');
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (!(error instanceof ContentWriteConflict) || !canGetContent(adapter) || attempt === 2)
|
|
62
|
+
throw error;
|
|
63
|
+
const fresh = await adapter.getContent(document.meta.collection, document.meta.slug, document.meta.locale);
|
|
64
|
+
// Deleted meanwhile: nothing left that points at the old file
|
|
65
|
+
if (!fresh)
|
|
66
|
+
return false;
|
|
67
|
+
document = fresh;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Recursively replace all string occurrences of oldUrl with newUrl in a fields object.
|
|
73
|
+
* Returns the same object reference if nothing changed, a new object if changed.
|
|
74
|
+
*/
|
|
75
|
+
function replaceInFields(fields, oldUrl, newUrl) {
|
|
76
|
+
let changed = false;
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
79
|
+
if (typeof value === 'string' && value.includes(oldUrl)) {
|
|
80
|
+
result[key] = value.replaceAll(oldUrl, newUrl);
|
|
81
|
+
changed = true;
|
|
82
|
+
}
|
|
83
|
+
else if (Array.isArray(value)) {
|
|
84
|
+
const newArr = replaceInArray(value, oldUrl, newUrl);
|
|
85
|
+
result[key] = newArr.result;
|
|
86
|
+
if (newArr.changed)
|
|
87
|
+
changed = true;
|
|
88
|
+
}
|
|
89
|
+
else if (value && typeof value === 'object') {
|
|
90
|
+
const newObj = replaceInFields(value, oldUrl, newUrl);
|
|
91
|
+
result[key] = newObj;
|
|
92
|
+
if (newObj !== value)
|
|
93
|
+
changed = true;
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
result[key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return changed ? result : fields;
|
|
100
|
+
}
|
|
101
|
+
function replaceInArray(arr, oldUrl, newUrl) {
|
|
102
|
+
let changed = false;
|
|
103
|
+
const result = arr.map((item) => {
|
|
104
|
+
if (typeof item === 'string' && item.includes(oldUrl)) {
|
|
105
|
+
changed = true;
|
|
106
|
+
return item.replaceAll(oldUrl, newUrl);
|
|
107
|
+
}
|
|
108
|
+
if (item && typeof item === 'object' && !Array.isArray(item)) {
|
|
109
|
+
const newObj = replaceInFields(item, oldUrl, newUrl);
|
|
110
|
+
if (newObj !== item)
|
|
111
|
+
changed = true;
|
|
112
|
+
return newObj;
|
|
113
|
+
}
|
|
114
|
+
if (Array.isArray(item)) {
|
|
115
|
+
const nested = replaceInArray(item, oldUrl, newUrl);
|
|
116
|
+
if (nested.changed)
|
|
117
|
+
changed = true;
|
|
118
|
+
return nested.result;
|
|
119
|
+
}
|
|
120
|
+
return item;
|
|
121
|
+
});
|
|
122
|
+
return { result, changed };
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=media-reference-updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media-reference-updater.js","sourceRoot":"","sources":["../src/media-reference-updater.ts"],"names":[],"mappings":"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"}
|