@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.
Files changed (383) hide show
  1. package/LICENSE +34 -0
  2. package/dist/esm/.builder.pid +9 -0
  3. package/dist/esm/astro/blog-post-bridge.d.ts +324 -0
  4. package/dist/esm/astro/blog-post-bridge.d.ts.map +1 -0
  5. package/dist/esm/astro/blog-post-bridge.js +57 -0
  6. package/dist/esm/astro/blog-post-bridge.js.map +1 -0
  7. package/dist/esm/astro/blog-post-head.renderer.d.ts +129 -0
  8. package/dist/esm/astro/blog-post-head.renderer.d.ts.map +1 -0
  9. package/dist/esm/astro/blog-post-head.renderer.js +139 -0
  10. package/dist/esm/astro/blog-post-head.renderer.js.map +1 -0
  11. package/dist/esm/astro/bridge-runtime.d.ts +224 -0
  12. package/dist/esm/astro/bridge-runtime.d.ts.map +1 -0
  13. package/dist/esm/astro/bridge-runtime.js +30 -0
  14. package/dist/esm/astro/bridge-runtime.js.map +1 -0
  15. package/dist/esm/astro/collect-expected-label-keys.d.ts +65 -0
  16. package/dist/esm/astro/collect-expected-label-keys.d.ts.map +1 -0
  17. package/dist/esm/astro/collect-expected-label-keys.js +101 -0
  18. package/dist/esm/astro/collect-expected-label-keys.js.map +1 -0
  19. package/dist/esm/astro/headers-renderer.d.ts +32 -0
  20. package/dist/esm/astro/headers-renderer.d.ts.map +1 -0
  21. package/dist/esm/astro/headers-renderer.js +64 -0
  22. package/dist/esm/astro/headers-renderer.js.map +1 -0
  23. package/dist/esm/astro/i18n-routing.helper.d.ts +91 -0
  24. package/dist/esm/astro/i18n-routing.helper.d.ts.map +1 -0
  25. package/dist/esm/astro/i18n-routing.helper.js +23 -0
  26. package/dist/esm/astro/i18n-routing.helper.js.map +1 -0
  27. package/dist/esm/astro/internal/html-escape.d.ts +31 -0
  28. package/dist/esm/astro/internal/html-escape.d.ts.map +1 -0
  29. package/dist/esm/astro/internal/html-escape.js +40 -0
  30. package/dist/esm/astro/internal/html-escape.js.map +1 -0
  31. package/dist/esm/astro/label-pack-loader.d.ts +134 -0
  32. package/dist/esm/astro/label-pack-loader.d.ts.map +1 -0
  33. package/dist/esm/astro/label-pack-loader.js +298 -0
  34. package/dist/esm/astro/label-pack-loader.js.map +1 -0
  35. package/dist/esm/astro/llms-txt-server.d.ts +28 -0
  36. package/dist/esm/astro/llms-txt-server.d.ts.map +1 -0
  37. package/dist/esm/astro/llms-txt-server.js +33 -0
  38. package/dist/esm/astro/llms-txt-server.js.map +1 -0
  39. package/dist/esm/astro/pick-labels-for-page.d.ts +63 -0
  40. package/dist/esm/astro/pick-labels-for-page.d.ts.map +1 -0
  41. package/dist/esm/astro/pick-labels-for-page.js +73 -0
  42. package/dist/esm/astro/pick-labels-for-page.js.map +1 -0
  43. package/dist/esm/astro/robots-renderer.d.ts +85 -0
  44. package/dist/esm/astro/robots-renderer.d.ts.map +1 -0
  45. package/dist/esm/astro/robots-renderer.js +157 -0
  46. package/dist/esm/astro/robots-renderer.js.map +1 -0
  47. package/dist/esm/astro/sitemap-coverage.d.ts +101 -0
  48. package/dist/esm/astro/sitemap-coverage.d.ts.map +1 -0
  49. package/dist/esm/astro/sitemap-coverage.js +67 -0
  50. package/dist/esm/astro/sitemap-coverage.js.map +1 -0
  51. package/dist/esm/astro/structured-data.renderer.d.ts +21 -0
  52. package/dist/esm/astro/structured-data.renderer.d.ts.map +1 -0
  53. package/dist/esm/astro/structured-data.renderer.js +142 -0
  54. package/dist/esm/astro/structured-data.renderer.js.map +1 -0
  55. package/dist/esm/astro/website-page-head.renderer.d.ts +93 -0
  56. package/dist/esm/astro/website-page-head.renderer.d.ts.map +1 -0
  57. package/dist/esm/astro/website-page-head.renderer.js +184 -0
  58. package/dist/esm/astro/website-page-head.renderer.js.map +1 -0
  59. package/dist/esm/astro/website-page-runtime.helper.d.ts +112 -0
  60. package/dist/esm/astro/website-page-runtime.helper.d.ts.map +1 -0
  61. package/dist/esm/astro/website-page-runtime.helper.js +60 -0
  62. package/dist/esm/astro/website-page-runtime.helper.js.map +1 -0
  63. package/dist/esm/astro/website-site-context.d.ts +126 -0
  64. package/dist/esm/astro/website-site-context.d.ts.map +1 -0
  65. package/dist/esm/astro/website-site-context.js +37 -0
  66. package/dist/esm/astro/website-site-context.js.map +1 -0
  67. package/dist/esm/astro-island.d.ts +56 -0
  68. package/dist/esm/astro-island.d.ts.map +1 -0
  69. package/dist/esm/astro-island.js +61 -0
  70. package/dist/esm/astro-island.js.map +1 -0
  71. package/dist/esm/astro.d.ts +151 -0
  72. package/dist/esm/astro.d.ts.map +1 -0
  73. package/dist/esm/astro.js +151 -0
  74. package/dist/esm/astro.js.map +1 -0
  75. package/dist/esm/companion-exports.d.ts +38 -0
  76. package/dist/esm/companion-exports.d.ts.map +1 -0
  77. package/dist/esm/companion-exports.js +38 -0
  78. package/dist/esm/companion-exports.js.map +1 -0
  79. package/dist/esm/components/low-level/WebsiteButton.d.ts +73 -0
  80. package/dist/esm/components/low-level/WebsiteButton.d.ts.map +1 -0
  81. package/dist/esm/components/low-level/WebsiteButton.js +68 -0
  82. package/dist/esm/components/low-level/WebsiteButton.js.map +1 -0
  83. package/dist/esm/components/low-level/WebsiteHeading.d.ts +78 -0
  84. package/dist/esm/components/low-level/WebsiteHeading.d.ts.map +1 -0
  85. package/dist/esm/components/low-level/WebsiteHeading.js +41 -0
  86. package/dist/esm/components/low-level/WebsiteHeading.js.map +1 -0
  87. package/dist/esm/components/low-level/WebsiteImage.d.ts +73 -0
  88. package/dist/esm/components/low-level/WebsiteImage.d.ts.map +1 -0
  89. package/dist/esm/components/low-level/WebsiteImage.js +21 -0
  90. package/dist/esm/components/low-level/WebsiteImage.js.map +1 -0
  91. package/dist/esm/components/low-level/WebsiteInternalButton.d.ts +90 -0
  92. package/dist/esm/components/low-level/WebsiteInternalButton.d.ts.map +1 -0
  93. package/dist/esm/components/low-level/WebsiteInternalButton.js +47 -0
  94. package/dist/esm/components/low-level/WebsiteInternalButton.js.map +1 -0
  95. package/dist/esm/components/low-level/WebsiteInternalLink.d.ts +99 -0
  96. package/dist/esm/components/low-level/WebsiteInternalLink.d.ts.map +1 -0
  97. package/dist/esm/components/low-level/WebsiteInternalLink.js +68 -0
  98. package/dist/esm/components/low-level/WebsiteInternalLink.js.map +1 -0
  99. package/dist/esm/components/low-level/WebsiteLink.d.ts +50 -0
  100. package/dist/esm/components/low-level/WebsiteLink.d.ts.map +1 -0
  101. package/dist/esm/components/low-level/WebsiteLink.js +22 -0
  102. package/dist/esm/components/low-level/WebsiteLink.js.map +1 -0
  103. package/dist/esm/components/low-level/WebsiteText.d.ts +57 -0
  104. package/dist/esm/components/low-level/WebsiteText.d.ts.map +1 -0
  105. package/dist/esm/components/low-level/WebsiteText.js +57 -0
  106. package/dist/esm/components/low-level/WebsiteText.js.map +1 -0
  107. package/dist/esm/config/define-website-config.d.ts +83 -0
  108. package/dist/esm/config/define-website-config.d.ts.map +1 -0
  109. package/dist/esm/config/define-website-config.js +126 -0
  110. package/dist/esm/config/define-website-config.js.map +1 -0
  111. package/dist/esm/config/index.d.ts +38 -0
  112. package/dist/esm/config/index.d.ts.map +1 -0
  113. package/dist/esm/config/index.js +38 -0
  114. package/dist/esm/config/index.js.map +1 -0
  115. package/dist/esm/config/load-website-config.d.ts +136 -0
  116. package/dist/esm/config/load-website-config.d.ts.map +1 -0
  117. package/dist/esm/config/load-website-config.js +177 -0
  118. package/dist/esm/config/load-website-config.js.map +1 -0
  119. package/dist/esm/config/wildo-website-config.schemas.d.ts +251 -0
  120. package/dist/esm/config/wildo-website-config.schemas.d.ts.map +1 -0
  121. package/dist/esm/config/wildo-website-config.schemas.js +302 -0
  122. package/dist/esm/config/wildo-website-config.schemas.js.map +1 -0
  123. package/dist/esm/config-loader.d.ts +35 -0
  124. package/dist/esm/config-loader.d.ts.map +1 -0
  125. package/dist/esm/config-loader.js +35 -0
  126. package/dist/esm/config-loader.js.map +1 -0
  127. package/dist/esm/core/anonymous-session/InboundContactForm.d.ts +38 -0
  128. package/dist/esm/core/anonymous-session/InboundContactForm.d.ts.map +1 -0
  129. package/dist/esm/core/anonymous-session/InboundContactForm.js +77 -0
  130. package/dist/esm/core/anonymous-session/InboundContactForm.js.map +1 -0
  131. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts +41 -0
  132. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.d.ts.map +1 -0
  133. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js +58 -0
  134. package/dist/esm/core/anonymous-session/inbound-contact-form.schema.js.map +1 -0
  135. package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts +81 -0
  136. package/dist/esm/core/anonymous-session/website-anonymous-session-client.d.ts.map +1 -0
  137. package/dist/esm/core/anonymous-session/website-anonymous-session-client.js +177 -0
  138. package/dist/esm/core/anonymous-session/website-anonymous-session-client.js.map +1 -0
  139. package/dist/esm/core/contexts/WebsitePageContext.d.ts +40 -0
  140. package/dist/esm/core/contexts/WebsitePageContext.d.ts.map +1 -0
  141. package/dist/esm/core/contexts/WebsitePageContext.js +8 -0
  142. package/dist/esm/core/contexts/WebsitePageContext.js.map +1 -0
  143. package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts +162 -0
  144. package/dist/esm/core/contexts/WebsiteRuntimeContext.d.ts.map +1 -0
  145. package/dist/esm/core/contexts/WebsiteRuntimeContext.js +22 -0
  146. package/dist/esm/core/contexts/WebsiteRuntimeContext.js.map +1 -0
  147. package/dist/esm/core/contexts/WebsiteSectionContext.d.ts +47 -0
  148. package/dist/esm/core/contexts/WebsiteSectionContext.d.ts.map +1 -0
  149. package/dist/esm/core/contexts/WebsiteSectionContext.js +8 -0
  150. package/dist/esm/core/contexts/WebsiteSectionContext.js.map +1 -0
  151. package/dist/esm/core/contexts/useWebsitePage.d.ts +13 -0
  152. package/dist/esm/core/contexts/useWebsitePage.d.ts.map +1 -0
  153. package/dist/esm/core/contexts/useWebsitePage.js +22 -0
  154. package/dist/esm/core/contexts/useWebsitePage.js.map +1 -0
  155. package/dist/esm/core/contexts/useWebsiteRuntime.d.ts +19 -0
  156. package/dist/esm/core/contexts/useWebsiteRuntime.d.ts.map +1 -0
  157. package/dist/esm/core/contexts/useWebsiteRuntime.js +28 -0
  158. package/dist/esm/core/contexts/useWebsiteRuntime.js.map +1 -0
  159. package/dist/esm/core/contexts/useWebsiteSection.d.ts +12 -0
  160. package/dist/esm/core/contexts/useWebsiteSection.d.ts.map +1 -0
  161. package/dist/esm/core/contexts/useWebsiteSection.js +22 -0
  162. package/dist/esm/core/contexts/useWebsiteSection.js.map +1 -0
  163. package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts +17 -0
  164. package/dist/esm/core/external-providers/frontend-provider-registry.website.d.ts.map +1 -0
  165. package/dist/esm/core/external-providers/frontend-provider-registry.website.js +23 -0
  166. package/dist/esm/core/external-providers/frontend-provider-registry.website.js.map +1 -0
  167. package/dist/esm/core/factories/define-website-page-manifest.d.ts +70 -0
  168. package/dist/esm/core/factories/define-website-page-manifest.d.ts.map +1 -0
  169. package/dist/esm/core/factories/define-website-page-manifest.js +51 -0
  170. package/dist/esm/core/factories/define-website-page-manifest.js.map +1 -0
  171. package/dist/esm/core/factories/define-website-section.d.ts +101 -0
  172. package/dist/esm/core/factories/define-website-section.d.ts.map +1 -0
  173. package/dist/esm/core/factories/define-website-section.js +71 -0
  174. package/dist/esm/core/factories/define-website-section.js.map +1 -0
  175. package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts +23 -0
  176. package/dist/esm/core/hooks/useWebsiteDesignTokens.d.ts.map +1 -0
  177. package/dist/esm/core/hooks/useWebsiteDesignTokens.js +25 -0
  178. package/dist/esm/core/hooks/useWebsiteDesignTokens.js.map +1 -0
  179. package/dist/esm/core/hooks/useWebsiteLabel.d.ts +68 -0
  180. package/dist/esm/core/hooks/useWebsiteLabel.d.ts.map +1 -0
  181. package/dist/esm/core/hooks/useWebsiteLabel.js +103 -0
  182. package/dist/esm/core/hooks/useWebsiteLabel.js.map +1 -0
  183. package/dist/esm/core/layouts/WebsitePageLayout.d.ts +87 -0
  184. package/dist/esm/core/layouts/WebsitePageLayout.d.ts.map +1 -0
  185. package/dist/esm/core/layouts/WebsitePageLayout.js +170 -0
  186. package/dist/esm/core/layouts/WebsitePageLayout.js.map +1 -0
  187. package/dist/esm/core/layouts/WebsiteSection.d.ts +91 -0
  188. package/dist/esm/core/layouts/WebsiteSection.d.ts.map +1 -0
  189. package/dist/esm/core/layouts/WebsiteSection.js +26 -0
  190. package/dist/esm/core/layouts/WebsiteSection.js.map +1 -0
  191. package/dist/esm/core/routing/internal-routing.utils.d.ts +65 -0
  192. package/dist/esm/core/routing/internal-routing.utils.d.ts.map +1 -0
  193. package/dist/esm/core/routing/internal-routing.utils.js +14 -0
  194. package/dist/esm/core/routing/internal-routing.utils.js.map +1 -0
  195. package/dist/esm/index.d.ts +129 -0
  196. package/dist/esm/index.d.ts.map +1 -0
  197. package/dist/esm/index.js +129 -0
  198. package/dist/esm/index.js.map +1 -0
  199. package/dist/esm/mdx/BlogPost.d.ts +193 -0
  200. package/dist/esm/mdx/BlogPost.d.ts.map +1 -0
  201. package/dist/esm/mdx/BlogPost.js +161 -0
  202. package/dist/esm/mdx/BlogPost.js.map +1 -0
  203. package/dist/esm/mdx/blog-post-collection.config.d.ts +139 -0
  204. package/dist/esm/mdx/blog-post-collection.config.d.ts.map +1 -0
  205. package/dist/esm/mdx/blog-post-collection.config.js +27 -0
  206. package/dist/esm/mdx/blog-post-collection.config.js.map +1 -0
  207. package/dist/esm/mdx/blog-post-frontmatter-source.d.ts +12 -0
  208. package/dist/esm/mdx/blog-post-frontmatter-source.d.ts.map +1 -0
  209. package/dist/esm/mdx/blog-post-frontmatter-source.js +13 -0
  210. package/dist/esm/mdx/blog-post-frontmatter-source.js.map +1 -0
  211. package/dist/esm/mdx/index.d.ts +22 -0
  212. package/dist/esm/mdx/index.d.ts.map +1 -0
  213. package/dist/esm/mdx/index.js +22 -0
  214. package/dist/esm/mdx/index.js.map +1 -0
  215. package/dist/esm/mdx/website-mdx-provider.d.ts +90 -0
  216. package/dist/esm/mdx/website-mdx-provider.d.ts.map +1 -0
  217. package/dist/esm/mdx/website-mdx-provider.js +8 -0
  218. package/dist/esm/mdx/website-mdx-provider.js.map +1 -0
  219. package/dist/esm/mdx.d.ts +38 -0
  220. package/dist/esm/mdx.d.ts.map +1 -0
  221. package/dist/esm/mdx.js +38 -0
  222. package/dist/esm/mdx.js.map +1 -0
  223. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts +75 -0
  224. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.d.ts.map +1 -0
  225. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js +85 -0
  226. package/dist/esm/schemas/blog/blog-post-frontmatter.shared.schemas.js.map +1 -0
  227. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts +120 -0
  228. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.d.ts.map +1 -0
  229. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js +152 -0
  230. package/dist/esm/schemas/design-tokens/website-design-tokens.shared.schemas.js.map +1 -0
  231. package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts +73 -0
  232. package/dist/esm/schemas/label-keys/website-label-key.schemas.d.ts.map +1 -0
  233. package/dist/esm/schemas/label-keys/website-label-key.schemas.js +76 -0
  234. package/dist/esm/schemas/label-keys/website-label-key.schemas.js.map +1 -0
  235. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts +209 -0
  236. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.d.ts.map +1 -0
  237. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js +218 -0
  238. package/dist/esm/schemas/manifests/website-page-manifest.shared.schemas.js.map +1 -0
  239. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts +431 -0
  240. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.d.ts.map +1 -0
  241. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js +438 -0
  242. package/dist/esm/schemas/manifests/website-root-config.shared.schemas.js.map +1 -0
  243. package/dist/esm/schemas/refs/page-ref.schemas.d.ts +40 -0
  244. package/dist/esm/schemas/refs/page-ref.schemas.d.ts.map +1 -0
  245. package/dist/esm/schemas/refs/page-ref.schemas.js +43 -0
  246. package/dist/esm/schemas/refs/page-ref.schemas.js.map +1 -0
  247. package/dist/esm/schemas/refs/section-ref.schemas.d.ts +41 -0
  248. package/dist/esm/schemas/refs/section-ref.schemas.d.ts.map +1 -0
  249. package/dist/esm/schemas/refs/section-ref.schemas.js +44 -0
  250. package/dist/esm/schemas/refs/section-ref.schemas.js.map +1 -0
  251. package/dist/esm/schemas/sections/website-section-category.shared.d.ts +63 -0
  252. package/dist/esm/schemas/sections/website-section-category.shared.d.ts.map +1 -0
  253. package/dist/esm/schemas/sections/website-section-category.shared.js +64 -0
  254. package/dist/esm/schemas/sections/website-section-category.shared.js.map +1 -0
  255. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts +114 -0
  256. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.d.ts.map +1 -0
  257. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js +69 -0
  258. package/dist/esm/schemas/sections/website-section-definition.shared.schemas.js.map +1 -0
  259. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts +100 -0
  260. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.d.ts.map +1 -0
  261. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js +355 -0
  262. package/dist/esm/schemas/structured-data/structured-data-reconciliation.shared.js.map +1 -0
  263. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts +58 -0
  264. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.d.ts.map +1 -0
  265. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js +2 -0
  266. package/dist/esm/schemas/structured-data/website-structured-data.shared.schemas.js.map +1 -0
  267. package/dist/esm/schemas/validators/label-pack.validator.d.ts +144 -0
  268. package/dist/esm/schemas/validators/label-pack.validator.d.ts.map +1 -0
  269. package/dist/esm/schemas/validators/label-pack.validator.js +100 -0
  270. package/dist/esm/schemas/validators/label-pack.validator.js.map +1 -0
  271. package/dist/tsconfig.build.tsbuildinfo +1 -0
  272. package/package.json +143 -0
  273. package/src/__tests__/bundle-isolation.test.ts +607 -0
  274. package/src/astro/__tests__/blog-post-bridge.test.tsx +288 -0
  275. package/src/astro/__tests__/blog-post-head.renderer.test.ts +249 -0
  276. package/src/astro/__tests__/bridge-runtime.test.tsx +198 -0
  277. package/src/astro/__tests__/collect-expected-label-keys.test.ts +69 -0
  278. package/src/astro/__tests__/headers-renderer.test.ts +143 -0
  279. package/src/astro/__tests__/i18n-routing.helper.test.ts +116 -0
  280. package/src/astro/__tests__/label-pack-loader.test.ts +305 -0
  281. package/src/astro/__tests__/llms-txt-server.test.ts +127 -0
  282. package/src/astro/__tests__/pick-labels-for-page.test.ts +60 -0
  283. package/src/astro/__tests__/robots-renderer.test.ts +228 -0
  284. package/src/astro/__tests__/sitemap-coverage.test.ts +230 -0
  285. package/src/astro/__tests__/structured-data.renderer.test.ts +172 -0
  286. package/src/astro/__tests__/website-page-head.renderer.test.ts +424 -0
  287. package/src/astro/__tests__/website-page-runtime.helper.test.ts +157 -0
  288. package/src/astro/__tests__/website-site-context.test.ts +121 -0
  289. package/src/astro/blog-post-bridge.tsx +404 -0
  290. package/src/astro/blog-post-head.renderer.ts +293 -0
  291. package/src/astro/bridge-runtime.tsx +270 -0
  292. package/src/astro/collect-expected-label-keys.ts +113 -0
  293. package/src/astro/headers-renderer.ts +82 -0
  294. package/src/astro/i18n-routing.helper.ts +116 -0
  295. package/src/astro/internal/html-escape.ts +41 -0
  296. package/src/astro/label-pack-loader.ts +385 -0
  297. package/src/astro/llms-txt-server.ts +56 -0
  298. package/src/astro/pick-labels-for-page.ts +85 -0
  299. package/src/astro/robots-renderer.ts +171 -0
  300. package/src/astro/sitemap-coverage.ts +186 -0
  301. package/src/astro/structured-data.renderer.ts +171 -0
  302. package/src/astro/website-page-head.renderer.ts +279 -0
  303. package/src/astro/website-page-runtime.helper.ts +188 -0
  304. package/src/astro/website-site-context.ts +136 -0
  305. package/src/astro-island.ts +61 -0
  306. package/src/astro.ts +151 -0
  307. package/src/companion-exports.ts +38 -0
  308. package/src/components/low-level/WebsiteButton.tsx +118 -0
  309. package/src/components/low-level/WebsiteHeading.tsx +96 -0
  310. package/src/components/low-level/WebsiteImage.tsx +96 -0
  311. package/src/components/low-level/WebsiteInternalButton.tsx +172 -0
  312. package/src/components/low-level/WebsiteInternalLink.tsx +193 -0
  313. package/src/components/low-level/WebsiteLink.tsx +71 -0
  314. package/src/components/low-level/WebsiteText.tsx +75 -0
  315. package/src/components/low-level/__tests__/WebsiteInternalButton.test.tsx +169 -0
  316. package/src/components/low-level/__tests__/WebsiteInternalLink.test.tsx +202 -0
  317. package/src/components/low-level/__tests__/primitives.test.tsx +141 -0
  318. package/src/config/__tests__/define-website-config.test.ts +231 -0
  319. package/src/config/__tests__/load-website-config.test.ts +215 -0
  320. package/src/config/define-website-config.ts +134 -0
  321. package/src/config/index.ts +38 -0
  322. package/src/config/load-website-config.ts +229 -0
  323. package/src/config/wildo-website-config.schemas.ts +322 -0
  324. package/src/config-loader.ts +35 -0
  325. package/src/core/__tests__/WebsitePageLayout.test.tsx +184 -0
  326. package/src/core/__tests__/WebsiteSection.test.tsx +85 -0
  327. package/src/core/__tests__/contexts.test.tsx +133 -0
  328. package/src/core/__tests__/core-boundary.test.ts +85 -0
  329. package/src/core/__tests__/define-website-page-manifest.test.tsx +111 -0
  330. package/src/core/__tests__/define-website-section.test.tsx +89 -0
  331. package/src/core/__tests__/useWebsiteDesignTokens.test.tsx +41 -0
  332. package/src/core/__tests__/useWebsiteLabel.test.tsx +117 -0
  333. package/src/core/anonymous-session/InboundContactForm.tsx +157 -0
  334. package/src/core/anonymous-session/__tests__/inbound-contact-form.schema.test.ts +44 -0
  335. package/src/core/anonymous-session/inbound-contact-form.schema.ts +62 -0
  336. package/src/core/anonymous-session/website-anonymous-session-client.ts +194 -0
  337. package/src/core/contexts/WebsitePageContext.tsx +52 -0
  338. package/src/core/contexts/WebsiteRuntimeContext.tsx +175 -0
  339. package/src/core/contexts/WebsiteSectionContext.tsx +59 -0
  340. package/src/core/contexts/useWebsitePage.ts +28 -0
  341. package/src/core/contexts/useWebsiteRuntime.ts +34 -0
  342. package/src/core/contexts/useWebsiteSection.ts +28 -0
  343. package/src/core/external-providers/frontend-provider-registry.website.ts +62 -0
  344. package/src/core/factories/define-website-page-manifest.ts +102 -0
  345. package/src/core/factories/define-website-section.ts +128 -0
  346. package/src/core/hooks/useWebsiteDesignTokens.ts +26 -0
  347. package/src/core/hooks/useWebsiteLabel.ts +121 -0
  348. package/src/core/layouts/WebsitePageLayout.tsx +311 -0
  349. package/src/core/layouts/WebsiteSection.tsx +139 -0
  350. package/src/core/routing/__tests__/internal-routing.utils.test.ts +134 -0
  351. package/src/core/routing/internal-routing.utils.ts +77 -0
  352. package/src/index.ts +132 -0
  353. package/src/mdx/BlogPost.tsx +296 -0
  354. package/src/mdx/__tests__/BlogPost.test.tsx +218 -0
  355. package/src/mdx/__tests__/blog-post-collection.config.test.ts +127 -0
  356. package/src/mdx/__tests__/website-mdx-provider.test.tsx +82 -0
  357. package/src/mdx/blog-post-collection.config.ts +177 -0
  358. package/src/mdx/blog-post-frontmatter-source.ts +31 -0
  359. package/src/mdx/index.ts +39 -0
  360. package/src/mdx/website-mdx-provider.tsx +95 -0
  361. package/src/mdx.ts +38 -0
  362. package/src/schemas/__tests__/blog-frontmatter.test.ts +50 -0
  363. package/src/schemas/__tests__/companion-exports-react-free.test.ts +51 -0
  364. package/src/schemas/__tests__/design-tokens.test.ts +163 -0
  365. package/src/schemas/__tests__/label-key.test.ts +46 -0
  366. package/src/schemas/__tests__/label-pack-validator.test.ts +146 -0
  367. package/src/schemas/__tests__/page-manifest.test.ts +66 -0
  368. package/src/schemas/__tests__/refs.test.ts +37 -0
  369. package/src/schemas/__tests__/root-config.test.ts +292 -0
  370. package/src/schemas/__tests__/section-definition.test.ts +47 -0
  371. package/src/schemas/__tests__/structured-data-reconciliation.test.ts +543 -0
  372. package/src/schemas/blog/blog-post-frontmatter.shared.schemas.ts +111 -0
  373. package/src/schemas/design-tokens/website-design-tokens.shared.schemas.ts +166 -0
  374. package/src/schemas/label-keys/website-label-key.schemas.ts +88 -0
  375. package/src/schemas/manifests/website-page-manifest.shared.schemas.ts +266 -0
  376. package/src/schemas/manifests/website-root-config.shared.schemas.ts +504 -0
  377. package/src/schemas/refs/page-ref.schemas.ts +49 -0
  378. package/src/schemas/refs/section-ref.schemas.ts +50 -0
  379. package/src/schemas/sections/website-section-category.shared.ts +65 -0
  380. package/src/schemas/sections/website-section-definition.shared.schemas.ts +120 -0
  381. package/src/schemas/structured-data/structured-data-reconciliation.shared.ts +579 -0
  382. package/src/schemas/structured-data/website-structured-data.shared.schemas.ts +62 -0
  383. package/src/schemas/validators/label-pack.validator.ts +201 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * @fileoverview Author helper for `wildo.website.config.ts` files.
3
+ *
4
+ * `defineWebsiteConfig({...})` mirrors the `defineSaasConfig` /
5
+ * `defineInfraEnvConfig` helpers from `@wildo-ai/platform-config-lib`
6
+ * and `defineTechnicalDocConfig` from `@wildo-ai/saas-technical-doc`:
7
+ * it wraps `WildoMarketingWebsiteConfigSchema.parse(...)` with full
8
+ * IDE autocompletion on the input shape, and emits a parse-time
9
+ * stderr warning for any authored field that has no runtime
10
+ * consumer yet.
11
+ *
12
+ * # `@unimplemented` channel — current state
13
+ *
14
+ * The warner has ZERO branches today because every OPTIONAL field that
15
+ * exists is already wired (`csp?` now flows through the website-local
16
+ * CSP sync step) and the only unwired field left is `appOrigin`, which
17
+ * is REQUIRED. After the seam-collapse (`saas-website-seam-collapse.md`
18
+ * — SHIPPED), the routing/origin fields (`publicOrigin`,
19
+ * `defaultLocale`, `locales`) are consumed directly by every Astro
20
+ * engine helper via `WebsiteSiteContext`, so they are no longer
21
+ * candidates for a "deferred wiring" warning either. The
22
+ * `@unimplemented` warner is for fields that are parsed-but-unused AND
23
+ * opt-in — firing on every Astro build for a required field would drown
24
+ * the dev console.
25
+ *
26
+ * Two valid futures will trigger adding warner branches:
27
+ * 1. A future optional field lands (e.g. `seo?.{title,description}`,
28
+ * `structuredData?.organization`) whose runtime wiring ships
29
+ * in a later PR — that would get
30
+ * `if (config.seo !== undefined) warn('seo', ...)` until the
31
+ * renderer reads it.
32
+ * 2. A required field temporarily loses its consumer (e.g. a
33
+ * large refactor splits the SEO renderer into two PRs); the
34
+ * branch fires unconditionally for the duration.
35
+ *
36
+ * The scaffold is kept (and the no-warning contract is pinned by
37
+ * the test suite) so the moment either case lands, the warning
38
+ * channel is one branch addition away — matching the
39
+ * `defineTechnicalDocConfig` shape exactly so future authors
40
+ * grepping for `@unimplemented` find a uniform pattern.
41
+ *
42
+ * Why we don't reuse `platform-config-lib`'s
43
+ * `createUnimplementedFieldWarner`:
44
+ *
45
+ * `platform-config-lib` is the platform-level boundary; this engine
46
+ * package is downstream of it for everything else. Importing the
47
+ * warner from `platform-config-lib` would invert the dependency
48
+ * direction (engine → platform-config), creating the same architectural
49
+ * defect Step 7.5 set out to fix. The warning format is small and
50
+ * stable enough to inline here — kept structurally similar to the
51
+ * platform-config-lib warner so readers grepping for `@unimplemented`
52
+ * still find both surfaces.
53
+ */
54
+ import { WildoMarketingWebsiteConfigSchema, } from './wildo-website-config.schemas.js';
55
+ /**
56
+ * Define a per-service marketing-website config. Provides full IDE
57
+ * autocompletion on the input shape, runs Zod validation (fail-closed
58
+ * on typos / unknown keys / out-of-range values / cross-field
59
+ * invariants like `defaultLocale ∈ locales`), and emits parse-time
60
+ * `@unimplemented` warnings for fields that are authored but have no
61
+ * runtime consumer yet.
62
+ *
63
+ * Throws on validation failure — same contract as `defineSaasConfig`
64
+ * and `defineTechnicalDocConfig`.
65
+ *
66
+ * @example
67
+ * ```ts
68
+ * import { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';
69
+ * import { defineWebsiteConfig } from '@wildo-ai/saas-website';
70
+ *
71
+ * export default defineWebsiteConfig({
72
+ * publicOrigin: 'https://wonder-todos.example.com',
73
+ * appOrigin: 'https://app.wonder-todos.example.com',
74
+ * defaultLocale: AvailableLanguage.EN,
75
+ * locales: [
76
+ * { locale: AvailableLanguage.EN, path: 'en' },
77
+ * { locale: AvailableLanguage.FR, path: 'fr' },
78
+ * ],
79
+ * });
80
+ * ```
81
+ */
82
+ export function defineWebsiteConfig(config) {
83
+ const parsed = WildoMarketingWebsiteConfigSchema.parse(config);
84
+ emitUnimplementedRuntimeWarnings(parsed);
85
+ return parsed;
86
+ }
87
+ /**
88
+ * Emit `@unimplemented` parse-time warnings for every authored
89
+ * OPTIONAL field on `WildoMarketingWebsiteConfig` that is parsed
90
+ * but has no runtime consumer yet.
91
+ *
92
+ * Branches today: ZERO. The one OPTIONAL field that exists (`csp?`) is
93
+ * fully wired through the website-local CSP sync/build path, while the
94
+ * only field that still lacks a runtime consumer (`appOrigin`) is
95
+ * REQUIRED. After the seam-collapse (`saas-website-seam-collapse.md` —
96
+ * SHIPPED) the routing/origin fields are consumed directly by every
97
+ * Astro engine helper via `WebsiteSiteContext`. Required-but-unwired
98
+ * fields cannot reasonably fire on every parse — that's a
99
+ * deferred-wiring surface tracked in the schema header, not an
100
+ * `@unimplemented` warner concern.
101
+ *
102
+ * The function exists as a structural mirror of
103
+ * `defineTechnicalDocConfig.emitUnimplementedRuntimeWarnings` so
104
+ * readers grepping for `emitUnimplementedRuntimeWarnings` find a
105
+ * uniform pattern across every `defineXxxConfig` helper.
106
+ *
107
+ * # Adding a branch (recipe)
108
+ *
109
+ * When the first OPTIONAL `@unimplemented` field lands (most
110
+ * likely candidate: `seo?.{title,description}`), add the warner
111
+ * machinery here: a `seen` set + a
112
+ * `warn(fieldPath, sliceId)` helper that formats as
113
+ * `[wildo-website-config] @unimplemented field '...'` and writes
114
+ * to `process.stderr`, then the matching `if (config.<field> !==
115
+ * undefined)` branch. Copy the exact shape from
116
+ * `define-tech-doc-config.ts > emitUnimplementedRuntimeWarnings`
117
+ * to keep the message format identical across helpers. The test
118
+ * suite pins the zero-warnings contract — flip its expectation in
119
+ * the same commit.
120
+ */
121
+ function emitUnimplementedRuntimeWarnings(_config) {
122
+ // Intentional no-op — see function JSDoc for why a no-op is the
123
+ // correct shape today (optional fields are either fully wired or
124
+ // absent) and the recipe for adding the first branch.
125
+ }
126
+ //# sourceMappingURL=define-website-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-website-config.js","sourceRoot":"","sources":["../../../../src/config/define-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,OAAO,EACL,iCAAiC,GAGlC,MAAM,gCAAgC,CAAC;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAwC;IAExC,MAAM,MAAM,GAAG,iCAAiC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/D,gCAAgC,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,SAAS,gCAAgC,CAAC,OAAoC;IAC5E,gEAAgE;IAChE,iEAAiE;IACjE,sDAAsD;AACxD,CAAC","sourcesContent":["/**\n * @fileoverview Author helper for `wildo.website.config.ts` files.\n *\n * `defineWebsiteConfig({...})` mirrors the `defineSaasConfig` /\n * `defineInfraEnvConfig` helpers from `@wildo-ai/platform-config-lib`\n * and `defineTechnicalDocConfig` from `@wildo-ai/saas-technical-doc`:\n * it wraps `WildoMarketingWebsiteConfigSchema.parse(...)` with full\n * IDE autocompletion on the input shape, and emits a parse-time\n * stderr warning for any authored field that has no runtime\n * consumer yet.\n *\n * # `@unimplemented` channel — current state\n *\n * The warner has ZERO branches today because every OPTIONAL field that\n * exists is already wired (`csp?` now flows through the website-local\n * CSP sync step) and the only unwired field left is `appOrigin`, which\n * is REQUIRED. After the seam-collapse (`saas-website-seam-collapse.md`\n * — SHIPPED), the routing/origin fields (`publicOrigin`,\n * `defaultLocale`, `locales`) are consumed directly by every Astro\n * engine helper via `WebsiteSiteContext`, so they are no longer\n * candidates for a \"deferred wiring\" warning either. The\n * `@unimplemented` warner is for fields that are parsed-but-unused AND\n * opt-in — firing on every Astro build for a required field would drown\n * the dev console.\n *\n * Two valid futures will trigger adding warner branches:\n * 1. A future optional field lands (e.g. `seo?.{title,description}`,\n * `structuredData?.organization`) whose runtime wiring ships\n * in a later PR — that would get\n * `if (config.seo !== undefined) warn('seo', ...)` until the\n * renderer reads it.\n * 2. A required field temporarily loses its consumer (e.g. a\n * large refactor splits the SEO renderer into two PRs); the\n * branch fires unconditionally for the duration.\n *\n * The scaffold is kept (and the no-warning contract is pinned by\n * the test suite) so the moment either case lands, the warning\n * channel is one branch addition away — matching the\n * `defineTechnicalDocConfig` shape exactly so future authors\n * grepping for `@unimplemented` find a uniform pattern.\n *\n * Why we don't reuse `platform-config-lib`'s\n * `createUnimplementedFieldWarner`:\n *\n * `platform-config-lib` is the platform-level boundary; this engine\n * package is downstream of it for everything else. Importing the\n * warner from `platform-config-lib` would invert the dependency\n * direction (engine → platform-config), creating the same architectural\n * defect Step 7.5 set out to fix. The warning format is small and\n * stable enough to inline here — kept structurally similar to the\n * platform-config-lib warner so readers grepping for `@unimplemented`\n * still find both surfaces.\n */\n\nimport {\n WildoMarketingWebsiteConfigSchema,\n type WildoMarketingWebsiteConfig,\n type WildoMarketingWebsiteConfigInput,\n} from './wildo-website-config.schemas';\n\n/**\n * Define a per-service marketing-website config. Provides full IDE\n * autocompletion on the input shape, runs Zod validation (fail-closed\n * on typos / unknown keys / out-of-range values / cross-field\n * invariants like `defaultLocale ∈ locales`), and emits parse-time\n * `@unimplemented` warnings for fields that are authored but have no\n * runtime consumer yet.\n *\n * Throws on validation failure — same contract as `defineSaasConfig`\n * and `defineTechnicalDocConfig`.\n *\n * @example\n * ```ts\n * import { AvailableLanguage } from '@wildo-ai/saas-models/public-runtime';\n * import { defineWebsiteConfig } from '@wildo-ai/saas-website';\n *\n * export default defineWebsiteConfig({\n * publicOrigin: 'https://wonder-todos.example.com',\n * appOrigin: 'https://app.wonder-todos.example.com',\n * defaultLocale: AvailableLanguage.EN,\n * locales: [\n * { locale: AvailableLanguage.EN, path: 'en' },\n * { locale: AvailableLanguage.FR, path: 'fr' },\n * ],\n * });\n * ```\n */\nexport function defineWebsiteConfig(\n config: WildoMarketingWebsiteConfigInput,\n): WildoMarketingWebsiteConfig {\n const parsed = WildoMarketingWebsiteConfigSchema.parse(config);\n emitUnimplementedRuntimeWarnings(parsed);\n return parsed;\n}\n\n/**\n * Emit `@unimplemented` parse-time warnings for every authored\n * OPTIONAL field on `WildoMarketingWebsiteConfig` that is parsed\n * but has no runtime consumer yet.\n *\n * Branches today: ZERO. The one OPTIONAL field that exists (`csp?`) is\n * fully wired through the website-local CSP sync/build path, while the\n * only field that still lacks a runtime consumer (`appOrigin`) is\n * REQUIRED. After the seam-collapse (`saas-website-seam-collapse.md` —\n * SHIPPED) the routing/origin fields are consumed directly by every\n * Astro engine helper via `WebsiteSiteContext`. Required-but-unwired\n * fields cannot reasonably fire on every parse — that's a\n * deferred-wiring surface tracked in the schema header, not an\n * `@unimplemented` warner concern.\n *\n * The function exists as a structural mirror of\n * `defineTechnicalDocConfig.emitUnimplementedRuntimeWarnings` so\n * readers grepping for `emitUnimplementedRuntimeWarnings` find a\n * uniform pattern across every `defineXxxConfig` helper.\n *\n * # Adding a branch (recipe)\n *\n * When the first OPTIONAL `@unimplemented` field lands (most\n * likely candidate: `seo?.{title,description}`), add the warner\n * machinery here: a `seen` set + a\n * `warn(fieldPath, sliceId)` helper that formats as\n * `[wildo-website-config] @unimplemented field '...'` and writes\n * to `process.stderr`, then the matching `if (config.<field> !==\n * undefined)` branch. Copy the exact shape from\n * `define-tech-doc-config.ts > emitUnimplementedRuntimeWarnings`\n * to keep the message format identical across helpers. The test\n * suite pins the zero-warnings contract — flip its expectation in\n * the same commit.\n */\nfunction emitUnimplementedRuntimeWarnings(_config: WildoMarketingWebsiteConfig): void {\n // Intentional no-op — see function JSDoc for why a no-op is the\n // correct shape today (optional fields are either fully wired or\n // absent) and the recipe for adding the first branch.\n}\n"]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `@wildo-ai/saas-website` — config surface.
3
+ *
4
+ * Per-service `wildo.website.config.ts` schema + `defineWebsiteConfig`
5
+ * helper. Co-located with the engine package that owns the marketing-
6
+ * site primitives so a new SEO field / locale-pack id ships in a
7
+ * single PR with no cross-package allow-list to keep in sync (see
8
+ * `wildo-website-config.schemas.ts` JSDoc for the architectural
9
+ * rationale behind moving this out of `platform-config-lib` —
10
+ * `saas-website-slice.md` Step 7.5 mirrors the
11
+ * `saas-technical-doc.md` Step 7.5 fix).
12
+ *
13
+ * @wildo-boundary
14
+ * This sub-tree is split intentionally:
15
+ *
16
+ * - `wildo-website-config.schemas.ts` — Zod-only, no Node-only
17
+ * imports, no `process.*` references. Safe to bundle anywhere.
18
+ * - `define-website-config.ts` — uses `process.stderr.write` for
19
+ * the (currently empty) `@unimplemented` warner. Bundle-safe in
20
+ * practice (the global `process` is polyfilled by every modern
21
+ * bundler and the warner has no `node:*` bare specifier), so it
22
+ * can ship through the root barrel alongside the schema.
23
+ * - `load-website-config.ts` — Node-only. Imports `loadConfig` +
24
+ * `AppFrontendType` from `@wildo-ai/platform-config-lib` and
25
+ * `node:fs` / `node:path`. Re-exported via the dedicated
26
+ * package subpath `./config-loader` (NOT from this barrel) so
27
+ * the React-island closure stays free of Node-only specifiers
28
+ * (enforced by `__tests__/bundle-isolation.test.ts`).
29
+ *
30
+ * Consumers:
31
+ * - Author per-service config: `import { defineWebsiteConfig }`
32
+ * from `'@wildo-ai/saas-website'`.
33
+ * - Load per-service config from a Node-side build / dev pipeline:
34
+ * `import { loadWebsiteConfig }` from `'@wildo-ai/saas-website/config-loader'`.
35
+ */
36
+ export * from './define-website-config';
37
+ export * from './wildo-website-config.schemas';
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `@wildo-ai/saas-website` — config surface.
3
+ *
4
+ * Per-service `wildo.website.config.ts` schema + `defineWebsiteConfig`
5
+ * helper. Co-located with the engine package that owns the marketing-
6
+ * site primitives so a new SEO field / locale-pack id ships in a
7
+ * single PR with no cross-package allow-list to keep in sync (see
8
+ * `wildo-website-config.schemas.ts` JSDoc for the architectural
9
+ * rationale behind moving this out of `platform-config-lib` —
10
+ * `saas-website-slice.md` Step 7.5 mirrors the
11
+ * `saas-technical-doc.md` Step 7.5 fix).
12
+ *
13
+ * @wildo-boundary
14
+ * This sub-tree is split intentionally:
15
+ *
16
+ * - `wildo-website-config.schemas.ts` — Zod-only, no Node-only
17
+ * imports, no `process.*` references. Safe to bundle anywhere.
18
+ * - `define-website-config.ts` — uses `process.stderr.write` for
19
+ * the (currently empty) `@unimplemented` warner. Bundle-safe in
20
+ * practice (the global `process` is polyfilled by every modern
21
+ * bundler and the warner has no `node:*` bare specifier), so it
22
+ * can ship through the root barrel alongside the schema.
23
+ * - `load-website-config.ts` — Node-only. Imports `loadConfig` +
24
+ * `AppFrontendType` from `@wildo-ai/platform-config-lib` and
25
+ * `node:fs` / `node:path`. Re-exported via the dedicated
26
+ * package subpath `./config-loader` (NOT from this barrel) so
27
+ * the React-island closure stays free of Node-only specifiers
28
+ * (enforced by `__tests__/bundle-isolation.test.ts`).
29
+ *
30
+ * Consumers:
31
+ * - Author per-service config: `import { defineWebsiteConfig }`
32
+ * from `'@wildo-ai/saas-website'`.
33
+ * - Load per-service config from a Node-side build / dev pipeline:
34
+ * `import { loadWebsiteConfig }` from `'@wildo-ai/saas-website/config-loader'`.
35
+ */
36
+ export * from './define-website-config.js';
37
+ export * from './wildo-website-config.schemas.js';
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/config/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,cAAc,yBAAyB,CAAC;AACxC,cAAc,gCAAgC,CAAC","sourcesContent":["/**\n * `@wildo-ai/saas-website` — config surface.\n *\n * Per-service `wildo.website.config.ts` schema + `defineWebsiteConfig`\n * helper. Co-located with the engine package that owns the marketing-\n * site primitives so a new SEO field / locale-pack id ships in a\n * single PR with no cross-package allow-list to keep in sync (see\n * `wildo-website-config.schemas.ts` JSDoc for the architectural\n * rationale behind moving this out of `platform-config-lib` —\n * `saas-website-slice.md` Step 7.5 mirrors the\n * `saas-technical-doc.md` Step 7.5 fix).\n *\n * @wildo-boundary\n * This sub-tree is split intentionally:\n *\n * - `wildo-website-config.schemas.ts` — Zod-only, no Node-only\n * imports, no `process.*` references. Safe to bundle anywhere.\n * - `define-website-config.ts` — uses `process.stderr.write` for\n * the (currently empty) `@unimplemented` warner. Bundle-safe in\n * practice (the global `process` is polyfilled by every modern\n * bundler and the warner has no `node:*` bare specifier), so it\n * can ship through the root barrel alongside the schema.\n * - `load-website-config.ts` — Node-only. Imports `loadConfig` +\n * `AppFrontendType` from `@wildo-ai/platform-config-lib` and\n * `node:fs` / `node:path`. Re-exported via the dedicated\n * package subpath `./config-loader` (NOT from this barrel) so\n * the React-island closure stays free of Node-only specifiers\n * (enforced by `__tests__/bundle-isolation.test.ts`).\n *\n * Consumers:\n * - Author per-service config: `import { defineWebsiteConfig }`\n * from `'@wildo-ai/saas-website'`.\n * - Load per-service config from a Node-side build / dev pipeline:\n * `import { loadWebsiteConfig }` from `'@wildo-ai/saas-website/config-loader'`.\n */\n\nexport * from './define-website-config';\nexport * from './wildo-website-config.schemas';\n"]}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @fileoverview Per-service `wildo.website.config.ts` loader.
3
+ *
4
+ * Mirrors the `loadTechnicalDocConfig()` shape used by
5
+ * `platform/factory/wildo-dev-companion/src/technical-doc/services/technical-doc.companion.service.ts`
6
+ * (see `saas-technical-doc.md` Step 7.5). Discovers the unique
7
+ * `frontendType: STATIC_WEBSITE` service in the SaaS config, joins
8
+ * `<saasRoot>/<service.path>/wildo.website.config.ts`, and loads it
9
+ * via the jiti-backed `loadConfig` from `@wildo-ai/platform-config-lib`.
10
+ *
11
+ * The actual Zod validation runs INSIDE `defineWebsiteConfig` (which
12
+ * the per-service config file invokes via
13
+ * `export default defineWebsiteConfig({...})`), so by the time
14
+ * `loadConfig` returns we already hold a parsed
15
+ * `WildoMarketingWebsiteConfig`.
16
+ *
17
+ * @wildo-boundary
18
+ * This module is **Node-only**. It imports `loadConfig` and
19
+ * `AppFrontendType` from `@wildo-ai/platform-config-lib`, which
20
+ * transitively pulls `jiti`, `node:fs`, `node:path`, `node:crypto`,
21
+ * and other Node-only API surface. It MUST NOT be imported from
22
+ * any browser-bundled entry of this engine package — specifically
23
+ * NOT from `index.ts`, `companion-exports.ts`, or `astro-island.ts`.
24
+ * The dedicated `./config-loader` package subpath exists precisely
25
+ * to keep this surface OUT of the React-island bundle (enforced by
26
+ * `__tests__/bundle-isolation.test.ts`).
27
+ *
28
+ * The Astro build's `astro.config.ts` (a Node-side file by
29
+ * construction) is the canonical caller. A future companion
30
+ * subprocess that audits the marketing surface would also call
31
+ * from here. Browser bundles MUST NOT.
32
+ */
33
+ import type { WildoSaasConfig } from '@wildo-ai/platform-config-lib';
34
+ import type { WildoMarketingWebsiteConfig } from './wildo-website-config.schemas';
35
+ /**
36
+ * Conventional file name for the per-service marketing-website
37
+ * configuration (Step 7.5 refactor — `saas-website-slice.md` /
38
+ * `saas-technical-doc.md` Step 7.5 mirror). Authored at the website
39
+ * service root next to `package.json` / `astro.config.ts`.
40
+ *
41
+ * Discovery is "by convention, not by configuration":
42
+ *
43
+ * - The loader locates this file by walking the `services` entry
44
+ * whose `frontendType === STATIC_WEBSITE` and joining
45
+ * `<saasRoot>/<service.path>/`. The saas-config schema's
46
+ * `superRefine` already enforces "at most one STATIC_WEBSITE
47
+ * service per app", so the lookup is deterministic — apps can
48
+ * name the website service anything (`'website'`, `'marketing'`,
49
+ * `'site'`).
50
+ *
51
+ * - File presence is the enable signal — there is NO `enabled`
52
+ * field on `WildoMarketingWebsiteConfigSchema`. A STATIC_WEBSITE
53
+ * service without this file is treated as a misconfiguration
54
+ * and the loader throws (rather than silently shipping an Astro
55
+ * build with no `i18n` routing / no canonical origin).
56
+ */
57
+ export declare const PER_SERVICE_WEBSITE_CONFIG_FILE_NAME = "wildo.website.config.ts";
58
+ /**
59
+ * Test helper — pre-populate the loader's memoization slot for a
60
+ * given absolute config path. Mirrors the
61
+ * `cachedTechnicalDocConfig` pre-population trick used by
62
+ * `technical-doc.publish-openapi.service.test.ts` so the loader's
63
+ * downstream consumers can be exercised in tests without writing a
64
+ * `.ts` file to disk + invoking jiti.
65
+ *
66
+ * Production callers MUST NOT use this helper.
67
+ */
68
+ export declare function primeWebsiteConfigCache(absoluteConfigPath: string, config: WildoMarketingWebsiteConfig): void;
69
+ /**
70
+ * Test helper — clear every cached entry. Use in `beforeEach`/`afterEach`
71
+ * to prevent test cross-contamination.
72
+ */
73
+ export declare function clearWebsiteConfigCache(): void;
74
+ /**
75
+ * Arguments for {@link loadWebsiteConfig}. Kept as a structured shape
76
+ * (rather than positional `loadWebsiteConfig(saasRoot, saasConfig)`)
77
+ * so that future per-call options (e.g. an explicit `serviceKey`
78
+ * override for multi-website apps the day the singleton invariant
79
+ * relaxes) slot in without breaking callers.
80
+ */
81
+ export interface LoadWebsiteConfigArgs {
82
+ /**
83
+ * Absolute path to the SaaS app root — the directory holding
84
+ * `wildo.saas.config.ts`. Used to resolve `<saasRoot>/<service.path>/`
85
+ * for the website service folder.
86
+ */
87
+ saasRoot: string;
88
+ /**
89
+ * The already-parsed SaaS config (load once via
90
+ * `loadConfig<WildoSaasConfig>(...)` upstream and pass it down here
91
+ * — re-parsing per call would invoke jiti twice for one logical
92
+ * load).
93
+ */
94
+ saasConfig: WildoSaasConfig;
95
+ }
96
+ /**
97
+ * Discover and load the per-service marketing-website config.
98
+ *
99
+ * Resolution algorithm (mirrors
100
+ * `TechnicalDocCompanionService.loadTechnicalDocConfig`):
101
+ *
102
+ * 1. Find the unique service in `saasConfig.services` whose
103
+ * `frontendType === STATIC_WEBSITE`. The saas-config
104
+ * `superRefine` guarantees there is at most one — if there is
105
+ * none, throw with the misconfiguration message.
106
+ * 2. Resolve `<saasRoot>/<service.path>/wildo.website.config.ts`.
107
+ * 3. If the file does not exist, throw (file presence IS the
108
+ * enable signal — a STATIC_WEBSITE service without this file
109
+ * is broken).
110
+ * 4. Check the memoization slot keyed on the absolute path; return
111
+ * the cached value if present.
112
+ * 5. Call `loadConfig<WildoMarketingWebsiteConfig>(absolutePath)`.
113
+ * jiti evaluates the file, which invokes `defineWebsiteConfig`,
114
+ * which invokes `WildoMarketingWebsiteConfigSchema.parse` and
115
+ * emits any `@unimplemented` warnings. The returned object is
116
+ * already-validated — we trust the in-file `defineWebsiteConfig`
117
+ * contract here (mirrors the technical-doc loader pattern in
118
+ * `TechnicalDocCompanionService.loadTechnicalDocConfig`, which
119
+ * also does NOT re-parse). A file that hand-rolls the default
120
+ * export without going through `defineWebsiteConfig` would
121
+ * surface as a downstream type mismatch — acceptable given the
122
+ * authoring contract is explicit and grep-discoverable.
123
+ * 6. Memoize and return.
124
+ *
125
+ * @throws Error with a `[wildo-website-config]` prefix if no
126
+ * STATIC_WEBSITE service is declared, the per-service config
127
+ * file is missing, or the file's default export does not
128
+ * pass `WildoMarketingWebsiteConfigSchema`. The loader
129
+ * intentionally throws plain `Error`s rather than building a
130
+ * `WildoBackendError` so it stays usable from the Astro
131
+ * build pipeline (which has no DI container) — the companion
132
+ * can wrap with `errorBuilder` at the call site if needed
133
+ * (mirrors how `loadConfig` itself throws plain `Error`).
134
+ */
135
+ export declare function loadWebsiteConfig(args: LoadWebsiteConfigArgs): Promise<WildoMarketingWebsiteConfig>;
136
+ //# sourceMappingURL=load-website-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-website-config.d.ts","sourceRoot":"","sources":["../../../../src/config/load-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAElF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,oCAAoC,4BAA4B,CAAC;AAkB9E;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,kBAAkB,EAAE,MAAM,EAC1B,MAAM,EAAE,2BAA2B,GAClC,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,2BAA2B,CAAC,CA4DtC"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * @fileoverview Per-service `wildo.website.config.ts` loader.
3
+ *
4
+ * Mirrors the `loadTechnicalDocConfig()` shape used by
5
+ * `platform/factory/wildo-dev-companion/src/technical-doc/services/technical-doc.companion.service.ts`
6
+ * (see `saas-technical-doc.md` Step 7.5). Discovers the unique
7
+ * `frontendType: STATIC_WEBSITE` service in the SaaS config, joins
8
+ * `<saasRoot>/<service.path>/wildo.website.config.ts`, and loads it
9
+ * via the jiti-backed `loadConfig` from `@wildo-ai/platform-config-lib`.
10
+ *
11
+ * The actual Zod validation runs INSIDE `defineWebsiteConfig` (which
12
+ * the per-service config file invokes via
13
+ * `export default defineWebsiteConfig({...})`), so by the time
14
+ * `loadConfig` returns we already hold a parsed
15
+ * `WildoMarketingWebsiteConfig`.
16
+ *
17
+ * @wildo-boundary
18
+ * This module is **Node-only**. It imports `loadConfig` and
19
+ * `AppFrontendType` from `@wildo-ai/platform-config-lib`, which
20
+ * transitively pulls `jiti`, `node:fs`, `node:path`, `node:crypto`,
21
+ * and other Node-only API surface. It MUST NOT be imported from
22
+ * any browser-bundled entry of this engine package — specifically
23
+ * NOT from `index.ts`, `companion-exports.ts`, or `astro-island.ts`.
24
+ * The dedicated `./config-loader` package subpath exists precisely
25
+ * to keep this surface OUT of the React-island bundle (enforced by
26
+ * `__tests__/bundle-isolation.test.ts`).
27
+ *
28
+ * The Astro build's `astro.config.ts` (a Node-side file by
29
+ * construction) is the canonical caller. A future companion
30
+ * subprocess that audits the marketing surface would also call
31
+ * from here. Browser bundles MUST NOT.
32
+ */
33
+ import { existsSync } from 'node:fs';
34
+ import { resolve as resolvePath } from 'node:path';
35
+ import { AppFrontendType, loadConfig } from '@wildo-ai/platform-config-lib';
36
+ /**
37
+ * Conventional file name for the per-service marketing-website
38
+ * configuration (Step 7.5 refactor — `saas-website-slice.md` /
39
+ * `saas-technical-doc.md` Step 7.5 mirror). Authored at the website
40
+ * service root next to `package.json` / `astro.config.ts`.
41
+ *
42
+ * Discovery is "by convention, not by configuration":
43
+ *
44
+ * - The loader locates this file by walking the `services` entry
45
+ * whose `frontendType === STATIC_WEBSITE` and joining
46
+ * `<saasRoot>/<service.path>/`. The saas-config schema's
47
+ * `superRefine` already enforces "at most one STATIC_WEBSITE
48
+ * service per app", so the lookup is deterministic — apps can
49
+ * name the website service anything (`'website'`, `'marketing'`,
50
+ * `'site'`).
51
+ *
52
+ * - File presence is the enable signal — there is NO `enabled`
53
+ * field on `WildoMarketingWebsiteConfigSchema`. A STATIC_WEBSITE
54
+ * service without this file is treated as a misconfiguration
55
+ * and the loader throws (rather than silently shipping an Astro
56
+ * build with no `i18n` routing / no canonical origin).
57
+ */
58
+ export const PER_SERVICE_WEBSITE_CONFIG_FILE_NAME = 'wildo.website.config.ts';
59
+ /**
60
+ * Memoization slot scoped to the loader module. Keyed by absolute
61
+ * config file path so multiple SaaS configs evaluated in the same
62
+ * process (rare in production — possible in tests) do not collide.
63
+ *
64
+ * Lifetime: the loader is invoked from the Astro build / dev-server
65
+ * pipeline, both of which restart the Node process on every dev-stack
66
+ * reload (the watcher that picks up changes to `wildo.website.config.ts`
67
+ * is the same watcher that reboots the build). A stale entry here
68
+ * therefore cannot outlive a config edit.
69
+ *
70
+ * Tests can pre-populate a known path via {@link primeWebsiteConfigCache}
71
+ * to skip the jiti round-trip when exercising downstream consumers.
72
+ */
73
+ const WEBSITE_CONFIG_CACHE = new Map();
74
+ /**
75
+ * Test helper — pre-populate the loader's memoization slot for a
76
+ * given absolute config path. Mirrors the
77
+ * `cachedTechnicalDocConfig` pre-population trick used by
78
+ * `technical-doc.publish-openapi.service.test.ts` so the loader's
79
+ * downstream consumers can be exercised in tests without writing a
80
+ * `.ts` file to disk + invoking jiti.
81
+ *
82
+ * Production callers MUST NOT use this helper.
83
+ */
84
+ export function primeWebsiteConfigCache(absoluteConfigPath, config) {
85
+ WEBSITE_CONFIG_CACHE.set(resolvePath(absoluteConfigPath), config);
86
+ }
87
+ /**
88
+ * Test helper — clear every cached entry. Use in `beforeEach`/`afterEach`
89
+ * to prevent test cross-contamination.
90
+ */
91
+ export function clearWebsiteConfigCache() {
92
+ WEBSITE_CONFIG_CACHE.clear();
93
+ }
94
+ /**
95
+ * Discover and load the per-service marketing-website config.
96
+ *
97
+ * Resolution algorithm (mirrors
98
+ * `TechnicalDocCompanionService.loadTechnicalDocConfig`):
99
+ *
100
+ * 1. Find the unique service in `saasConfig.services` whose
101
+ * `frontendType === STATIC_WEBSITE`. The saas-config
102
+ * `superRefine` guarantees there is at most one — if there is
103
+ * none, throw with the misconfiguration message.
104
+ * 2. Resolve `<saasRoot>/<service.path>/wildo.website.config.ts`.
105
+ * 3. If the file does not exist, throw (file presence IS the
106
+ * enable signal — a STATIC_WEBSITE service without this file
107
+ * is broken).
108
+ * 4. Check the memoization slot keyed on the absolute path; return
109
+ * the cached value if present.
110
+ * 5. Call `loadConfig<WildoMarketingWebsiteConfig>(absolutePath)`.
111
+ * jiti evaluates the file, which invokes `defineWebsiteConfig`,
112
+ * which invokes `WildoMarketingWebsiteConfigSchema.parse` and
113
+ * emits any `@unimplemented` warnings. The returned object is
114
+ * already-validated — we trust the in-file `defineWebsiteConfig`
115
+ * contract here (mirrors the technical-doc loader pattern in
116
+ * `TechnicalDocCompanionService.loadTechnicalDocConfig`, which
117
+ * also does NOT re-parse). A file that hand-rolls the default
118
+ * export without going through `defineWebsiteConfig` would
119
+ * surface as a downstream type mismatch — acceptable given the
120
+ * authoring contract is explicit and grep-discoverable.
121
+ * 6. Memoize and return.
122
+ *
123
+ * @throws Error with a `[wildo-website-config]` prefix if no
124
+ * STATIC_WEBSITE service is declared, the per-service config
125
+ * file is missing, or the file's default export does not
126
+ * pass `WildoMarketingWebsiteConfigSchema`. The loader
127
+ * intentionally throws plain `Error`s rather than building a
128
+ * `WildoBackendError` so it stays usable from the Astro
129
+ * build pipeline (which has no DI container) — the companion
130
+ * can wrap with `errorBuilder` at the call site if needed
131
+ * (mirrors how `loadConfig` itself throws plain `Error`).
132
+ */
133
+ export async function loadWebsiteConfig(args) {
134
+ const { saasRoot, saasConfig } = args;
135
+ const websiteServiceEntry = Object.entries(saasConfig.services).find(([, service]) => service.frontendType === AppFrontendType.STATIC_WEBSITE);
136
+ if (!websiteServiceEntry) {
137
+ throw new Error('[wildo-website-config] No frontend service with `frontendType: STATIC_WEBSITE` is declared in '
138
+ + 'wildo.saas.config.ts. The marketing-website Astro build / loader requires an authored '
139
+ + 'STATIC_WEBSITE service because that service folder owns the per-service '
140
+ + '`wildo.website.config.ts` (publicOrigin, appOrigin, defaultLocale, locales). '
141
+ + 'Add a STATIC_WEBSITE service in wildo.saas.config.ts and ship the per-service '
142
+ + 'config file under it.');
143
+ }
144
+ const [websiteServiceKey, websiteService] = websiteServiceEntry;
145
+ const websiteConfigPath = resolvePath(saasRoot, websiteService.path, PER_SERVICE_WEBSITE_CONFIG_FILE_NAME);
146
+ const cached = WEBSITE_CONFIG_CACHE.get(websiteConfigPath);
147
+ if (cached !== undefined) {
148
+ return cached;
149
+ }
150
+ if (!existsSync(websiteConfigPath)) {
151
+ throw new Error(`[wildo-website-config] STATIC_WEBSITE service '${websiteServiceKey}' is declared in `
152
+ + `wildo.saas.config.ts but the required per-service config file `
153
+ + `'${PER_SERVICE_WEBSITE_CONFIG_FILE_NAME}' is missing under `
154
+ + `'${websiteService.path}/'. File presence IS the enable signal `
155
+ + '(saas-website-slice.md / saas-technical-doc.md Step 7.5 — the legacy '
156
+ + '`marketingWebsite` block on wildo.saas.config.ts was dropped in favor of '
157
+ + 'a per-service file). Create '
158
+ + `'${websiteConfigPath}' with `
159
+ + '`export default defineWebsiteConfig({ ... })` from `@wildo-ai/saas-website`.');
160
+ }
161
+ let loaded;
162
+ try {
163
+ loaded = await loadConfig(websiteConfigPath);
164
+ }
165
+ catch (e) {
166
+ const cause = e instanceof Error ? e.message : String(e);
167
+ throw new Error(`[wildo-website-config] Failed to load per-service marketing-website config at `
168
+ + `${websiteConfigPath}. The file MUST do `
169
+ + '`export default defineWebsiteConfig({...})` and pass '
170
+ + 'WildoMarketingWebsiteConfigSchema (`z.strictObject` — unknown keys reject; '
171
+ + '`defaultLocale` must appear in `locales`). '
172
+ + `Cause: ${cause}`);
173
+ }
174
+ WEBSITE_CONFIG_CACHE.set(websiteConfigPath, loaded);
175
+ return loaded;
176
+ }
177
+ //# sourceMappingURL=load-website-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-website-config.js","sourceRoot":"","sources":["../../../../src/config/load-website-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAI5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,yBAAyB,CAAC;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAuC,CAAC;AAE5E;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,kBAA0B,EAC1B,MAAmC;IAEnC,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB;IACrC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAC/B,CAAC;AAyBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAA2B;IAE3B,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAEtC,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAClE,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,KAAK,eAAe,CAAC,cAAc,CACzE,CAAC;IACF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CACb,gGAAgG;cAC5F,wFAAwF;cACxF,0EAA0E;cAC1E,+EAA+E;cAC/E,gFAAgF;cAChF,uBAAuB,CAC5B,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC,GAAG,mBAAmB,CAAC;IAChE,MAAM,iBAAiB,GAAG,WAAW,CACnC,QAAQ,EACR,cAAc,CAAC,IAAI,EACnB,oCAAoC,CACrC,CAAC;IAEF,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC3D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,kDAAkD,iBAAiB,mBAAmB;cAClF,gEAAgE;cAChE,IAAI,oCAAoC,qBAAqB;cAC7D,IAAI,cAAc,CAAC,IAAI,yCAAyC;cAChE,uEAAuE;cACvE,2EAA2E;cAC3E,8BAA8B;cAC9B,IAAI,iBAAiB,SAAS;cAC9B,8EAA8E,CACnF,CAAC;IACJ,CAAC;IAED,IAAI,MAAmC,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,UAAU,CAA8B,iBAAiB,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,gFAAgF;cAC5E,GAAG,iBAAiB,qBAAqB;cACzC,uDAAuD;cACvD,6EAA6E;cAC7E,6CAA6C;cAC7C,UAAU,KAAK,EAAE,CACtB,CAAC;IACJ,CAAC;IAED,oBAAoB,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * @fileoverview Per-service `wildo.website.config.ts` loader.\n *\n * Mirrors the `loadTechnicalDocConfig()` shape used by\n * `platform/factory/wildo-dev-companion/src/technical-doc/services/technical-doc.companion.service.ts`\n * (see `saas-technical-doc.md` Step 7.5). Discovers the unique\n * `frontendType: STATIC_WEBSITE` service in the SaaS config, joins\n * `<saasRoot>/<service.path>/wildo.website.config.ts`, and loads it\n * via the jiti-backed `loadConfig` from `@wildo-ai/platform-config-lib`.\n *\n * The actual Zod validation runs INSIDE `defineWebsiteConfig` (which\n * the per-service config file invokes via\n * `export default defineWebsiteConfig({...})`), so by the time\n * `loadConfig` returns we already hold a parsed\n * `WildoMarketingWebsiteConfig`.\n *\n * @wildo-boundary\n * This module is **Node-only**. It imports `loadConfig` and\n * `AppFrontendType` from `@wildo-ai/platform-config-lib`, which\n * transitively pulls `jiti`, `node:fs`, `node:path`, `node:crypto`,\n * and other Node-only API surface. It MUST NOT be imported from\n * any browser-bundled entry of this engine package — specifically\n * NOT from `index.ts`, `companion-exports.ts`, or `astro-island.ts`.\n * The dedicated `./config-loader` package subpath exists precisely\n * to keep this surface OUT of the React-island bundle (enforced by\n * `__tests__/bundle-isolation.test.ts`).\n *\n * The Astro build's `astro.config.ts` (a Node-side file by\n * construction) is the canonical caller. A future companion\n * subprocess that audits the marketing surface would also call\n * from here. Browser bundles MUST NOT.\n */\n\nimport { existsSync } from 'node:fs';\nimport { resolve as resolvePath } from 'node:path';\nimport { AppFrontendType, loadConfig } from '@wildo-ai/platform-config-lib';\nimport type { WildoSaasConfig } from '@wildo-ai/platform-config-lib';\nimport type { WildoMarketingWebsiteConfig } from './wildo-website-config.schemas';\n\n/**\n * Conventional file name for the per-service marketing-website\n * configuration (Step 7.5 refactor — `saas-website-slice.md` /\n * `saas-technical-doc.md` Step 7.5 mirror). Authored at the website\n * service root next to `package.json` / `astro.config.ts`.\n *\n * Discovery is \"by convention, not by configuration\":\n *\n * - The loader locates this file by walking the `services` entry\n * whose `frontendType === STATIC_WEBSITE` and joining\n * `<saasRoot>/<service.path>/`. The saas-config schema's\n * `superRefine` already enforces \"at most one STATIC_WEBSITE\n * service per app\", so the lookup is deterministic — apps can\n * name the website service anything (`'website'`, `'marketing'`,\n * `'site'`).\n *\n * - File presence is the enable signal — there is NO `enabled`\n * field on `WildoMarketingWebsiteConfigSchema`. A STATIC_WEBSITE\n * service without this file is treated as a misconfiguration\n * and the loader throws (rather than silently shipping an Astro\n * build with no `i18n` routing / no canonical origin).\n */\nexport const PER_SERVICE_WEBSITE_CONFIG_FILE_NAME = 'wildo.website.config.ts';\n\n/**\n * Memoization slot scoped to the loader module. Keyed by absolute\n * config file path so multiple SaaS configs evaluated in the same\n * process (rare in production — possible in tests) do not collide.\n *\n * Lifetime: the loader is invoked from the Astro build / dev-server\n * pipeline, both of which restart the Node process on every dev-stack\n * reload (the watcher that picks up changes to `wildo.website.config.ts`\n * is the same watcher that reboots the build). A stale entry here\n * therefore cannot outlive a config edit.\n *\n * Tests can pre-populate a known path via {@link primeWebsiteConfigCache}\n * to skip the jiti round-trip when exercising downstream consumers.\n */\nconst WEBSITE_CONFIG_CACHE = new Map<string, WildoMarketingWebsiteConfig>();\n\n/**\n * Test helper — pre-populate the loader's memoization slot for a\n * given absolute config path. Mirrors the\n * `cachedTechnicalDocConfig` pre-population trick used by\n * `technical-doc.publish-openapi.service.test.ts` so the loader's\n * downstream consumers can be exercised in tests without writing a\n * `.ts` file to disk + invoking jiti.\n *\n * Production callers MUST NOT use this helper.\n */\nexport function primeWebsiteConfigCache(\n absoluteConfigPath: string,\n config: WildoMarketingWebsiteConfig,\n): void {\n WEBSITE_CONFIG_CACHE.set(resolvePath(absoluteConfigPath), config);\n}\n\n/**\n * Test helper — clear every cached entry. Use in `beforeEach`/`afterEach`\n * to prevent test cross-contamination.\n */\nexport function clearWebsiteConfigCache(): void {\n WEBSITE_CONFIG_CACHE.clear();\n}\n\n/**\n * Arguments for {@link loadWebsiteConfig}. Kept as a structured shape\n * (rather than positional `loadWebsiteConfig(saasRoot, saasConfig)`)\n * so that future per-call options (e.g. an explicit `serviceKey`\n * override for multi-website apps the day the singleton invariant\n * relaxes) slot in without breaking callers.\n */\nexport interface LoadWebsiteConfigArgs {\n /**\n * Absolute path to the SaaS app root — the directory holding\n * `wildo.saas.config.ts`. Used to resolve `<saasRoot>/<service.path>/`\n * for the website service folder.\n */\n saasRoot: string;\n /**\n * The already-parsed SaaS config (load once via\n * `loadConfig<WildoSaasConfig>(...)` upstream and pass it down here\n * — re-parsing per call would invoke jiti twice for one logical\n * load).\n */\n saasConfig: WildoSaasConfig;\n}\n\n/**\n * Discover and load the per-service marketing-website config.\n *\n * Resolution algorithm (mirrors\n * `TechnicalDocCompanionService.loadTechnicalDocConfig`):\n *\n * 1. Find the unique service in `saasConfig.services` whose\n * `frontendType === STATIC_WEBSITE`. The saas-config\n * `superRefine` guarantees there is at most one — if there is\n * none, throw with the misconfiguration message.\n * 2. Resolve `<saasRoot>/<service.path>/wildo.website.config.ts`.\n * 3. If the file does not exist, throw (file presence IS the\n * enable signal — a STATIC_WEBSITE service without this file\n * is broken).\n * 4. Check the memoization slot keyed on the absolute path; return\n * the cached value if present.\n * 5. Call `loadConfig<WildoMarketingWebsiteConfig>(absolutePath)`.\n * jiti evaluates the file, which invokes `defineWebsiteConfig`,\n * which invokes `WildoMarketingWebsiteConfigSchema.parse` and\n * emits any `@unimplemented` warnings. The returned object is\n * already-validated — we trust the in-file `defineWebsiteConfig`\n * contract here (mirrors the technical-doc loader pattern in\n * `TechnicalDocCompanionService.loadTechnicalDocConfig`, which\n * also does NOT re-parse). A file that hand-rolls the default\n * export without going through `defineWebsiteConfig` would\n * surface as a downstream type mismatch — acceptable given the\n * authoring contract is explicit and grep-discoverable.\n * 6. Memoize and return.\n *\n * @throws Error with a `[wildo-website-config]` prefix if no\n * STATIC_WEBSITE service is declared, the per-service config\n * file is missing, or the file's default export does not\n * pass `WildoMarketingWebsiteConfigSchema`. The loader\n * intentionally throws plain `Error`s rather than building a\n * `WildoBackendError` so it stays usable from the Astro\n * build pipeline (which has no DI container) — the companion\n * can wrap with `errorBuilder` at the call site if needed\n * (mirrors how `loadConfig` itself throws plain `Error`).\n */\nexport async function loadWebsiteConfig(\n args: LoadWebsiteConfigArgs,\n): Promise<WildoMarketingWebsiteConfig> {\n const { saasRoot, saasConfig } = args;\n\n const websiteServiceEntry = Object.entries(saasConfig.services).find(\n ([, service]) => service.frontendType === AppFrontendType.STATIC_WEBSITE,\n );\n if (!websiteServiceEntry) {\n throw new Error(\n '[wildo-website-config] No frontend service with `frontendType: STATIC_WEBSITE` is declared in '\n + 'wildo.saas.config.ts. The marketing-website Astro build / loader requires an authored '\n + 'STATIC_WEBSITE service because that service folder owns the per-service '\n + '`wildo.website.config.ts` (publicOrigin, appOrigin, defaultLocale, locales). '\n + 'Add a STATIC_WEBSITE service in wildo.saas.config.ts and ship the per-service '\n + 'config file under it.',\n );\n }\n\n const [websiteServiceKey, websiteService] = websiteServiceEntry;\n const websiteConfigPath = resolvePath(\n saasRoot,\n websiteService.path,\n PER_SERVICE_WEBSITE_CONFIG_FILE_NAME,\n );\n\n const cached = WEBSITE_CONFIG_CACHE.get(websiteConfigPath);\n if (cached !== undefined) {\n return cached;\n }\n\n if (!existsSync(websiteConfigPath)) {\n throw new Error(\n `[wildo-website-config] STATIC_WEBSITE service '${websiteServiceKey}' is declared in `\n + `wildo.saas.config.ts but the required per-service config file `\n + `'${PER_SERVICE_WEBSITE_CONFIG_FILE_NAME}' is missing under `\n + `'${websiteService.path}/'. File presence IS the enable signal `\n + '(saas-website-slice.md / saas-technical-doc.md Step 7.5 — the legacy '\n + '`marketingWebsite` block on wildo.saas.config.ts was dropped in favor of '\n + 'a per-service file). Create '\n + `'${websiteConfigPath}' with `\n + '`export default defineWebsiteConfig({ ... })` from `@wildo-ai/saas-website`.',\n );\n }\n\n let loaded: WildoMarketingWebsiteConfig;\n try {\n loaded = await loadConfig<WildoMarketingWebsiteConfig>(websiteConfigPath);\n } catch (e) {\n const cause = e instanceof Error ? e.message : String(e);\n throw new Error(\n `[wildo-website-config] Failed to load per-service marketing-website config at `\n + `${websiteConfigPath}. The file MUST do `\n + '`export default defineWebsiteConfig({...})` and pass '\n + 'WildoMarketingWebsiteConfigSchema (`z.strictObject` — unknown keys reject; '\n + '`defaultLocale` must appear in `locales`). '\n + `Cause: ${cause}`,\n );\n }\n\n WEBSITE_CONFIG_CACHE.set(websiteConfigPath, loaded);\n return loaded;\n}\n"]}