@wildo-ai/saas-website 1.1.1
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 +34 -0
- package/dist/esm/.builder.pid +9 -0
- package/dist/esm/astro/blog-post-bridge.d.ts +324 -0
- package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-bridge.js +57 -0
- package/dist/esm/astro/blog-post-bridge.js.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts +129 -0
- package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/blog-post-head.renderer.js +139 -0
- package/dist/esm/astro/blog-post-head.renderer.js.map +1 -0
- package/dist/esm/astro/bridge-runtime.d.ts +224 -0
- package/dist/esm/astro/bridge-runtime.d.ts.map +1 -0
- package/dist/esm/astro/bridge-runtime.js +30 -0
- package/dist/esm/astro/bridge-runtime.js.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts +65 -0
- package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -0
- package/dist/esm/astro/collect-expected-label-keys.js +101 -0
- package/dist/esm/astro/collect-expected-label-keys.js.map +1 -0
- package/dist/esm/astro/headers-renderer.d.ts +32 -0
- package/dist/esm/astro/headers-renderer.d.ts.map +1 -0
- package/dist/esm/astro/headers-renderer.js +64 -0
- package/dist/esm/astro/headers-renderer.js.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts +91 -0
- package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -0
- package/dist/esm/astro/i18n-routing.helper.js +23 -0
- package/dist/esm/astro/i18n-routing.helper.js.map +1 -0
- package/dist/esm/astro/internal/html-escape.d.ts +31 -0
- package/dist/esm/astro/internal/html-escape.d.ts.map +1 -0
- package/dist/esm/astro/internal/html-escape.js +40 -0
- package/dist/esm/astro/internal/html-escape.js.map +1 -0
- package/dist/esm/astro/label-pack-loader.d.ts +134 -0
- package/dist/esm/astro/label-pack-loader.d.ts.map +1 -0
- package/dist/esm/astro/label-pack-loader.js +298 -0
- package/dist/esm/astro/label-pack-loader.js.map +1 -0
- package/dist/esm/astro/llms-txt-server.d.ts +28 -0
- package/dist/esm/astro/llms-txt-server.d.ts.map +1 -0
- package/dist/esm/astro/llms-txt-server.js +33 -0
- package/dist/esm/astro/llms-txt-server.js.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts +63 -0
- package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -0
- package/dist/esm/astro/pick-labels-for-page.js +73 -0
- package/dist/esm/astro/pick-labels-for-page.js.map +1 -0
- package/dist/esm/astro/robots-renderer.d.ts +85 -0
- package/dist/esm/astro/robots-renderer.d.ts.map +1 -0
- package/dist/esm/astro/robots-renderer.js +157 -0
- package/dist/esm/astro/robots-renderer.js.map +1 -0
- package/dist/esm/astro/sitemap-coverage.d.ts +101 -0
- package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -0
- package/dist/esm/astro/sitemap-coverage.js +67 -0
- package/dist/esm/astro/sitemap-coverage.js.map +1 -0
- package/dist/esm/astro/structured-data.renderer.d.ts +21 -0
- package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -0
- package/dist/esm/astro/structured-data.renderer.js +142 -0
- package/dist/esm/astro/structured-data.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts +93 -0
- package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -0
- package/dist/esm/astro/website-page-head.renderer.js +184 -0
- package/dist/esm/astro/website-page-head.renderer.js.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts +112 -0
- package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -0
- package/dist/esm/astro/website-page-runtime.helper.js +60 -0
- package/dist/esm/astro/website-page-runtime.helper.js.map +1 -0
- package/dist/esm/astro/website-site-context.d.ts +126 -0
- package/dist/esm/astro/website-site-context.d.ts.map +1 -0
- package/dist/esm/astro/website-site-context.js +37 -0
- package/dist/esm/astro/website-site-context.js.map +1 -0
- package/dist/esm/astro-island.d.ts +56 -0
- package/dist/esm/astro-island.d.ts.map +1 -0
- package/dist/esm/astro-island.js +61 -0
- package/dist/esm/astro-island.js.map +1 -0
- package/dist/esm/astro.d.ts +151 -0
- package/dist/esm/astro.d.ts.map +1 -0
- package/dist/esm/astro.js +151 -0
- package/dist/esm/astro.js.map +1 -0
- package/dist/esm/companion-exports.d.ts +38 -0
- package/dist/esm/companion-exports.d.ts.map +1 -0
- package/dist/esm/companion-exports.js +38 -0
- package/dist/esm/companion-exports.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteButton.js +68 -0
- package/dist/esm/components/low-level/WebsiteButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts +78 -0
- package/dist/esm/components/low-level/WebsiteHeading.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteHeading.js +41 -0
- package/dist/esm/components/low-level/WebsiteHeading.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts +73 -0
- package/dist/esm/components/low-level/WebsiteImage.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteImage.js +21 -0
- package/dist/esm/components/low-level/WebsiteImage.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts +90 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js +47 -0
- package/dist/esm/components/low-level/WebsiteInternalButton.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts +99 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js +68 -0
- package/dist/esm/components/low-level/WebsiteInternalLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts +50 -0
- package/dist/esm/components/low-level/WebsiteLink.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteLink.js +22 -0
- package/dist/esm/components/low-level/WebsiteLink.js.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts +57 -0
- package/dist/esm/components/low-level/WebsiteText.d.ts.map +1 -0
- package/dist/esm/components/low-level/WebsiteText.js +57 -0
- package/dist/esm/components/low-level/WebsiteText.js.map +1 -0
- package/dist/esm/config/define-website-config.d.ts +83 -0
- package/dist/esm/config/define-website-config.d.ts.map +1 -0
- package/dist/esm/config/define-website-config.js +126 -0
- package/dist/esm/config/define-website-config.js.map +1 -0
- package/dist/esm/config/index.d.ts +38 -0
- package/dist/esm/config/index.d.ts.map +1 -0
- package/dist/esm/config/index.js +38 -0
- package/dist/esm/config/index.js.map +1 -0
- package/dist/esm/config/load-website-config.d.ts +136 -0
- package/dist/esm/config/load-website-config.d.ts.map +1 -0
- package/dist/esm/config/load-website-config.js +177 -0
- package/dist/esm/config/load-website-config.js.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts +251 -0
- package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -0
- package/dist/esm/config/wildo-website-config.schemas.js +302 -0
- package/dist/esm/config/wildo-website-config.schemas.js.map +1 -0
- package/dist/esm/config-loader.d.ts +35 -0
- package/dist/esm/config-loader.d.ts.map +1 -0
- package/dist/esm/config-loader.js +35 -0
- package/dist/esm/config-loader.js.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts +38 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js +77 -0
- package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts +41 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js +58 -0
- package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts +81 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js +177 -0
- package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts +40 -0
- package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsitePageContext.js +8 -0
- package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts +162 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js +22 -0
- package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts +47 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js +8 -0
- package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts +13 -0
- package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsitePage.js +22 -0
- package/dist/esm/core/contexts/useWebsitePage.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts +19 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js +28 -0
- package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts +12 -0
- package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/contexts/useWebsiteSection.js +22 -0
- package/dist/esm/core/contexts/useWebsiteSection.js.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts +17 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js +23 -0
- package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts +70 -0
- package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-page-manifest.js +51 -0
- package/dist/esm/core/factories/define-website-page-manifest.js.map +1 -0
- package/dist/esm/core/factories/define-website-section.d.ts +101 -0
- package/dist/esm/core/factories/define-website-section.d.ts.map +1 -0
- package/dist/esm/core/factories/define-website-section.js +71 -0
- package/dist/esm/core/factories/define-website-section.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts +23 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js +25 -0
- package/dist/esm/core/hooks/useWebsiteDesignTokens.js.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts +68 -0
- package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js +103 -0
- package/dist/esm/core/hooks/useWebsiteLabel.js.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts +87 -0
- package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js +170 -0
- package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts +91 -0
- package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -0
- package/dist/esm/core/layouts/WebsiteSection.js +26 -0
- package/dist/esm/core/layouts/WebsiteSection.js.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts +65 -0
- package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -0
- package/dist/esm/core/routing/internal-routing.utils.js +14 -0
- package/dist/esm/core/routing/internal-routing.utils.js.map +1 -0
- package/dist/esm/index.d.ts +129 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +129 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mdx/BlogPost.d.ts +193 -0
- package/dist/esm/mdx/BlogPost.d.ts.map +1 -0
- package/dist/esm/mdx/BlogPost.js +161 -0
- package/dist/esm/mdx/BlogPost.js.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts +139 -0
- package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-collection.config.js +27 -0
- package/dist/esm/mdx/blog-post-collection.config.js.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts +12 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js +13 -0
- package/dist/esm/mdx/blog-post-frontmatter-source.js.map +1 -0
- package/dist/esm/mdx/index.d.ts +22 -0
- package/dist/esm/mdx/index.d.ts.map +1 -0
- package/dist/esm/mdx/index.js +22 -0
- package/dist/esm/mdx/index.js.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts +90 -0
- package/dist/esm/mdx/website-mdx-provider.d.ts.map +1 -0
- package/dist/esm/mdx/website-mdx-provider.js +8 -0
- package/dist/esm/mdx/website-mdx-provider.js.map +1 -0
- package/dist/esm/mdx.d.ts +38 -0
- package/dist/esm/mdx.d.ts.map +1 -0
- package/dist/esm/mdx.js +38 -0
- package/dist/esm/mdx.js.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts +75 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js +85 -0
- package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts +120 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js +152 -0
- package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts +73 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js +76 -0
- package/dist/esm/schemas/label-keys/website-label-key.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +209 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +218 -0
- package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +431 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js +438 -0
- package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts +40 -0
- package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js +43 -0
- package/dist/esm/schemas/refs/page-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts +41 -0
- package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js +44 -0
- package/dist/esm/schemas/refs/section-ref.schemas.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts +63 -0
- package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js +64 -0
- package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +114 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +69 -0
- package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts +100 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js +355 -0
- package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts +58 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js +2 -0
- package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts +144 -0
- package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -0
- package/dist/esm/schemas/validators/label-pack.validator.js +100 -0
- package/dist/esm/schemas/validators/label-pack.validator.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +143 -0
- package/src/__tests__/bundle-isolation.test.ts +607 -0
- package/src/astro/__tests__/blog-post-bridge.test.tsx +288 -0
- package/src/astro/__tests__/blog-post-head.renderer.test.ts +249 -0
- package/src/astro/__tests__/bridge-runtime.test.tsx +198 -0
- package/src/astro/__tests__/collect-expected-label-keys.test.ts +69 -0
- package/src/astro/__tests__/headers-renderer.test.ts +143 -0
- package/src/astro/__tests__/i18n-routing.helper.test.ts +116 -0
- package/src/astro/__tests__/label-pack-loader.test.ts +305 -0
- package/src/astro/__tests__/llms-txt-server.test.ts +127 -0
- package/src/astro/__tests__/pick-labels-for-page.test.ts +60 -0
- package/src/astro/__tests__/robots-renderer.test.ts +228 -0
- package/src/astro/__tests__/sitemap-coverage.test.ts +230 -0
- package/src/astro/__tests__/structured-data.renderer.test.ts +172 -0
- package/src/astro/__tests__/website-page-head.renderer.test.ts +424 -0
- package/src/astro/__tests__/website-page-runtime.helper.test.ts +157 -0
- package/src/astro/__tests__/website-site-context.test.ts +121 -0
- package/src/astro/blog-post-bridge.tsx +404 -0
- package/src/astro/blog-post-head.renderer.ts +293 -0
- package/src/astro/bridge-runtime.tsx +270 -0
- package/src/astro/collect-expected-label-keys.ts +113 -0
- package/src/astro/headers-renderer.ts +82 -0
- package/src/astro/i18n-routing.helper.ts +116 -0
- package/src/astro/internal/html-escape.ts +41 -0
- package/src/astro/label-pack-loader.ts +385 -0
- package/src/astro/llms-txt-server.ts +56 -0
- package/src/astro/pick-labels-for-page.ts +85 -0
- package/src/astro/robots-renderer.ts +171 -0
- package/src/astro/sitemap-coverage.ts +186 -0
- package/src/astro/structured-data.renderer.ts +171 -0
- package/src/astro/website-page-head.renderer.ts +279 -0
- package/src/astro/website-page-runtime.helper.ts +188 -0
- package/src/astro/website-site-context.ts +136 -0
- package/src/astro-island.ts +61 -0
- package/src/astro.ts +151 -0
- package/src/companion-exports.ts +38 -0
- package/src/components/low-level/WebsiteButton.tsx +118 -0
- package/src/components/low-level/WebsiteHeading.tsx +96 -0
- package/src/components/low-level/WebsiteImage.tsx +96 -0
- package/src/components/low-level/WebsiteInternalButton.tsx +172 -0
- package/src/components/low-level/WebsiteInternalLink.tsx +193 -0
- package/src/components/low-level/WebsiteLink.tsx +71 -0
- package/src/components/low-level/WebsiteText.tsx +75 -0
- package/src/components/low-level/__tests__/WebsiteInternalButton.test.tsx +169 -0
- package/src/components/low-level/__tests__/WebsiteInternalLink.test.tsx +202 -0
- package/src/components/low-level/__tests__/primitives.test.tsx +141 -0
- package/src/config/__tests__/define-website-config.test.ts +231 -0
- package/src/config/__tests__/load-website-config.test.ts +215 -0
- package/src/config/define-website-config.ts +134 -0
- package/src/config/index.ts +38 -0
- package/src/config/load-website-config.ts +229 -0
- package/src/config/wildo-website-config.schemas.ts +322 -0
- package/src/config-loader.ts +35 -0
- package/src/core/__tests__/WebsitePageLayout.test.tsx +184 -0
- package/src/core/__tests__/WebsiteSection.test.tsx +85 -0
- package/src/core/__tests__/contexts.test.tsx +133 -0
- package/src/core/__tests__/core-boundary.test.ts +85 -0
- package/src/core/__tests__/define-website-page-manifest.test.tsx +111 -0
- package/src/core/__tests__/define-website-section.test.tsx +89 -0
- package/src/core/__tests__/useWebsiteDesignTokens.test.tsx +41 -0
- package/src/core/__tests__/useWebsiteLabel.test.tsx +117 -0
- package/src/core/anonymous-session/InboundContactForm.tsx +157 -0
- package/src/core/anonymous-session/__tests__/inbound-contact-form.schema.test.ts +44 -0
- package/src/core/anonymous-session/inbound-contact-form.schema.ts +62 -0
- package/src/core/anonymous-session/website-anonymous-session-client.ts +194 -0
- package/src/core/contexts/WebsitePageContext.tsx +52 -0
- package/src/core/contexts/WebsiteRuntimeContext.tsx +175 -0
- package/src/core/contexts/WebsiteSectionContext.tsx +59 -0
- package/src/core/contexts/useWebsitePage.ts +28 -0
- package/src/core/contexts/useWebsiteRuntime.ts +34 -0
- package/src/core/contexts/useWebsiteSection.ts +28 -0
- package/src/core/external-providers/frontend-provider-registry.website.ts +62 -0
- package/src/core/factories/define-website-page-manifest.ts +102 -0
- package/src/core/factories/define-website-section.ts +128 -0
- package/src/core/hooks/useWebsiteDesignTokens.ts +26 -0
- package/src/core/hooks/useWebsiteLabel.ts +121 -0
- package/src/core/layouts/WebsitePageLayout.tsx +311 -0
- package/src/core/layouts/WebsiteSection.tsx +139 -0
- package/src/core/routing/__tests__/internal-routing.utils.test.ts +134 -0
- package/src/core/routing/internal-routing.utils.ts +77 -0
- package/src/index.ts +132 -0
- package/src/mdx/BlogPost.tsx +296 -0
- package/src/mdx/__tests__/BlogPost.test.tsx +218 -0
- package/src/mdx/__tests__/blog-post-collection.config.test.ts +127 -0
- package/src/mdx/__tests__/website-mdx-provider.test.tsx +82 -0
- package/src/mdx/blog-post-collection.config.ts +177 -0
- package/src/mdx/blog-post-frontmatter-source.ts +31 -0
- package/src/mdx/index.ts +39 -0
- package/src/mdx/website-mdx-provider.tsx +95 -0
- package/src/mdx.ts +38 -0
- package/src/schemas/__tests__/blog-frontmatter.test.ts +50 -0
- package/src/schemas/__tests__/companion-exports-react-free.test.ts +51 -0
- package/src/schemas/__tests__/design-tokens.test.ts +163 -0
- package/src/schemas/__tests__/label-key.test.ts +46 -0
- package/src/schemas/__tests__/label-pack-validator.test.ts +146 -0
- package/src/schemas/__tests__/page-manifest.test.ts +66 -0
- package/src/schemas/__tests__/refs.test.ts +37 -0
- package/src/schemas/__tests__/root-config.test.ts +292 -0
- package/src/schemas/__tests__/section-definition.test.ts +47 -0
- package/src/schemas/__tests__/structured-data-reconciliation.test.ts +543 -0
- package/src/schemas/blog/blog-post-frontmatter.shared.schemas.ts +111 -0
- package/src/schemas/design-tokens/website-design-tokens.shared.schemas.ts +166 -0
- package/src/schemas/label-keys/website-label-key.schemas.ts +88 -0
- package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +266 -0
- package/src/schemas/manifests/website-root-config.shared.schemas.ts +504 -0
- package/src/schemas/refs/page-ref.schemas.ts +49 -0
- package/src/schemas/refs/section-ref.schemas.ts +50 -0
- package/src/schemas/sections/website-section-category.shared.ts +65 -0
- package/src/schemas/sections/website-section-definition.shared.schemas.ts +120 -0
- package/src/schemas/structured-data/structured-data-reconciliation.shared.ts +579 -0
- package/src/schemas/structured-data/website-structured-data.shared.schemas.ts +62 -0
- package/src/schemas/validators/label-pack.validator.ts +201 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
export function reconcileStructuredDataAgainstCatalog(options) {
|
|
2
|
+
const findings = [];
|
|
3
|
+
const pages = [];
|
|
4
|
+
const sectionsByRef = new Map(options.sections.map((section) => [section.sectionRef, section]));
|
|
5
|
+
const pagePayloadsByPageRef = new Map();
|
|
6
|
+
for (const pagePayload of options.pagePayloads ?? []) {
|
|
7
|
+
const pagePayloads = pagePayloadsByPageRef.get(pagePayload.pageRef) ?? [];
|
|
8
|
+
pagePayloads.push(pagePayload);
|
|
9
|
+
pagePayloadsByPageRef.set(pagePayload.pageRef, pagePayloads);
|
|
10
|
+
}
|
|
11
|
+
const catalogByType = new Map();
|
|
12
|
+
const catalogCounts = new Map();
|
|
13
|
+
for (const entry of options.catalog) {
|
|
14
|
+
catalogByType.set(entry['@type'], entry);
|
|
15
|
+
catalogCounts.set(entry['@type'], (catalogCounts.get(entry['@type']) ?? 0) + 1);
|
|
16
|
+
}
|
|
17
|
+
for (const [entityType, count] of catalogCounts.entries()) {
|
|
18
|
+
if (count > 1) {
|
|
19
|
+
findings.push({
|
|
20
|
+
kind: 'catalog-override',
|
|
21
|
+
entityType,
|
|
22
|
+
count,
|
|
23
|
+
message: `Merged catalog contains ${count} entries for @type="${entityType}". ` +
|
|
24
|
+
'Replacement semantics are last-wins; duplicate array entries indicate an unresolved override.',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
for (const page of options.pages) {
|
|
29
|
+
const pageFindingStart = findings.length;
|
|
30
|
+
const sectionPayloadContexts = [];
|
|
31
|
+
const isTemplatedRoute = page.routePath.includes('[');
|
|
32
|
+
for (const sectionRef of page.sectionRefs) {
|
|
33
|
+
const section = sectionsByRef.get(sectionRef);
|
|
34
|
+
if (!section) {
|
|
35
|
+
findings.push({
|
|
36
|
+
kind: 'spec-violation',
|
|
37
|
+
code: 'missing-section-definition',
|
|
38
|
+
pageRef: page.ref,
|
|
39
|
+
routePath: page.routePath,
|
|
40
|
+
sectionRef,
|
|
41
|
+
message: `Page "${page.ref}" references sectionRef "${sectionRef}" but no matching section ` +
|
|
42
|
+
'definition was supplied to the structured-data reconciliation harness.',
|
|
43
|
+
});
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (!section.getStructuredData) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const rawStructuredData = section.getStructuredData();
|
|
50
|
+
const normalizedPayloads = normalizeStructuredDataReturn(rawStructuredData);
|
|
51
|
+
if (normalizedPayloads === null) {
|
|
52
|
+
findings.push({
|
|
53
|
+
kind: 'spec-violation',
|
|
54
|
+
code: 'invalid-payload-shape',
|
|
55
|
+
pageRef: page.ref,
|
|
56
|
+
routePath: page.routePath,
|
|
57
|
+
sectionRef,
|
|
58
|
+
message: `Section "${sectionRef}" on page "${page.ref}" returned an invalid ` +
|
|
59
|
+
'`getStructuredData()` shape. Expected object, array, null, or undefined.',
|
|
60
|
+
});
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
for (const candidate of normalizedPayloads) {
|
|
64
|
+
if (!isPlainObject(candidate)) {
|
|
65
|
+
findings.push({
|
|
66
|
+
kind: 'spec-violation',
|
|
67
|
+
code: 'invalid-payload-shape',
|
|
68
|
+
pageRef: page.ref,
|
|
69
|
+
routePath: page.routePath,
|
|
70
|
+
sectionRef,
|
|
71
|
+
message: `Section "${sectionRef}" on page "${page.ref}" returned a non-object structured-data payload.`,
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (typeof candidate['@type'] !== 'string' || candidate['@type'].trim().length === 0) {
|
|
76
|
+
findings.push({
|
|
77
|
+
kind: 'spec-violation',
|
|
78
|
+
code: 'missing-entity-type',
|
|
79
|
+
pageRef: page.ref,
|
|
80
|
+
routePath: page.routePath,
|
|
81
|
+
sectionRef,
|
|
82
|
+
entityId: typeof candidate['@id'] === 'string' ? candidate['@id'] : undefined,
|
|
83
|
+
message: `Section "${sectionRef}" on page "${page.ref}" returned a structured-data payload ` +
|
|
84
|
+
'without a non-empty string `@type`.',
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
sectionPayloadContexts.push({
|
|
89
|
+
pageRef: page.ref,
|
|
90
|
+
routePath: page.routePath,
|
|
91
|
+
sectionRef,
|
|
92
|
+
payload: candidate,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const contextsByRoutePath = new Map();
|
|
97
|
+
const collectionFindingCountByRoutePath = new Map();
|
|
98
|
+
const pagePayloadsForPage = pagePayloadsByPageRef.get(page.ref) ?? [];
|
|
99
|
+
pagePayloadsByPageRef.delete(page.ref);
|
|
100
|
+
const shouldEmitManifestResult = (sectionPayloadContexts.length > 0 && (!isTemplatedRoute || pagePayloadsForPage.length === 0))
|
|
101
|
+
|| findings.length > pageFindingStart
|
|
102
|
+
|| pagePayloadsForPage.length === 0;
|
|
103
|
+
if (shouldEmitManifestResult) {
|
|
104
|
+
const manifestPayloadContexts = isTemplatedRoute && pagePayloadsForPage.length > 0
|
|
105
|
+
? []
|
|
106
|
+
: [...sectionPayloadContexts];
|
|
107
|
+
contextsByRoutePath.set(page.routePath, manifestPayloadContexts);
|
|
108
|
+
collectionFindingCountByRoutePath.set(page.routePath, findings.length - pageFindingStart);
|
|
109
|
+
}
|
|
110
|
+
for (const pagePayload of pagePayloadsForPage) {
|
|
111
|
+
const routePath = pagePayload.routePath ?? page.routePath;
|
|
112
|
+
const payloadContexts = contextsByRoutePath.get(routePath) ?? [];
|
|
113
|
+
if (payloadContexts.length === 0
|
|
114
|
+
&& isTemplatedRoute
|
|
115
|
+
&& sectionPayloadContexts.length > 0) {
|
|
116
|
+
payloadContexts.push(...sectionPayloadContexts.map((context) => ({
|
|
117
|
+
...context,
|
|
118
|
+
routePath,
|
|
119
|
+
})));
|
|
120
|
+
}
|
|
121
|
+
contextsByRoutePath.set(routePath, payloadContexts);
|
|
122
|
+
const collectionFindingStart = findings.length;
|
|
123
|
+
collectNormalizedPayloadContexts({
|
|
124
|
+
rawStructuredData: pagePayload.payloads,
|
|
125
|
+
pageRef: page.ref,
|
|
126
|
+
routePath,
|
|
127
|
+
sectionRef: pagePayload.sourceRef ?? `page:${page.ref}`,
|
|
128
|
+
findings,
|
|
129
|
+
into: payloadContexts,
|
|
130
|
+
});
|
|
131
|
+
collectionFindingCountByRoutePath.set(routePath, (collectionFindingCountByRoutePath.get(routePath) ?? 0)
|
|
132
|
+
+ findings.length - collectionFindingStart);
|
|
133
|
+
}
|
|
134
|
+
for (const [routePath, payloadContexts] of contextsByRoutePath.entries()) {
|
|
135
|
+
const declaredEntityIds = new Set();
|
|
136
|
+
for (const payloadContext of payloadContexts) {
|
|
137
|
+
collectDeclaredEntityIds(payloadContext.payload, declaredEntityIds);
|
|
138
|
+
}
|
|
139
|
+
const routeFindingStart = findings.length;
|
|
140
|
+
for (const payloadContext of payloadContexts) {
|
|
141
|
+
validatePayloadAgainstCatalog(payloadContext, catalogByType, declaredEntityIds, findings);
|
|
142
|
+
}
|
|
143
|
+
pages.push({
|
|
144
|
+
pageRef: page.ref,
|
|
145
|
+
routePath,
|
|
146
|
+
payloadCount: payloadContexts.length,
|
|
147
|
+
findingCount: (collectionFindingCountByRoutePath.get(routePath) ?? 0)
|
|
148
|
+
+ findings.length - routeFindingStart,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const [pageRef, pagePayloads] of pagePayloadsByPageRef.entries()) {
|
|
153
|
+
for (const pagePayload of pagePayloads) {
|
|
154
|
+
findings.push({
|
|
155
|
+
kind: 'spec-violation',
|
|
156
|
+
code: 'orphan-page-payload',
|
|
157
|
+
pageRef,
|
|
158
|
+
routePath: pagePayload.routePath ?? '',
|
|
159
|
+
sectionRef: pagePayload.sourceRef ?? `page:${pageRef}`,
|
|
160
|
+
message: `Structured-data page payload "${pagePayload.sourceRef ?? `page:${pageRef}`}" ` +
|
|
161
|
+
`references pageRef "${pageRef}" but no matching page manifest was supplied.`,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
findings,
|
|
167
|
+
pages,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function collectNormalizedPayloadContexts(input) {
|
|
171
|
+
const { rawStructuredData, pageRef, routePath, sectionRef, findings, into, } = input;
|
|
172
|
+
const normalizedPayloads = normalizeStructuredDataReturn(rawStructuredData);
|
|
173
|
+
if (normalizedPayloads === null) {
|
|
174
|
+
findings.push({
|
|
175
|
+
kind: 'spec-violation',
|
|
176
|
+
code: 'invalid-payload-shape',
|
|
177
|
+
pageRef,
|
|
178
|
+
routePath,
|
|
179
|
+
sectionRef,
|
|
180
|
+
message: `Structured-data source "${sectionRef}" on page "${pageRef}" returned an invalid ` +
|
|
181
|
+
'structured-data shape. Expected object, array, null, or undefined.',
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
for (const candidate of normalizedPayloads) {
|
|
186
|
+
if (!isPlainObject(candidate)) {
|
|
187
|
+
findings.push({
|
|
188
|
+
kind: 'spec-violation',
|
|
189
|
+
code: 'invalid-payload-shape',
|
|
190
|
+
pageRef,
|
|
191
|
+
routePath,
|
|
192
|
+
sectionRef,
|
|
193
|
+
message: `Structured-data source "${sectionRef}" on page "${pageRef}" returned a non-object structured-data payload.`,
|
|
194
|
+
});
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (typeof candidate['@type'] !== 'string' || candidate['@type'].trim().length === 0) {
|
|
198
|
+
findings.push({
|
|
199
|
+
kind: 'spec-violation',
|
|
200
|
+
code: 'missing-entity-type',
|
|
201
|
+
pageRef,
|
|
202
|
+
routePath,
|
|
203
|
+
sectionRef,
|
|
204
|
+
entityId: typeof candidate['@id'] === 'string' ? candidate['@id'] : undefined,
|
|
205
|
+
message: `Structured-data source "${sectionRef}" on page "${pageRef}" returned a structured-data payload ` +
|
|
206
|
+
'without a non-empty string `@type`.',
|
|
207
|
+
});
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
into.push({
|
|
211
|
+
pageRef,
|
|
212
|
+
routePath,
|
|
213
|
+
sectionRef,
|
|
214
|
+
payload: candidate,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function validatePayloadAgainstCatalog(payloadContext, catalogByType, declaredEntityIds, findings) {
|
|
219
|
+
const { payload, pageRef, routePath, sectionRef } = payloadContext;
|
|
220
|
+
const entityType = payload['@type'];
|
|
221
|
+
const entityId = typeof payload['@id'] === 'string' ? payload['@id'] : undefined;
|
|
222
|
+
const catalogEntry = catalogByType.get(entityType);
|
|
223
|
+
if (!catalogEntry) {
|
|
224
|
+
findings.push({
|
|
225
|
+
kind: 'catalog-miss',
|
|
226
|
+
pageRef,
|
|
227
|
+
routePath,
|
|
228
|
+
sectionRef,
|
|
229
|
+
entityType,
|
|
230
|
+
entityId,
|
|
231
|
+
message: `Structured-data payload @type="${entityType}" emitted by section "${sectionRef}" ` +
|
|
232
|
+
`on page "${pageRef}" does not exist in the merged catalog.`,
|
|
233
|
+
});
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
for (const requiredField of catalogEntry.requiredFields) {
|
|
237
|
+
if (!hasPresentFieldValue(payload, requiredField)) {
|
|
238
|
+
findings.push({
|
|
239
|
+
kind: 'spec-violation',
|
|
240
|
+
code: 'missing-required-field',
|
|
241
|
+
pageRef,
|
|
242
|
+
routePath,
|
|
243
|
+
sectionRef,
|
|
244
|
+
entityType,
|
|
245
|
+
entityId,
|
|
246
|
+
field: requiredField,
|
|
247
|
+
message: `Structured-data payload @type="${entityType}" emitted by section "${sectionRef}" ` +
|
|
248
|
+
`on page "${pageRef}" is missing required field "${requiredField}".`,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
for (const deprecatedField of catalogEntry.deprecatedFields ?? []) {
|
|
253
|
+
if (!hasPresentFieldValue(payload, deprecatedField.field)) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
findings.push({
|
|
257
|
+
kind: 'deprecated-field',
|
|
258
|
+
pageRef,
|
|
259
|
+
routePath,
|
|
260
|
+
sectionRef,
|
|
261
|
+
entityType,
|
|
262
|
+
entityId,
|
|
263
|
+
field: deprecatedField.field,
|
|
264
|
+
replacedBy: deprecatedField.replacedBy,
|
|
265
|
+
deprecatedSince: deprecatedField.deprecatedSince,
|
|
266
|
+
message: deprecatedField.replacedBy === null
|
|
267
|
+
? `Structured-data payload @type="${entityType}" emitted by section "${sectionRef}" ` +
|
|
268
|
+
`on page "${pageRef}" uses deprecated field "${deprecatedField.field}" ` +
|
|
269
|
+
`(deprecated since ${deprecatedField.deprecatedSince}).`
|
|
270
|
+
: `Structured-data payload @type="${entityType}" emitted by section "${sectionRef}" ` +
|
|
271
|
+
`on page "${pageRef}" uses deprecated field "${deprecatedField.field}". ` +
|
|
272
|
+
`Use "${deprecatedField.replacedBy}" instead ` +
|
|
273
|
+
`(deprecated since ${deprecatedField.deprecatedSince}).`,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
const referencedIds = new Set();
|
|
277
|
+
collectReferencedEntityIds(payload, referencedIds, true);
|
|
278
|
+
for (const referencedId of referencedIds) {
|
|
279
|
+
if (declaredEntityIds.has(referencedId)) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
findings.push({
|
|
283
|
+
kind: 'cross-entity-reference-drift',
|
|
284
|
+
pageRef,
|
|
285
|
+
routePath,
|
|
286
|
+
sectionRef,
|
|
287
|
+
entityType,
|
|
288
|
+
entityId,
|
|
289
|
+
missingReferenceId: referencedId,
|
|
290
|
+
message: `Structured-data payload @type="${entityType}" emitted by section "${sectionRef}" ` +
|
|
291
|
+
`on page "${pageRef}" references @id "${referencedId}" but no emitted entity on the page defines it.`,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function normalizeStructuredDataReturn(value) {
|
|
296
|
+
if (value === null || value === undefined) {
|
|
297
|
+
return [];
|
|
298
|
+
}
|
|
299
|
+
if (Array.isArray(value)) {
|
|
300
|
+
return value.filter((item) => item !== null && item !== undefined);
|
|
301
|
+
}
|
|
302
|
+
if (isPlainObject(value)) {
|
|
303
|
+
return [value];
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
function hasPresentFieldValue(payload, fieldName) {
|
|
308
|
+
if (!Object.prototype.hasOwnProperty.call(payload, fieldName)) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
const value = payload[fieldName];
|
|
312
|
+
return value !== null && value !== undefined;
|
|
313
|
+
}
|
|
314
|
+
function collectDeclaredEntityIds(value, into) {
|
|
315
|
+
if (Array.isArray(value)) {
|
|
316
|
+
for (const item of value) {
|
|
317
|
+
collectDeclaredEntityIds(item, into);
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (!isPlainObject(value)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const entityId = typeof value['@id'] === 'string' ? value['@id'] : null;
|
|
325
|
+
const entityType = typeof value['@type'] === 'string' ? value['@type'] : null;
|
|
326
|
+
if (entityId && entityType) {
|
|
327
|
+
into.add(entityId);
|
|
328
|
+
}
|
|
329
|
+
for (const child of Object.values(value)) {
|
|
330
|
+
collectDeclaredEntityIds(child, into);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function collectReferencedEntityIds(value, into, isRootPayload) {
|
|
334
|
+
if (Array.isArray(value)) {
|
|
335
|
+
for (const item of value) {
|
|
336
|
+
collectReferencedEntityIds(item, into, false);
|
|
337
|
+
}
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (!isPlainObject(value)) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const entityId = typeof value['@id'] === 'string' ? value['@id'] : null;
|
|
344
|
+
const entityType = typeof value['@type'] === 'string' ? value['@type'] : null;
|
|
345
|
+
if (!isRootPayload && entityId && !entityType) {
|
|
346
|
+
into.add(entityId);
|
|
347
|
+
}
|
|
348
|
+
for (const child of Object.values(value)) {
|
|
349
|
+
collectReferencedEntityIds(child, into, false);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function isPlainObject(value) {
|
|
353
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=structured-data-reconciliation.shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-data-reconciliation.shared.js","sourceRoot":"","sources":["../../../../../src/schemas/structured-data/structured-data-reconciliation.shared.ts"],"names":[],"mappings":"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","sourcesContent":["export interface StructuredDataDeprecatedField {\n field: string;\n replacedBy: string | null;\n deprecatedSince: string;\n}\n\nexport interface StructuredDataCatalogEntry {\n '@type': string;\n requiredFields: readonly string[];\n optionalFields?: readonly string[];\n deprecatedFields?: readonly StructuredDataDeprecatedField[];\n recommendOptionals?: boolean;\n}\n\nexport interface StructuredDataPayload {\n '@type': string;\n '@id'?: string;\n [key: string]: unknown;\n}\n\nexport interface StructuredDataSectionDefinitionLike {\n sectionRef: string;\n getStructuredData?: () => unknown;\n}\n\nexport interface StructuredDataPageManifestLike {\n ref: string;\n routePath: string;\n sectionRefs: readonly string[];\n}\n\nexport interface StructuredDataPagePayloadLike {\n pageRef: string;\n routePath?: string;\n sourceRef?: string;\n payloads: unknown;\n}\n\nexport type StructuredDataSpecViolationCode =\n | 'invalid-payload-shape'\n | 'missing-entity-type'\n | 'missing-required-field'\n | 'missing-section-definition'\n | 'orphan-page-payload';\n\nexport interface StructuredDataCatalogOverrideFinding {\n kind: 'catalog-override';\n entityType: string;\n count: number;\n message: string;\n}\n\nexport interface StructuredDataCatalogMissFinding {\n kind: 'catalog-miss';\n pageRef: string;\n routePath: string;\n sectionRef: string;\n entityType: string;\n entityId?: string;\n message: string;\n}\n\nexport interface StructuredDataSpecViolationFinding {\n kind: 'spec-violation';\n code: StructuredDataSpecViolationCode;\n pageRef: string;\n routePath: string;\n sectionRef: string;\n entityType?: string;\n entityId?: string;\n field?: string;\n message: string;\n}\n\nexport interface StructuredDataDeprecatedFieldFinding {\n kind: 'deprecated-field';\n pageRef: string;\n routePath: string;\n sectionRef: string;\n entityType: string;\n entityId?: string;\n field: string;\n replacedBy: string | null;\n deprecatedSince: string;\n message: string;\n}\n\nexport interface StructuredDataCrossEntityReferenceDriftFinding {\n kind: 'cross-entity-reference-drift';\n pageRef: string;\n routePath: string;\n sectionRef: string;\n entityType: string;\n entityId?: string;\n missingReferenceId: string;\n message: string;\n}\n\nexport type StructuredDataReconciliationFinding =\n | StructuredDataCatalogOverrideFinding\n | StructuredDataCatalogMissFinding\n | StructuredDataSpecViolationFinding\n | StructuredDataDeprecatedFieldFinding\n | StructuredDataCrossEntityReferenceDriftFinding;\n\nexport interface StructuredDataReconciliationPageResult {\n pageRef: string;\n routePath: string;\n payloadCount: number;\n findingCount: number;\n}\n\nexport interface StructuredDataReconciliationResult {\n findings: StructuredDataReconciliationFinding[];\n pages: StructuredDataReconciliationPageResult[];\n}\n\nexport interface ReconcileStructuredDataOptions {\n catalog: readonly StructuredDataCatalogEntry[];\n pages: readonly StructuredDataPageManifestLike[];\n sections: readonly StructuredDataSectionDefinitionLike[];\n pagePayloads?: readonly StructuredDataPagePayloadLike[];\n}\n\ninterface ReconciliationPayloadContext {\n pageRef: string;\n routePath: string;\n sectionRef: string;\n payload: StructuredDataPayload;\n}\n\nexport function reconcileStructuredDataAgainstCatalog(\n options: ReconcileStructuredDataOptions,\n): StructuredDataReconciliationResult {\n const findings: StructuredDataReconciliationFinding[] = [];\n const pages: StructuredDataReconciliationPageResult[] = [];\n const sectionsByRef = new Map(\n options.sections.map((section) => [section.sectionRef, section] as const),\n );\n const pagePayloadsByPageRef = new Map<string, StructuredDataPagePayloadLike[]>();\n for (const pagePayload of options.pagePayloads ?? []) {\n const pagePayloads = pagePayloadsByPageRef.get(pagePayload.pageRef) ?? [];\n pagePayloads.push(pagePayload);\n pagePayloadsByPageRef.set(pagePayload.pageRef, pagePayloads);\n }\n const catalogByType = new Map<string, StructuredDataCatalogEntry>();\n const catalogCounts = new Map<string, number>();\n\n for (const entry of options.catalog) {\n catalogByType.set(entry['@type'], entry);\n catalogCounts.set(entry['@type'], (catalogCounts.get(entry['@type']) ?? 0) + 1);\n }\n\n for (const [entityType, count] of catalogCounts.entries()) {\n if (count > 1) {\n findings.push({\n kind: 'catalog-override',\n entityType,\n count,\n message:\n `Merged catalog contains ${count} entries for @type=\"${entityType}\". ` +\n 'Replacement semantics are last-wins; duplicate array entries indicate an unresolved override.',\n });\n }\n }\n\n for (const page of options.pages) {\n const pageFindingStart = findings.length;\n const sectionPayloadContexts: ReconciliationPayloadContext[] = [];\n const isTemplatedRoute = page.routePath.includes('[');\n\n for (const sectionRef of page.sectionRefs) {\n const section = sectionsByRef.get(sectionRef);\n if (!section) {\n findings.push({\n kind: 'spec-violation',\n code: 'missing-section-definition',\n pageRef: page.ref,\n routePath: page.routePath,\n sectionRef,\n message:\n `Page \"${page.ref}\" references sectionRef \"${sectionRef}\" but no matching section ` +\n 'definition was supplied to the structured-data reconciliation harness.',\n });\n continue;\n }\n\n if (!section.getStructuredData) {\n continue;\n }\n\n const rawStructuredData = section.getStructuredData();\n const normalizedPayloads = normalizeStructuredDataReturn(rawStructuredData);\n\n if (normalizedPayloads === null) {\n findings.push({\n kind: 'spec-violation',\n code: 'invalid-payload-shape',\n pageRef: page.ref,\n routePath: page.routePath,\n sectionRef,\n message:\n `Section \"${sectionRef}\" on page \"${page.ref}\" returned an invalid ` +\n '`getStructuredData()` shape. Expected object, array, null, or undefined.',\n });\n continue;\n }\n\n for (const candidate of normalizedPayloads) {\n if (!isPlainObject(candidate)) {\n findings.push({\n kind: 'spec-violation',\n code: 'invalid-payload-shape',\n pageRef: page.ref,\n routePath: page.routePath,\n sectionRef,\n message:\n `Section \"${sectionRef}\" on page \"${page.ref}\" returned a non-object structured-data payload.`,\n });\n continue;\n }\n\n if (typeof candidate['@type'] !== 'string' || candidate['@type'].trim().length === 0) {\n findings.push({\n kind: 'spec-violation',\n code: 'missing-entity-type',\n pageRef: page.ref,\n routePath: page.routePath,\n sectionRef,\n entityId: typeof candidate['@id'] === 'string' ? candidate['@id'] : undefined,\n message:\n `Section \"${sectionRef}\" on page \"${page.ref}\" returned a structured-data payload ` +\n 'without a non-empty string `@type`.',\n });\n continue;\n }\n\n sectionPayloadContexts.push({\n pageRef: page.ref,\n routePath: page.routePath,\n sectionRef,\n payload: candidate as StructuredDataPayload,\n });\n }\n }\n\n const contextsByRoutePath = new Map<string, ReconciliationPayloadContext[]>();\n const collectionFindingCountByRoutePath = new Map<string, number>();\n const pagePayloadsForPage = pagePayloadsByPageRef.get(page.ref) ?? [];\n pagePayloadsByPageRef.delete(page.ref);\n const shouldEmitManifestResult =\n (sectionPayloadContexts.length > 0 && (!isTemplatedRoute || pagePayloadsForPage.length === 0))\n || findings.length > pageFindingStart\n || pagePayloadsForPage.length === 0;\n if (shouldEmitManifestResult) {\n const manifestPayloadContexts =\n isTemplatedRoute && pagePayloadsForPage.length > 0\n ? []\n : [...sectionPayloadContexts];\n contextsByRoutePath.set(page.routePath, manifestPayloadContexts);\n collectionFindingCountByRoutePath.set(page.routePath, findings.length - pageFindingStart);\n }\n\n for (const pagePayload of pagePayloadsForPage) {\n const routePath = pagePayload.routePath ?? page.routePath;\n const payloadContexts = contextsByRoutePath.get(routePath) ?? [];\n if (\n payloadContexts.length === 0\n && isTemplatedRoute\n && sectionPayloadContexts.length > 0\n ) {\n payloadContexts.push(\n ...sectionPayloadContexts.map((context) => ({\n ...context,\n routePath,\n })),\n );\n }\n contextsByRoutePath.set(routePath, payloadContexts);\n const collectionFindingStart = findings.length;\n collectNormalizedPayloadContexts({\n rawStructuredData: pagePayload.payloads,\n pageRef: page.ref,\n routePath,\n sectionRef: pagePayload.sourceRef ?? `page:${page.ref}`,\n findings,\n into: payloadContexts,\n });\n collectionFindingCountByRoutePath.set(\n routePath,\n (collectionFindingCountByRoutePath.get(routePath) ?? 0)\n + findings.length - collectionFindingStart,\n );\n }\n\n for (const [routePath, payloadContexts] of contextsByRoutePath.entries()) {\n const declaredEntityIds = new Set<string>();\n for (const payloadContext of payloadContexts) {\n collectDeclaredEntityIds(payloadContext.payload, declaredEntityIds);\n }\n\n const routeFindingStart = findings.length;\n for (const payloadContext of payloadContexts) {\n validatePayloadAgainstCatalog(payloadContext, catalogByType, declaredEntityIds, findings);\n }\n\n pages.push({\n pageRef: page.ref,\n routePath,\n payloadCount: payloadContexts.length,\n findingCount:\n (collectionFindingCountByRoutePath.get(routePath) ?? 0)\n + findings.length - routeFindingStart,\n });\n }\n }\n\n for (const [pageRef, pagePayloads] of pagePayloadsByPageRef.entries()) {\n for (const pagePayload of pagePayloads) {\n findings.push({\n kind: 'spec-violation',\n code: 'orphan-page-payload',\n pageRef,\n routePath: pagePayload.routePath ?? '',\n sectionRef: pagePayload.sourceRef ?? `page:${pageRef}`,\n message:\n `Structured-data page payload \"${pagePayload.sourceRef ?? `page:${pageRef}`}\" ` +\n `references pageRef \"${pageRef}\" but no matching page manifest was supplied.`,\n });\n }\n }\n\n return {\n findings,\n pages,\n };\n}\n\nfunction collectNormalizedPayloadContexts(input: {\n rawStructuredData: unknown;\n pageRef: string;\n routePath: string;\n sectionRef: string;\n findings: StructuredDataReconciliationFinding[];\n into: ReconciliationPayloadContext[];\n}): void {\n const {\n rawStructuredData,\n pageRef,\n routePath,\n sectionRef,\n findings,\n into,\n } = input;\n const normalizedPayloads = normalizeStructuredDataReturn(rawStructuredData);\n\n if (normalizedPayloads === null) {\n findings.push({\n kind: 'spec-violation',\n code: 'invalid-payload-shape',\n pageRef,\n routePath,\n sectionRef,\n message:\n `Structured-data source \"${sectionRef}\" on page \"${pageRef}\" returned an invalid ` +\n 'structured-data shape. Expected object, array, null, or undefined.',\n });\n return;\n }\n\n for (const candidate of normalizedPayloads) {\n if (!isPlainObject(candidate)) {\n findings.push({\n kind: 'spec-violation',\n code: 'invalid-payload-shape',\n pageRef,\n routePath,\n sectionRef,\n message:\n `Structured-data source \"${sectionRef}\" on page \"${pageRef}\" returned a non-object structured-data payload.`,\n });\n continue;\n }\n\n if (typeof candidate['@type'] !== 'string' || candidate['@type'].trim().length === 0) {\n findings.push({\n kind: 'spec-violation',\n code: 'missing-entity-type',\n pageRef,\n routePath,\n sectionRef,\n entityId: typeof candidate['@id'] === 'string' ? candidate['@id'] : undefined,\n message:\n `Structured-data source \"${sectionRef}\" on page \"${pageRef}\" returned a structured-data payload ` +\n 'without a non-empty string `@type`.',\n });\n continue;\n }\n\n into.push({\n pageRef,\n routePath,\n sectionRef,\n payload: candidate as StructuredDataPayload,\n });\n }\n}\n\nfunction validatePayloadAgainstCatalog(\n payloadContext: ReconciliationPayloadContext,\n catalogByType: ReadonlyMap<string, StructuredDataCatalogEntry>,\n declaredEntityIds: ReadonlySet<string>,\n findings: StructuredDataReconciliationFinding[],\n): void {\n const { payload, pageRef, routePath, sectionRef } = payloadContext;\n const entityType = payload['@type'];\n const entityId = typeof payload['@id'] === 'string' ? payload['@id'] : undefined;\n const catalogEntry = catalogByType.get(entityType);\n\n if (!catalogEntry) {\n findings.push({\n kind: 'catalog-miss',\n pageRef,\n routePath,\n sectionRef,\n entityType,\n entityId,\n message:\n `Structured-data payload @type=\"${entityType}\" emitted by section \"${sectionRef}\" ` +\n `on page \"${pageRef}\" does not exist in the merged catalog.`,\n });\n return;\n }\n\n for (const requiredField of catalogEntry.requiredFields) {\n if (!hasPresentFieldValue(payload, requiredField)) {\n findings.push({\n kind: 'spec-violation',\n code: 'missing-required-field',\n pageRef,\n routePath,\n sectionRef,\n entityType,\n entityId,\n field: requiredField,\n message:\n `Structured-data payload @type=\"${entityType}\" emitted by section \"${sectionRef}\" ` +\n `on page \"${pageRef}\" is missing required field \"${requiredField}\".`,\n });\n }\n }\n\n for (const deprecatedField of catalogEntry.deprecatedFields ?? []) {\n if (!hasPresentFieldValue(payload, deprecatedField.field)) {\n continue;\n }\n\n findings.push({\n kind: 'deprecated-field',\n pageRef,\n routePath,\n sectionRef,\n entityType,\n entityId,\n field: deprecatedField.field,\n replacedBy: deprecatedField.replacedBy,\n deprecatedSince: deprecatedField.deprecatedSince,\n message:\n deprecatedField.replacedBy === null\n ? `Structured-data payload @type=\"${entityType}\" emitted by section \"${sectionRef}\" ` +\n `on page \"${pageRef}\" uses deprecated field \"${deprecatedField.field}\" ` +\n `(deprecated since ${deprecatedField.deprecatedSince}).`\n : `Structured-data payload @type=\"${entityType}\" emitted by section \"${sectionRef}\" ` +\n `on page \"${pageRef}\" uses deprecated field \"${deprecatedField.field}\". ` +\n `Use \"${deprecatedField.replacedBy}\" instead ` +\n `(deprecated since ${deprecatedField.deprecatedSince}).`,\n });\n }\n\n const referencedIds = new Set<string>();\n collectReferencedEntityIds(payload, referencedIds, true);\n for (const referencedId of referencedIds) {\n if (declaredEntityIds.has(referencedId)) {\n continue;\n }\n\n findings.push({\n kind: 'cross-entity-reference-drift',\n pageRef,\n routePath,\n sectionRef,\n entityType,\n entityId,\n missingReferenceId: referencedId,\n message:\n `Structured-data payload @type=\"${entityType}\" emitted by section \"${sectionRef}\" ` +\n `on page \"${pageRef}\" references @id \"${referencedId}\" but no emitted entity on the page defines it.`,\n });\n }\n}\n\nfunction normalizeStructuredDataReturn(value: unknown): unknown[] | null {\n if (value === null || value === undefined) {\n return [];\n }\n\n if (Array.isArray(value)) {\n return value.filter((item) => item !== null && item !== undefined);\n }\n\n if (isPlainObject(value)) {\n return [value];\n }\n\n return null;\n}\n\nfunction hasPresentFieldValue(payload: StructuredDataPayload, fieldName: string): boolean {\n if (!Object.prototype.hasOwnProperty.call(payload, fieldName)) {\n return false;\n }\n\n const value = payload[fieldName];\n return value !== null && value !== undefined;\n}\n\nfunction collectDeclaredEntityIds(value: unknown, into: Set<string>): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n collectDeclaredEntityIds(item, into);\n }\n return;\n }\n\n if (!isPlainObject(value)) {\n return;\n }\n\n const entityId = typeof value['@id'] === 'string' ? value['@id'] : null;\n const entityType = typeof value['@type'] === 'string' ? value['@type'] : null;\n if (entityId && entityType) {\n into.add(entityId);\n }\n\n for (const child of Object.values(value)) {\n collectDeclaredEntityIds(child, into);\n }\n}\n\nfunction collectReferencedEntityIds(\n value: unknown,\n into: Set<string>,\n isRootPayload: boolean,\n): void {\n if (Array.isArray(value)) {\n for (const item of value) {\n collectReferencedEntityIds(item, into, false);\n }\n return;\n }\n\n if (!isPlainObject(value)) {\n return;\n }\n\n const entityId = typeof value['@id'] === 'string' ? value['@id'] : null;\n const entityType = typeof value['@type'] === 'string' ? value['@type'] : null;\n if (!isRootPayload && entityId && !entityType) {\n into.add(entityId);\n }\n\n for (const child of Object.values(value)) {\n collectReferencedEntityIds(child, into, false);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @wildo_source:part:start saas.website.structured-data.payload-shape facet:layer:shared facet:family:website
|
|
3
|
+
*
|
|
4
|
+
* `WebsiteStructuredDataPayload` — the runtime JSON-LD object shape returned
|
|
5
|
+
* by a section's `getStructuredData()` and serialized into one
|
|
6
|
+
* `<script type="application/ld+json">` block per payload.
|
|
7
|
+
*
|
|
8
|
+
* **Layering note** — the payload type is defined HERE (in the
|
|
9
|
+
* website runtime) rather than imported from the specification package because
|
|
10
|
+
* runtime rendering must remain independent from companion semantics. The
|
|
11
|
+
* application's Schema.org catalog describes the same vocabulary (per-`@type`
|
|
12
|
+
* required / optional / deprecated fields); the two contracts are structurally
|
|
13
|
+
* compatible by design but independently owned.
|
|
14
|
+
*
|
|
15
|
+
* **Authoring contract**:
|
|
16
|
+
*
|
|
17
|
+
* - `@type` REQUIRED — the Schema.org entity kind (`'Article'`,
|
|
18
|
+
* `'BlogPosting'`, `'FAQPage'`, …). Typed as a free-form `string`
|
|
19
|
+
* here (not a closed enum) so app-side catalog extensions
|
|
20
|
+
* (e.g. `'SoftwareApplication'`, custom Schema.org-extension
|
|
21
|
+
* `@type`s) are emittable without a saas-website release. The
|
|
22
|
+
* companion's catalog reconciliation surface validates the
|
|
23
|
+
* `@type` value against the merged engine + app catalog.
|
|
24
|
+
* - `@id?` OPTIONAL — a stable URI identifying the entity. Used for
|
|
25
|
+
* cross-referencing on the same page (e.g. `Article.publisher`
|
|
26
|
+
* referencing the page-level `Organization` via `@id`). The
|
|
27
|
+
* renderer uses `@id` for deduplication: two payloads with the
|
|
28
|
+
* same `@id` collapse into one emitted block (last-wins).
|
|
29
|
+
* - `@context?` OPTIONAL — the JSON-LD vocabulary URL. The renderer
|
|
30
|
+
* auto-injects `'https://schema.org'` when omitted; the field is
|
|
31
|
+
* exposed so consumers CAN override (Schema.org payload extended
|
|
32
|
+
* with a custom vocabulary).
|
|
33
|
+
* - All other fields are pass-through `unknown` — the catalog
|
|
34
|
+
* describes the FIELD NAMES per `@type`; the per-field SHAPE
|
|
35
|
+
* (e.g. `Article.author` is a `Person | Organization`) is locked
|
|
36
|
+
* at the section's payload-builder TS-side.
|
|
37
|
+
*/
|
|
38
|
+
export interface WebsiteStructuredDataPayload {
|
|
39
|
+
'@type': string;
|
|
40
|
+
'@id'?: string;
|
|
41
|
+
'@context'?: string | Record<string, unknown>;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Convenience union for `getStructuredData()` return types.
|
|
46
|
+
*
|
|
47
|
+
* A section may emit:
|
|
48
|
+
* - a single payload (most common — `FAQPage` for an FAQ section);
|
|
49
|
+
* - a fixed-length tuple of payloads (e.g. pricing emits `Product +
|
|
50
|
+
* AggregateOffer` together);
|
|
51
|
+
* - `null` / `undefined` when the section has no contribution for
|
|
52
|
+
* the current state (e.g. an empty FAQ list);
|
|
53
|
+
* - an empty array (semantically equivalent to `null`; the renderer
|
|
54
|
+
* short-circuits both).
|
|
55
|
+
*/
|
|
56
|
+
export type WebsiteStructuredDataReturn = WebsiteStructuredDataPayload | readonly WebsiteStructuredDataPayload[] | null | undefined;
|
|
57
|
+
/** @wildo_source:part:end saas.website.structured-data.payload-shape */
|
|
58
|
+
//# sourceMappingURL=website-structured-data.shared.schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"website-structured-data.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../../src/schemas/structured-data/website-structured-data.shared.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,2BAA2B,GACnC,4BAA4B,GAC5B,SAAS,4BAA4B,EAAE,GACvC,IAAI,GACJ,SAAS,CAAC;AACd,wEAAwE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"website-structured-data.shared.schemas.js","sourceRoot":"","sources":["../../../../../src/schemas/structured-data/website-structured-data.shared.schemas.ts"],"names":[],"mappings":"AA6DA,wEAAwE","sourcesContent":["/**\n * @wildo_source:part:start saas.website.structured-data.payload-shape facet:layer:shared facet:family:website\n *\n * `WebsiteStructuredDataPayload` — the runtime JSON-LD object shape returned\n * by a section's `getStructuredData()` and serialized into one\n * `<script type=\"application/ld+json\">` block per payload.\n *\n * **Layering note** — the payload type is defined HERE (in the\n * website runtime) rather than imported from the specification package because\n * runtime rendering must remain independent from companion semantics. The\n * application's Schema.org catalog describes the same vocabulary (per-`@type`\n * required / optional / deprecated fields); the two contracts are structurally\n * compatible by design but independently owned.\n *\n * **Authoring contract**:\n *\n * - `@type` REQUIRED — the Schema.org entity kind (`'Article'`,\n * `'BlogPosting'`, `'FAQPage'`, …). Typed as a free-form `string`\n * here (not a closed enum) so app-side catalog extensions\n * (e.g. `'SoftwareApplication'`, custom Schema.org-extension\n * `@type`s) are emittable without a saas-website release. The\n * companion's catalog reconciliation surface validates the\n * `@type` value against the merged engine + app catalog.\n * - `@id?` OPTIONAL — a stable URI identifying the entity. Used for\n * cross-referencing on the same page (e.g. `Article.publisher`\n * referencing the page-level `Organization` via `@id`). The\n * renderer uses `@id` for deduplication: two payloads with the\n * same `@id` collapse into one emitted block (last-wins).\n * - `@context?` OPTIONAL — the JSON-LD vocabulary URL. The renderer\n * auto-injects `'https://schema.org'` when omitted; the field is\n * exposed so consumers CAN override (Schema.org payload extended\n * with a custom vocabulary).\n * - All other fields are pass-through `unknown` — the catalog\n * describes the FIELD NAMES per `@type`; the per-field SHAPE\n * (e.g. `Article.author` is a `Person | Organization`) is locked\n * at the section's payload-builder TS-side.\n */\nexport interface WebsiteStructuredDataPayload {\n '@type': string;\n '@id'?: string;\n '@context'?: string | Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Convenience union for `getStructuredData()` return types.\n *\n * A section may emit:\n * - a single payload (most common — `FAQPage` for an FAQ section);\n * - a fixed-length tuple of payloads (e.g. pricing emits `Product +\n * AggregateOffer` together);\n * - `null` / `undefined` when the section has no contribution for\n * the current state (e.g. an empty FAQ list);\n * - an empty array (semantically equivalent to `null`; the renderer\n * short-circuits both).\n */\nexport type WebsiteStructuredDataReturn =\n | WebsiteStructuredDataPayload\n | readonly WebsiteStructuredDataPayload[]\n | null\n | undefined;\n/** @wildo_source:part:end saas.website.structured-data.payload-shape */\n"]}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import type { WebsiteLabelKey } from '../label-keys/website-label-key.schemas';
|
|
2
|
+
import type { WebsitePageManifest } from '../manifests/website-page-manifest.shared.schemas';
|
|
3
|
+
import type { WebsiteSectionRef } from '../refs/section-ref.schemas';
|
|
4
|
+
/**
|
|
5
|
+
* @wildo_source:part:start saas.website.label-pack.validator facet:layer:shared facet:family:website
|
|
6
|
+
*
|
|
7
|
+
* `LabelPack` — flat string→string map keyed by fully-composed
|
|
8
|
+
* `WebsiteLabelKey` (e.g. `"website.landing.hero.headline"` →
|
|
9
|
+
* `"Welcome to Wonder Todos"`). One pack per locale, loaded by the
|
|
10
|
+
* Astro adapter in Phase 5 from `website/src/i18n/<locale>.json`.
|
|
11
|
+
*
|
|
12
|
+
* Stored as a plain `Record<string, string>` rather than
|
|
13
|
+
* `Record<WebsiteLabelKey, string>` because runtime JSON parses to
|
|
14
|
+
* `Record<string, string>` and re-branding every key on load would
|
|
15
|
+
* cost O(N) parses per label-pack with no observable benefit (the
|
|
16
|
+
* validator below validates the keys against the manifest contract,
|
|
17
|
+
* which is the only meaningful guarantee).
|
|
18
|
+
*/
|
|
19
|
+
export type LabelPack = Record<string, string>;
|
|
20
|
+
/**
|
|
21
|
+
* Map from a section's `WebsiteSectionRef` to the fully-composed label
|
|
22
|
+
* keys that section's `defineWebsiteSection({ expectedLabelKeys })`
|
|
23
|
+
* declared. Built either:
|
|
24
|
+
* - **statically** at the site-config level (consumer hands the
|
|
25
|
+
* validator a literal map collected from imported sections), or
|
|
26
|
+
* - **at build time** by the Phase 5 collector
|
|
27
|
+
* (`collect-expected-label-keys.ts`) walking every manifest's
|
|
28
|
+
* `pageComponent` to discover the `defineWebsiteSection` calls
|
|
29
|
+
* it composes.
|
|
30
|
+
*
|
|
31
|
+
* The validator itself is build-source-agnostic — it validates whatever
|
|
32
|
+
* map it is given against the manifest registry.
|
|
33
|
+
*/
|
|
34
|
+
export type ExpectedLabelKeysBySectionRef = Map<WebsiteSectionRef, readonly WebsiteLabelKey[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Output of `validateLabelPackAgainstManifest`. Three flat lists, no
|
|
37
|
+
* grouping by page/section because the diagnostics CLI / build-time
|
|
38
|
+
* reporter wants a single sorted list per failure category.
|
|
39
|
+
*
|
|
40
|
+
* **Type-precision rationale** for the three lists:
|
|
41
|
+
*
|
|
42
|
+
* - `missing` is `WebsiteLabelKey[]`: every entry was originally declared
|
|
43
|
+
* in a section's `expectedLabelKeys`, which means it has already been
|
|
44
|
+
* parsed through `WebsiteLabelKeySchema` at section-definition time —
|
|
45
|
+
* the brand carries here legitimately.
|
|
46
|
+
* - `orphaned` is `string[]`: entries come from `Object.keys(pack)`,
|
|
47
|
+
* i.e. arbitrary keys present in the loaded JSON. They have NOT been
|
|
48
|
+
* parsed through `WebsiteLabelKeySchema` (in fact, malformed pack
|
|
49
|
+
* keys are a common cause of orphans — typos, prefix mistakes,
|
|
50
|
+
* missing segments). Branding these would be a type-system lie that
|
|
51
|
+
* would let downstream code feed an orphan key into a
|
|
52
|
+
* `WebsiteLabelKey`-typed API and blow up at runtime.
|
|
53
|
+
* - `unmappedSectionRefs` is `WebsiteSectionRef[]`: entries come from
|
|
54
|
+
* `manifest.sectionRefs`, which were already parsed through
|
|
55
|
+
* `WebsiteSectionRefSchema`.
|
|
56
|
+
*/
|
|
57
|
+
export interface LabelPackValidationResult {
|
|
58
|
+
/**
|
|
59
|
+
* Keys the manifest commits to (declared in any section's
|
|
60
|
+
* `expectedLabelKeys`) but absent from the provided pack. A non-empty
|
|
61
|
+
* `missing` list is a HARD ERROR — the build MUST fail.
|
|
62
|
+
*/
|
|
63
|
+
missing: WebsiteLabelKey[];
|
|
64
|
+
/**
|
|
65
|
+
* Raw pack keys NOT declared by any section in any manifest. A
|
|
66
|
+
* non-empty `orphaned` list is a SOFT WARNING — orphaned keys are
|
|
67
|
+
* usually stale entries left behind by a section rename or deletion,
|
|
68
|
+
* and surfacing them eagerly keeps the pack lean. The build does NOT
|
|
69
|
+
* fail on orphaned keys (a consumer might author keys for a section
|
|
70
|
+
* they haven't shipped yet).
|
|
71
|
+
*
|
|
72
|
+
* Typed `string[]` (NOT `WebsiteLabelKey[]`) because pack keys
|
|
73
|
+
* have not been validated against `WebsiteLabelKeySchema`.
|
|
74
|
+
*/
|
|
75
|
+
orphaned: string[];
|
|
76
|
+
/**
|
|
77
|
+
* Sections referenced by a manifest's `sectionRefs[]` whose
|
|
78
|
+
* `expectedLabelKeys` could not be resolved (the section was missing
|
|
79
|
+
* from the `expectedKeysBySectionRef` map). This is a build-pipeline
|
|
80
|
+
* configuration bug (the collector failed to discover the section's
|
|
81
|
+
* `defineWebsiteSection` call) — distinct from `missing`, which is a
|
|
82
|
+
* content authoring bug.
|
|
83
|
+
*/
|
|
84
|
+
unmappedSectionRefs: WebsiteSectionRef[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Pure label-pack validator. Cross-references the keys declared by
|
|
88
|
+
* every section across every page manifest against the keys present
|
|
89
|
+
* in the supplied pack.
|
|
90
|
+
*
|
|
91
|
+
* **Algorithm**:
|
|
92
|
+
* 1. Walk every manifest's `sectionRefs` and look up
|
|
93
|
+
* `expectedKeysBySectionRef.get(sectionRef)`. Sections whose ref
|
|
94
|
+
* appears in a manifest but is missing from the map are
|
|
95
|
+
* surfaced as a separate diagnostic (`unmappedSectionRefs`); the
|
|
96
|
+
* validator does NOT silently treat an unmapped section as
|
|
97
|
+
* "no expected keys".
|
|
98
|
+
* 2. Add every page's `metaLabelKeys.titleKey` and
|
|
99
|
+
* `metaLabelKeys.descriptionKey` to the expected set (these are
|
|
100
|
+
* page-level keys, not section-scoped).
|
|
101
|
+
* 3. `missing` = expected ∖ pack-keys.
|
|
102
|
+
* 4. `orphaned` = pack-keys ∖ expected.
|
|
103
|
+
* 5. Both lists are sorted lexicographically for deterministic
|
|
104
|
+
* diagnostic output.
|
|
105
|
+
*
|
|
106
|
+
* **Why `unmappedSectionRefs` is a third bucket** (not folded into
|
|
107
|
+
* `missing`): "I don't know what keys this section needs" is a
|
|
108
|
+
* different failure mode from "I know the section needs `headline`
|
|
109
|
+
* and you didn't provide it". The first is a build-pipeline
|
|
110
|
+
* configuration bug (the collector didn't see the section); the
|
|
111
|
+
* second is a content authoring bug. Keeping them distinct makes the
|
|
112
|
+
* diagnostic actionable.
|
|
113
|
+
*
|
|
114
|
+
* **Pure / no I/O**: the validator does not read files, does not boot
|
|
115
|
+
* React, does not require Astro. It accepts already-parsed data
|
|
116
|
+
* structures and returns a result object. This keeps it usable from:
|
|
117
|
+
* - the Astro build hook (Phase 5),
|
|
118
|
+
* - the `wildo website audit` CLI (Phase 7),
|
|
119
|
+
* - companion subprocesses,
|
|
120
|
+
* - unit tests.
|
|
121
|
+
*
|
|
122
|
+
* @param manifests Every `WebsitePageManifest` registered on the site.
|
|
123
|
+
* Typically `WebsiteRootConfig.pageManifests`.
|
|
124
|
+
* @param expectedKeysBySectionRef Map from sectionRef to the fully-
|
|
125
|
+
* composed keys that section commits to.
|
|
126
|
+
* @param pack The locale's loaded label pack.
|
|
127
|
+
* @param chromeLabelKeys OPTIONAL. The fully-composed keys read by
|
|
128
|
+
* site-wide chrome (header / footer / any slot
|
|
129
|
+
* rendered outside a section context). Declared
|
|
130
|
+
* on `WebsiteRootConfig.chromeLabelKeys` because
|
|
131
|
+
* chrome cannot register `expectedLabelKeys` via
|
|
132
|
+
* `defineWebsiteSection` (it lives outside the
|
|
133
|
+
* page+section context). Without this list, every
|
|
134
|
+
* `website.chrome.*` entry would surface as an
|
|
135
|
+
* orphan warning on every build. Defaults to `[]`
|
|
136
|
+
* — sites with no chrome label reads omit the
|
|
137
|
+
* argument entirely.
|
|
138
|
+
* @returns `LabelPackValidationResult` with three diagnostic buckets:
|
|
139
|
+
* `missing` (hard error), `orphaned` (soft warning), and
|
|
140
|
+
* `unmappedSectionRefs` (build-pipeline configuration bug).
|
|
141
|
+
*/
|
|
142
|
+
export declare function validateLabelPackAgainstManifest(manifests: readonly WebsitePageManifest[], expectedKeysBySectionRef: ExpectedLabelKeysBySectionRef, pack: LabelPack, chromeLabelKeys?: readonly WebsiteLabelKey[]): LabelPackValidationResult;
|
|
143
|
+
/** @wildo_source:part:end saas.website.label-pack.validator */
|
|
144
|
+
//# sourceMappingURL=label-pack.validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label-pack.validator.d.ts","sourceRoot":"","sources":["../../../../../src/schemas/validators/label-pack.validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mDAAmD,CAAC;AAC7F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,6BAA6B,GAAG,GAAG,CAAC,iBAAiB,EAAE,SAAS,eAAe,EAAE,CAAC,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;OAOG;IACH,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,SAAS,mBAAmB,EAAE,EACzC,wBAAwB,EAAE,6BAA6B,EACvD,IAAI,EAAE,SAAS,EACf,eAAe,GAAE,SAAS,eAAe,EAAO,GAC/C,yBAAyB,CAiD3B;AACD,+DAA+D"}
|