@gradial/aci 0.1.52-rc.3 → 0.1.52-rc.34-e2e.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 (276) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +86 -5
  3. package/dist/astro/error-page.js +1 -0
  4. package/dist/astro/index.js +4 -0
  5. package/dist/astro/page.d.ts +5 -2
  6. package/dist/astro/page.js +35 -23
  7. package/dist/astro/preview.js +2 -17
  8. package/dist/audience-data-models.d.ts +308 -194
  9. package/dist/audience-data-models.js +314 -51
  10. package/dist/cli/compile-registry.d.mts +5 -1
  11. package/dist/cli/compile-registry.mjs +31 -46
  12. package/dist/cli/mintlify-render.mjs +8 -0
  13. package/dist/cli/validate-content.d.mts +31 -1
  14. package/dist/cli/validate-content.mjs +50 -12
  15. package/dist/collect/aci.js +1 -1
  16. package/dist/collect/aci.js.sha256 +1 -1
  17. package/dist/collect/api.d.ts +6 -7
  18. package/dist/collect/api.js +21 -8
  19. package/dist/collect/assignments.d.ts +7 -9
  20. package/dist/collect/assignments.js +23 -32
  21. package/dist/collect/batcher.d.ts +9 -7
  22. package/dist/collect/batcher.js +6 -5
  23. package/dist/collect/consent/envelope.d.ts +7 -1
  24. package/dist/collect/consent/envelope.js +3 -1
  25. package/dist/collect/consent/mapping.d.ts +2 -0
  26. package/dist/collect/consent/mapping.js +1 -0
  27. package/dist/collect/consenthold.d.ts +38 -0
  28. package/dist/collect/consenthold.js +82 -0
  29. package/dist/collect/declarative.js +7 -5
  30. package/dist/collect/gapbuffer.d.ts +13 -4
  31. package/dist/collect/gapbuffer.js +21 -10
  32. package/dist/collect/index.js +67 -20
  33. package/dist/collect/pageviews.d.ts +11 -11
  34. package/dist/collect/pageviews.js +27 -22
  35. package/dist/consent-banner/index.d.ts +17 -0
  36. package/dist/consent-banner/index.js +23 -0
  37. package/dist/content/index.d.ts +2 -1
  38. package/dist/content/index.js +4 -1
  39. package/dist/content/provider.d.ts +16 -2
  40. package/dist/content/provider.js +5 -1
  41. package/dist/content/resolve-slots.d.ts +33 -4
  42. package/dist/content/resolve-slots.js +127 -19
  43. package/dist/content/types.d.ts +7 -1
  44. package/dist/edge/expression-capabilities.v1.d.ts +106 -0
  45. package/dist/edge/expression-capabilities.v1.js +165 -0
  46. package/dist/index.d.ts +1 -2
  47. package/dist/index.js +0 -1
  48. package/dist/internal/domain/edge/compose.d.ts +24 -0
  49. package/dist/internal/domain/edge/compose.js +89 -0
  50. package/dist/internal/domain/edge/identity.d.ts +5 -0
  51. package/dist/internal/domain/edge/identity.js +50 -14
  52. package/dist/internal/domain/edge/index.d.ts +2 -0
  53. package/dist/internal/domain/edge/index.js +2 -0
  54. package/dist/internal/domain/edge/mimic_token.d.ts +14 -0
  55. package/dist/internal/domain/edge/mimic_token.js +125 -0
  56. package/dist/internal/domain/edge/personalization-core.d.ts +61 -22
  57. package/dist/internal/domain/edge/personalization-core.js +789 -198
  58. package/dist/internal/domain/edge/personalization_index.d.ts +17 -0
  59. package/dist/internal/domain/edge/personalization_index.js +56 -0
  60. package/dist/internal/domain/edge/record/codec.d.ts +6 -32
  61. package/dist/internal/domain/edge/record/codec.js +86 -168
  62. package/dist/internal/domain/edge/resolve.js +76 -39
  63. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.d.ts +10 -0
  64. package/dist/internal/domain/edge/testdata/flat_only_validator_v1.js +253 -0
  65. package/dist/internal/domain/edge/types.d.ts +93 -41
  66. package/dist/internal/domain/edge/types.js +3 -3
  67. package/dist/internal/domain/edge/variant_key.d.ts +3 -0
  68. package/dist/internal/domain/edge/variant_key.js +44 -0
  69. package/dist/internal/platform/collectionstore/errors.d.ts +24 -0
  70. package/dist/internal/platform/collectionstore/errors.js +48 -0
  71. package/dist/mimic/core.d.ts +2 -0
  72. package/dist/mimic/core.js +31 -0
  73. package/dist/mintlify/blocks.d.ts +6 -0
  74. package/dist/mintlify/blocks.js +201 -0
  75. package/dist/mintlify/config.d.ts +3 -0
  76. package/dist/mintlify/config.js +77 -0
  77. package/dist/mintlify/index.d.ts +3 -0
  78. package/dist/mintlify/index.js +2 -0
  79. package/dist/mintlify/json.d.ts +8 -0
  80. package/dist/mintlify/json.js +37 -0
  81. package/dist/mintlify/materialize.d.ts +14 -0
  82. package/dist/mintlify/materialize.js +254 -0
  83. package/dist/mintlify/types.d.ts +74 -0
  84. package/dist/mintlify/types.js +1 -0
  85. package/dist/mintlify/validate.d.ts +7 -0
  86. package/dist/mintlify/validate.js +256 -0
  87. package/dist/next/assignments-navigation.d.ts +4 -0
  88. package/dist/next/assignments-navigation.js +18 -0
  89. package/dist/next/assignments-script.d.ts +3 -2
  90. package/dist/next/assignments-script.js +5 -5
  91. package/dist/next/error-pages.d.ts +4 -0
  92. package/dist/next/error-pages.js +4 -0
  93. package/dist/next/error-seat-payload.d.ts +2 -1
  94. package/dist/next/error-seat-payload.js +14 -24
  95. package/dist/next/error-seat.js +7 -2
  96. package/dist/next/hosted-page-target.d.ts +7 -0
  97. package/dist/next/hosted-page-target.js +39 -0
  98. package/dist/next/index.d.ts +1 -1
  99. package/dist/next/index.js +3 -1
  100. package/dist/next/page.d.ts +29 -6
  101. package/dist/next/page.js +47 -25
  102. package/dist/next/release-context.d.ts +29 -0
  103. package/dist/next/release-context.js +55 -0
  104. package/dist/next/render.d.ts +1 -1
  105. package/dist/next/render.js +15 -5
  106. package/dist/next/server.d.ts +8 -0
  107. package/dist/next/server.js +44 -3
  108. package/dist/next/vercel-edge-projection-v1.d.ts +0 -9
  109. package/dist/next/vercel-edge-projection-v1.js +9 -539
  110. package/dist/preview/core.d.ts +1 -0
  111. package/dist/preview/core.js +27 -0
  112. package/dist/react/VideoPlayer.d.ts +3 -3
  113. package/dist/react/VideoPlayer.js +2 -2
  114. package/dist/react/index.d.ts +4 -4
  115. package/dist/react/index.js +2 -3
  116. package/dist/registry.d.ts +4 -2
  117. package/dist/testing/conformance/checks.d.ts +2 -2
  118. package/dist/testing/conformance/checks.js +2 -0
  119. package/dist/testing/conformance/index.d.ts +1 -0
  120. package/dist/testing/conformance/index.js +1 -0
  121. package/dist/testing/conformance/next-stubs.d.ts +6 -0
  122. package/dist/testing/conformance/next-stubs.js +9 -0
  123. package/dist/testing/conformance/preset.d.ts +3 -2
  124. package/dist/testing/conformance/preset.js +15 -8
  125. package/dist/testing/conformance/root-identity.d.ts +31 -0
  126. package/dist/testing/conformance/root-identity.js +361 -0
  127. package/dist/testing/conformance/stubs/next-image.d.ts +7 -0
  128. package/dist/testing/conformance/stubs/next-image.js +5 -0
  129. package/dist/testing/conformance/stubs/next-link.d.ts +7 -0
  130. package/dist/testing/conformance/stubs/next-link.js +4 -0
  131. package/dist/testing/conformance/types.d.ts +5 -2
  132. package/dist/testing/index.d.ts +1 -1
  133. package/dist/testing/index.js +4 -3
  134. package/dist/types/block-ref.d.ts +2 -0
  135. package/dist/types/block-ref.js +3 -2
  136. package/dist/types/component.d.ts +9 -0
  137. package/dist/types/config.d.ts +0 -1
  138. package/dist/types/image.d.ts +54 -17
  139. package/dist/types/image.js +102 -18
  140. package/dist/types/index.d.ts +0 -1
  141. package/dist/types/index.js +0 -1
  142. package/dist/types/media.d.ts +14 -6
  143. package/dist/types/page.d.ts +0 -1
  144. package/dist/types/video.d.ts +7 -3
  145. package/migrations/conformance-registry.md +22 -0
  146. package/package.json +21 -7
  147. package/src/cli/compile-registry.mjs +30 -42
  148. package/src/cli/mintlify-render.mjs +9 -0
  149. package/src/cli/validate-content.mjs +52 -13
  150. package/src/types/block-ref.test.ts +60 -0
  151. package/src/types/block-ref.ts +4 -2
  152. package/src/types/component.ts +10 -0
  153. package/src/types/config.ts +0 -1
  154. package/src/types/image.ts +133 -29
  155. package/src/types/index.ts +0 -1
  156. package/src/types/page.ts +0 -1
  157. package/src/types/video.ts +1 -1
  158. package/templates/astro/starter-content/src/components/chrome/Footer.astro +5 -3
  159. package/templates/astro/starter-content/src/components/chrome/Header.astro +5 -3
  160. package/templates/astro/starter-content/src/components/elements/Button.astro +5 -2
  161. package/templates/astro/starter-content/src/components/elements/ButtonBlock.astro +5 -3
  162. package/templates/astro/starter-content/src/components/sections/ContainerSection.astro +4 -3
  163. package/templates/astro/starter-content/src/components/sections/FeatureCard.astro +4 -3
  164. package/templates/astro/starter-content/src/components/sections/FeatureGrid.astro +4 -3
  165. package/templates/astro/starter-content/src/components/sections/HomeHero.astro +5 -3
  166. package/templates/astro/starter-content/src/components/sections/PersonalizationChoice.astro +4 -3
  167. package/templates/astro/starter-content/src/components/sections/StatsBar.astro +4 -3
  168. package/templates/astro/starter-content/src/fixtures/atomicBlocks.ts +7 -6
  169. package/templates/astro/starter-content/src/fixtures/composition.ts +3 -2
  170. package/templates/astro/starter-content/src/fixtures/sections.ts +3 -3
  171. package/templates/astro/starter-content/src/stories/CompositionStoryFrame.astro +7 -2
  172. package/templates/astro/template/.aci.yaml.tmpl +0 -1
  173. package/templates/astro/template/package.json.tmpl +5 -5
  174. package/templates/astro/template/src/layouts/SiteLayout.astro +2 -2
  175. package/templates/common/.agents/skills/aci/SKILL.md +58 -1
  176. package/templates/common/.agents/skills/authoring/SKILL.md +203 -43
  177. package/templates/common/.agents/skills/authoring/references/block-registry.md +19 -3
  178. package/templates/common/.agents/skills/authoring/references/block-slots.md +3 -0
  179. package/templates/common/.agents/skills/authoring/references/contracts.md +9 -30
  180. package/templates/common/.agents/skills/authoring/references/repo-structure.md +5 -4
  181. package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +3 -3
  182. package/templates/common/.agents/skills/dam-delivery/SKILL.md +217 -0
  183. package/templates/common/.agents/skills/dam-delivery/references/permalink-grammar.md +167 -0
  184. package/templates/common/.agents/skills/migration/references/canon-migration.md +18 -67
  185. package/templates/common/.agents/skills/migration/references/selector-map.md +1 -1
  186. package/templates/common/.content/fragments/navbar/_index.json +24 -0
  187. package/templates/common/.content/fragments/site-footer/_index.json +61 -0
  188. package/templates/common/.content/pages/404/_index.json +4 -2
  189. package/templates/common/.content/pages/{home/_index.json → _index.json} +10 -1
  190. package/templates/common/.content/pages/error/_index.json +4 -2
  191. package/templates/common/.content/schemas/site.schema.json +11 -1
  192. package/templates/common/.content/templates/error.json +24 -0
  193. package/templates/common/.content/templates/home.json +28 -0
  194. package/templates/common/.content/templates/site.json +8 -0
  195. package/templates/common/.content/templates/standard.json +24 -0
  196. package/templates/common/.nvmrc +1 -1
  197. package/templates/common/starter-content/.content/.rules-baseline.json +8 -0
  198. package/templates/common/starter-content/.content/config/site.json +1 -1
  199. package/templates/common/starter-content/.content/content-rules/no-public-resource-paths.json +6 -0
  200. package/templates/common/starter-content/.content/dam/README.md +74 -0
  201. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/asset.json +1 -1
  202. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000101}/governance.json +2 -1
  203. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/asset.json +1 -1
  204. package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000102}/governance.json +2 -1
  205. package/templates/common/starter-content/.content/fragments/navbar/_index.json +23 -20
  206. package/templates/common/starter-content/.content/fragments/site-footer/_index.json +59 -56
  207. package/templates/common/starter-content/.content/pages/404/_index.json +2 -2
  208. package/templates/common/starter-content/.content/pages/{home/_index.json → _index.json} +23 -3
  209. package/templates/common/starter-content/.content/pages/about/_index.json +5 -2
  210. package/templates/common/starter-content/.content/pages/error/_index.json +2 -2
  211. package/templates/common/starter-content/.content/patterns/components/button.json +55 -0
  212. package/templates/common/starter-content/.content/patterns/components/container.json +67 -0
  213. package/templates/common/starter-content/.content/patterns/components/feature_card.json +30 -0
  214. package/templates/common/starter-content/.content/patterns/components/feature_grid.json +59 -0
  215. package/templates/common/starter-content/.content/patterns/components/home_hero.json +151 -0
  216. package/templates/common/starter-content/.content/patterns/components/personalization_choice.json +42 -0
  217. package/templates/common/starter-content/.content/patterns/components/site-footer.json +203 -0
  218. package/templates/common/starter-content/.content/patterns/components/site-navigation.json +115 -0
  219. package/templates/common/starter-content/.content/patterns/components/stats_bar.json +45 -0
  220. package/templates/common/starter-content/.content/schemas/site.schema.json +11 -1
  221. package/templates/nextjs/starter-content/src/components/chrome/Footer.tsx +4 -3
  222. package/templates/nextjs/starter-content/src/components/chrome/Header.tsx +4 -3
  223. package/templates/nextjs/starter-content/src/components/elements/Button.tsx +4 -3
  224. package/templates/nextjs/starter-content/src/components/elements/ButtonBlock.tsx +4 -3
  225. package/templates/nextjs/starter-content/src/components/sections/ContainerSection.tsx +4 -2
  226. package/templates/nextjs/starter-content/src/components/sections/FeatureCard.tsx +4 -3
  227. package/templates/nextjs/starter-content/src/components/sections/FeatureGrid.tsx +4 -2
  228. package/templates/nextjs/starter-content/src/components/sections/HomeHero.tsx +4 -3
  229. package/templates/nextjs/starter-content/src/components/sections/PersonalizationChoice.tsx +4 -2
  230. package/templates/nextjs/starter-content/src/components/sections/StatsBar.tsx +4 -3
  231. package/templates/nextjs/template/.aci.yaml +9 -0
  232. package/templates/nextjs/template/.aci.yaml.tmpl +0 -1
  233. package/templates/nextjs/template/package.json.tmpl +4 -3
  234. package/templates/nextjs/template/src/app/_components/c15t-bridge.ts +30 -0
  235. package/templates/nextjs/template/src/app/_components/c15t-consent-ui.tsx +37 -0
  236. package/templates/nextjs/template/src/app/_components/consent-manager.css +63 -0
  237. package/templates/nextjs/template/src/app/_components/consent-manager.tsx +76 -0
  238. package/templates/nextjs/template/src/app/fonts/inter/OFL.txt +93 -0
  239. package/templates/nextjs/template/src/app/fonts/inter/inter-latin.woff2 +0 -0
  240. package/templates/nextjs/template/src/app/fonts/space-grotesk/OFL.txt +93 -0
  241. package/templates/nextjs/template/src/app/fonts/space-grotesk/space-grotesk-latin.woff2 +0 -0
  242. package/templates/nextjs/template/src/app/layout.tsx +12 -7
  243. package/templates/nextjs/template/tests/conformance.test.ts.tmpl +1 -0
  244. package/dist/define-layout.d.ts +0 -6
  245. package/dist/define-layout.js +0 -14
  246. package/dist/edge/personalization-core.d.ts +0 -11
  247. package/dist/edge/personalization-core.js +0 -269
  248. package/dist/next/collect-route.d.ts +0 -19
  249. package/dist/next/collect-route.js +0 -459
  250. package/dist/next/envelope-digest.d.ts +0 -21
  251. package/dist/next/envelope-digest.js +0 -58
  252. package/dist/next/middleware.d.ts +0 -40
  253. package/dist/next/middleware.js +0 -475
  254. package/dist/next/personalization-host.d.ts +0 -134
  255. package/dist/next/personalization-host.js +0 -270
  256. package/dist/next/root-layout.d.ts +0 -4
  257. package/dist/next/root-layout.js +0 -5
  258. package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
  259. package/dist/next/vercel-collect-sdk-route.js +0 -181
  260. package/dist/next/vercel-personalization.d.ts +0 -4
  261. package/dist/next/vercel-personalization.js +0 -4
  262. package/dist/next/vercel-s3-personalization.d.ts +0 -79
  263. package/dist/next/vercel-s3-personalization.js +0 -570
  264. package/dist/types/layout.d.ts +0 -24
  265. package/src/types/layout.ts +0 -29
  266. package/templates/astro/starter-content/src/render/RenderPage.astro +0 -67
  267. package/templates/astro/template/src/cms/contracts/layouts/index.ts +0 -18
  268. package/templates/nextjs/starter-content/src/components/elements/AtomicBlock.tsx +0 -13
  269. package/templates/nextjs/template/src/cms/contracts/layouts/index.ts +0 -16
  270. /package/dist/{types/layout.js → cli/mintlify-render.d.mts} +0 -0
  271. /package/templates/common/.content/overlays/audience/preference-blue/pages/{home/_index.json → _index.json} +0 -0
  272. /package/templates/common/.content/overlays/audience/preference-red/pages/{home/_index.json → _index.json} +0 -0
  273. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/editorial.json +0 -0
  274. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_home_hero → 000000000000000000000000101}/versions/v0001.json +0 -0
  275. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/editorial.json +0 -0
  276. /package/templates/common/starter-content/.content/dam/folders/seed/{ast_site_about_hero → 000000000000000000000000102}/versions/v0001.json +0 -0
@@ -0,0 +1,74 @@
1
+ import type { FragmentRefNode } from '../types/page.js';
2
+ export type MintlifyJSONValue = null | boolean | number | string | MintlifyJSONValue[] | {
3
+ [key: string]: MintlifyJSONValue;
4
+ };
5
+ export interface MintlifyNavigationGroup {
6
+ group: string;
7
+ pages: string[];
8
+ }
9
+ /** Native Mintlify docs.json configuration from `.content/config/mintlify.json`. */
10
+ export type MintlifySite = Record<string, MintlifyJSONValue>;
11
+ export interface MintlifyBlock {
12
+ $type: 'component';
13
+ id: string;
14
+ component: 'mintlify.markdown' | 'mintlify.mdx' | 'mintlify.anchor' | 'mintlify.steps' | 'mintlify.step' | 'mintlify.card-group' | 'mintlify.card' | 'mintlify.accordion-group' | 'mintlify.accordion' | 'mintlify.callout' | 'mintlify.tabs' | 'mintlify.tab' | 'mintlify.snippet-ref';
15
+ props: {
16
+ source?: string;
17
+ name?: string;
18
+ variant?: 'info' | 'warning' | 'note' | 'tip' | 'check';
19
+ children?: MintlifyBlock[];
20
+ [key: string]: MintlifyJSONValue | MintlifyBlock[] | undefined;
21
+ };
22
+ }
23
+ export interface MintlifyDocument {
24
+ $type: 'page';
25
+ id: string;
26
+ status: string;
27
+ path: string;
28
+ metadata: {
29
+ title: string;
30
+ description?: string;
31
+ mintlify?: {
32
+ sidebarTitle?: string;
33
+ icon?: string;
34
+ frontmatter?: Record<string, MintlifyJSONValue>;
35
+ };
36
+ };
37
+ regions: {
38
+ main: MintlifyBlock[];
39
+ };
40
+ }
41
+ export interface MintlifySnippet {
42
+ $type: 'fragment';
43
+ id: string;
44
+ path: string;
45
+ block: MintlifyBlock;
46
+ }
47
+ export interface MintlifyConfigFragment {
48
+ $type: 'mintlify.config-fragment';
49
+ schemaVersion: 1;
50
+ path: string;
51
+ value: MintlifyJSONValue;
52
+ }
53
+ export interface MintlifyAPISpec {
54
+ $type: 'mintlify.api-spec';
55
+ schemaVersion: 1;
56
+ path: string;
57
+ format: 'openapi' | 'asyncapi' | 'graphql';
58
+ source: string;
59
+ }
60
+ export interface MintlifySource {
61
+ site: MintlifySite;
62
+ documents: MintlifyDocument[];
63
+ snippets?: MintlifySnippet[];
64
+ configFragments?: MintlifyConfigFragment[];
65
+ apiSpecs?: MintlifyAPISpec[];
66
+ }
67
+ export interface MaterializeMintlifySiteOptions extends Omit<MintlifySource, 'documents'> {
68
+ documents: Array<Omit<MintlifyDocument, 'regions'> & {
69
+ regions: {
70
+ main: Array<MintlifyBlock | FragmentRefNode>;
71
+ };
72
+ }>;
73
+ outputDir: string;
74
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { MintlifyAPISpec, MintlifyConfigFragment, MintlifyDocument, MintlifyJSONValue, MintlifySite, MintlifySnippet } from './types.js';
2
+ export declare function validateSource(site: MintlifyJSONValue, documents: MintlifyDocument[], snippets: MintlifySnippet[], apiSpecs: MintlifyAPISpec[]): void;
3
+ export declare function validateSite(value: unknown, label: string): MintlifySite;
4
+ export declare function validateDocument(value: unknown, label: string, sourcePath?: string): MintlifyDocument;
5
+ export declare function validateSnippet(value: unknown, label: string, sourcePath?: string): MintlifySnippet;
6
+ export declare function validateConfigFragment(value: unknown, label: string): MintlifyConfigFragment;
7
+ export declare function validateAPISpec(value: unknown, label: string): MintlifyAPISpec;
@@ -0,0 +1,256 @@
1
+ import { validateBlock, validateSnippetReferences } from './blocks.js';
2
+ import { cleanDocumentPath, cleanFilePath, isExternalReference, isMintlifyJSONValue, isObject, nonEmptyString, } from './json.js';
3
+ const CONFIG_FRAGMENT_SCHEMA_VERSION = 1;
4
+ const API_SPEC_SCHEMA_VERSION = 1;
5
+ export function validateSource(site, documents, snippets, apiSpecs) {
6
+ const paths = new Set();
7
+ for (const document of documents) {
8
+ if (paths.has(document.path))
9
+ throw new Error(`ACI Mintlify document path is duplicated: ${document.path}`);
10
+ paths.add(document.path);
11
+ }
12
+ const navigated = new Set();
13
+ const navigation = isObject(site) ? site.navigation : undefined;
14
+ validateNavigationPartitions(navigation);
15
+ for (const page of navigationPages(navigation)) {
16
+ // Links are valid Mintlify navigation items but are not ACI documents.
17
+ if (isExternalReference(page))
18
+ continue;
19
+ const normalized = cleanDocumentPath(page);
20
+ if (!normalized || normalized !== page)
21
+ throw new Error(`ACI Mintlify navigation page is invalid: ${page}`);
22
+ if (!paths.has(page))
23
+ throw new Error(`ACI Mintlify navigation references missing document: ${page}`);
24
+ if (navigated.has(page))
25
+ throw new Error(`ACI Mintlify navigation references document more than once: ${page}`);
26
+ navigated.add(page);
27
+ }
28
+ validateRedirects(isObject(site) ? site.redirects : undefined, paths);
29
+ validateSnippetReferences(documents, snippets);
30
+ validateAPISpecReferences(site, apiSpecs);
31
+ }
32
+ export function validateSite(value, label) {
33
+ if (!isObject(value) || !isMintlifyJSONValue(value)) {
34
+ throw new Error(`ACI Mintlify site is invalid: ${label}`);
35
+ }
36
+ if ('$schema' in value && value.$schema !== 'https://mintlify.com/docs.json') {
37
+ throw new Error(`ACI Mintlify site has an unsupported docs schema: ${label}`);
38
+ }
39
+ return value;
40
+ }
41
+ export function validateDocument(value, label, sourcePath) {
42
+ const metadata = isObject(value) && isObject(value.metadata) ? value.metadata : undefined;
43
+ const regions = isObject(value) && isObject(value.regions) ? value.regions : undefined;
44
+ if (!isObject(value) || value.$type !== 'page' || !nonEmptyString(value.id) || !nonEmptyString(value.status) || !nonEmptyString(sourcePath) || !metadata || !nonEmptyString(metadata.title) || !regions || !Array.isArray(regions.main)) {
45
+ throw new Error(`ACI Mintlify document is invalid: ${label}`);
46
+ }
47
+ for (const region of Object.keys(regions)) {
48
+ if (region !== 'main')
49
+ throw new Error(`ACI Mintlify document ${label} has unsupported region ${JSON.stringify(region)}; only main is supported`);
50
+ }
51
+ const documentPath = cleanDocumentPath(sourcePath);
52
+ if (!documentPath || documentPath !== sourcePath)
53
+ throw new Error(`ACI Mintlify document path is invalid: ${sourcePath}`);
54
+ const ids = new Set();
55
+ const blocks = regions.main.map((block, index) => validateBlock(block, `${label}.regions.main[${index}]`, ids));
56
+ const renderer = isObject(metadata.mintlify) ? metadata.mintlify : {};
57
+ return {
58
+ $type: 'page', id: value.id, status: value.status, path: documentPath,
59
+ metadata: { title: metadata.title,
60
+ ...(nonEmptyString(metadata.description) ? { description: metadata.description } : {}),
61
+ mintlify: {
62
+ ...(nonEmptyString(renderer.sidebarTitle) ? { sidebarTitle: renderer.sidebarTitle } : {}),
63
+ ...(nonEmptyString(renderer.icon) ? { icon: renderer.icon } : {}),
64
+ ...(validFrontmatter(renderer.frontmatter) ? { frontmatter: renderer.frontmatter } : {}),
65
+ },
66
+ }, regions: { main: blocks },
67
+ };
68
+ }
69
+ export function validateSnippet(value, label, sourcePath) {
70
+ if (!isObject(value) || value.$type !== 'fragment' || !nonEmptyString(value.id) || !nonEmptyString(sourcePath) || !isObject(value.block)) {
71
+ throw new Error(`ACI Mintlify snippet is invalid: ${label}`);
72
+ }
73
+ const snippetPath = cleanFilePath(sourcePath, '.mdx');
74
+ if (!snippetPath || snippetPath !== sourcePath)
75
+ throw new Error(`ACI Mintlify snippet path is invalid: ${sourcePath}`);
76
+ const ids = new Set();
77
+ return {
78
+ $type: 'fragment', id: value.id,
79
+ path: snippetPath, block: validateBlock(value.block, `${label}.block`, ids),
80
+ };
81
+ }
82
+ export function validateConfigFragment(value, label) {
83
+ if (!isObject(value) || value.$type !== 'mintlify.config-fragment' || value.schemaVersion !== CONFIG_FRAGMENT_SCHEMA_VERSION || !nonEmptyString(value.path) || !isMintlifyJSONValue(value.value)) {
84
+ throw new Error(`ACI Mintlify config fragment is invalid: ${label}`);
85
+ }
86
+ const fragmentPath = cleanFilePath(value.path, '.json');
87
+ if (!fragmentPath || fragmentPath !== value.path || fragmentPath === 'docs.json')
88
+ throw new Error(`ACI Mintlify config fragment path is invalid: ${value.path}`);
89
+ return { $type: 'mintlify.config-fragment', schemaVersion: CONFIG_FRAGMENT_SCHEMA_VERSION, path: fragmentPath, value: value.value };
90
+ }
91
+ export function validateAPISpec(value, label) {
92
+ if (!isObject(value) || value.$type !== 'mintlify.api-spec' || value.schemaVersion !== API_SPEC_SCHEMA_VERSION || !nonEmptyString(value.path) || !['openapi', 'asyncapi', 'graphql'].includes(String(value.format)) || !nonEmptyString(value.source)) {
93
+ throw new Error(`ACI Mintlify API specification is invalid: ${label}`);
94
+ }
95
+ const sourcePath = value.path;
96
+ const extensions = value.format === 'graphql' ? ['.graphql', '.gql', '.json'] : ['.json', '.yaml', '.yml'];
97
+ const specPath = extensions.map((extension) => cleanFilePath(sourcePath, extension)).find(Boolean) ?? '';
98
+ if (!specPath || specPath !== sourcePath)
99
+ throw new Error(`ACI Mintlify API specification path is invalid: ${sourcePath}`);
100
+ return {
101
+ $type: 'mintlify.api-spec',
102
+ schemaVersion: API_SPEC_SCHEMA_VERSION,
103
+ path: specPath,
104
+ format: value.format,
105
+ source: value.source,
106
+ };
107
+ }
108
+ function validFrontmatter(value) {
109
+ if (value === undefined)
110
+ return false;
111
+ if (!isObject(value))
112
+ throw new Error('ACI Mintlify document frontmatter is invalid');
113
+ for (const [key, entry] of Object.entries(value)) {
114
+ if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(key) || !isMintlifyJSONValue(entry)) {
115
+ throw new Error('ACI Mintlify document frontmatter is invalid');
116
+ }
117
+ if (['title', 'description', 'sidebarTitle', 'icon'].includes(key))
118
+ throw new Error(`ACI Mintlify document frontmatter key is reserved: ${key}`);
119
+ }
120
+ return true;
121
+ }
122
+ function validateRedirects(value, documentPaths) {
123
+ if (value === undefined)
124
+ return;
125
+ if (!Array.isArray(value))
126
+ throw new Error('ACI Mintlify redirects are invalid');
127
+ const redirects = new Map();
128
+ const routes = new Set([...documentPaths].map((documentPath) => `/${documentPath}`));
129
+ for (const entry of value) {
130
+ if (!isObject(entry) || !nonEmptyString(entry.source) || !nonEmptyString(entry.destination) || (entry.permanent !== undefined && typeof entry.permanent !== 'boolean')) {
131
+ throw new Error('ACI Mintlify redirect is invalid');
132
+ }
133
+ if (!entry.source.startsWith('/') || entry.source.includes('?') || entry.source.includes('#')) {
134
+ throw new Error(`ACI Mintlify redirect source is invalid: ${entry.source}`);
135
+ }
136
+ if (!entry.destination.startsWith('/') && !isExternalReference(entry.destination)) {
137
+ throw new Error(`ACI Mintlify redirect destination is invalid: ${entry.destination}`);
138
+ }
139
+ if (redirects.has(entry.source))
140
+ throw new Error(`ACI Mintlify redirect source is duplicated: ${entry.source}`);
141
+ if (!entry.source.includes('*') && !entry.source.includes(':') && routes.has(trimRouteSlash(entry.source))) {
142
+ throw new Error(`ACI Mintlify redirect source collides with a document: ${entry.source}`);
143
+ }
144
+ redirects.set(entry.source, entry.destination);
145
+ }
146
+ for (const [source, destination] of redirects) {
147
+ if (isExternalReference(destination) || destination.includes('*') || destination.includes(':'))
148
+ continue;
149
+ const destinationPath = trimRouteSlash(destination.split(/[?#]/, 1)[0]);
150
+ if (!routes.has(destinationPath) && !redirects.has(destinationPath)) {
151
+ throw new Error(`ACI Mintlify redirect destination is missing: ${destination}`);
152
+ }
153
+ const seen = new Set([source]);
154
+ let next = destinationPath;
155
+ while (redirects.has(next)) {
156
+ if (seen.has(next))
157
+ throw new Error(`ACI Mintlify redirect cycle includes: ${next}`);
158
+ seen.add(next);
159
+ const target = redirects.get(next);
160
+ if (isExternalReference(target) || target.includes('*') || target.includes(':'))
161
+ break;
162
+ next = trimRouteSlash(target.split(/[?#]/, 1)[0]);
163
+ }
164
+ }
165
+ }
166
+ function trimRouteSlash(value) {
167
+ return value.length > 1 ? value.replace(/\/+$/, '') : value;
168
+ }
169
+ function validateAPISpecReferences(site, specs) {
170
+ const byPath = new Map();
171
+ for (const spec of specs) {
172
+ if (byPath.has(spec.path))
173
+ throw new Error(`ACI Mintlify API specification path is duplicated: ${spec.path}`);
174
+ byPath.set(spec.path, spec);
175
+ }
176
+ const visit = (value) => {
177
+ if (Array.isArray(value)) {
178
+ for (const child of value)
179
+ visit(child);
180
+ return;
181
+ }
182
+ if (!isObject(value))
183
+ return;
184
+ for (const [key, child] of Object.entries(value)) {
185
+ if (['openapi', 'asyncapi', 'graphql'].includes(key)) {
186
+ const references = typeof child === 'string' ? [child] : Array.isArray(child) ? child.filter((entry) => typeof entry === 'string') : [];
187
+ for (const reference of references) {
188
+ if (isExternalReference(reference))
189
+ continue;
190
+ const spec = byPath.get(reference);
191
+ if (!spec || spec.format !== key)
192
+ throw new Error(`ACI Mintlify API specification reference is missing or has the wrong format: ${reference}`);
193
+ }
194
+ }
195
+ visit(child);
196
+ }
197
+ };
198
+ visit(site);
199
+ }
200
+ function navigationPages(value) {
201
+ if (!isObject(value))
202
+ return [];
203
+ const pages = [];
204
+ visitNavigation(value, pages);
205
+ return pages;
206
+ }
207
+ function visitNavigation(value, pages) {
208
+ if (Array.isArray(value)) {
209
+ for (const item of value)
210
+ visitNavigation(item, pages);
211
+ return;
212
+ }
213
+ if (!isObject(value))
214
+ return;
215
+ for (const [key, child] of Object.entries(value)) {
216
+ if (key === 'pages' && Array.isArray(child)) {
217
+ for (const item of child) {
218
+ if (typeof item === 'string')
219
+ pages.push(item);
220
+ else
221
+ visitNavigation(item, pages);
222
+ }
223
+ continue;
224
+ }
225
+ visitNavigation(child, pages);
226
+ }
227
+ }
228
+ function validateNavigationPartitions(value) {
229
+ if (Array.isArray(value)) {
230
+ for (const child of value)
231
+ validateNavigationPartitions(child);
232
+ return;
233
+ }
234
+ if (!isObject(value))
235
+ return;
236
+ for (const [key, child] of Object.entries(value)) {
237
+ if ((key === 'languages' || key === 'versions') && Array.isArray(child)) {
238
+ const identityKey = key === 'languages' ? 'language' : 'version';
239
+ const identities = new Set();
240
+ let defaults = 0;
241
+ for (const entry of child) {
242
+ if (!isObject(entry) || !nonEmptyString(entry[identityKey]))
243
+ throw new Error(`ACI Mintlify ${key} navigation is invalid`);
244
+ const identity = entry[identityKey];
245
+ if (identities.has(identity))
246
+ throw new Error(`ACI Mintlify ${key} navigation is duplicated: ${identity}`);
247
+ identities.add(identity);
248
+ if (entry.default === true)
249
+ defaults += 1;
250
+ }
251
+ if (defaults > 1)
252
+ throw new Error(`ACI Mintlify navigation has multiple default ${key}`);
253
+ }
254
+ validateNavigationPartitions(child);
255
+ }
256
+ }
@@ -0,0 +1,4 @@
1
+ /** Signals from the committed page tree, including a page with no assignments. */
2
+ export declare function AssignmentsNavigation({ json }: {
3
+ json: string;
4
+ }): null;
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+ import { useLayoutEffect } from 'react';
3
+ /** Signals from the committed page tree, including a page with no assignments. */
4
+ export function AssignmentsNavigation({ json }) {
5
+ // Deliberately runs on each page commit, including unchanged assignment props
6
+ // on a query navigation. The collector deduplicates hydration/StrictMode and
7
+ // same-URL/hash commits; discarded concurrent renders never run this effect.
8
+ useLayoutEffect(() => {
9
+ const win = window;
10
+ if (typeof win.aci !== 'function') {
11
+ const queue = (...args) => { (queue.q ??= []).push(args); };
12
+ win.aci = queue;
13
+ }
14
+ const assignments = json ? JSON.parse(json).experiments : [];
15
+ win.aci('navigation-complete', { url: win.location.href, assignments });
16
+ });
17
+ return null;
18
+ }
@@ -7,8 +7,9 @@ export interface AssignmentsScriptProps {
7
7
  * (`<script type="application/json" data-aci-assignments>` with a
8
8
  * {"v":1,"experiments":[…]} body, personalization-reporting design/04) when
9
9
  * the page payload carries a build-time `experiments` block, and nothing
10
- * otherwise. createPage appends it to the page tree exactly once per page;
10
+ * otherwise. Its client commit hook also signals empty pages so SPA
11
+ * attribution clears when leaving an experiment. createPage appends it to the page tree exactly once per page;
11
12
  * sites composing their own pages can render it directly. The JSON body is
12
13
  * HTML-safe (assignmentsScriptJSON \u-escapes angle brackets).
13
14
  */
14
- export declare function AssignmentsScript({ page }: AssignmentsScriptProps): import("react").JSX.Element | null;
15
+ export declare function AssignmentsScript({ page }: AssignmentsScriptProps): import("react").JSX.Element;
@@ -1,17 +1,17 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { AssignmentsNavigation } from './assignments-navigation.js';
2
3
  import { assignmentsScriptJSON, } from '../content/personalization.js';
3
4
  /**
4
5
  * AssignmentsScript renders the page-level experiment assignment tag
5
6
  * (`<script type="application/json" data-aci-assignments>` with a
6
7
  * {"v":1,"experiments":[…]} body, personalization-reporting design/04) when
7
8
  * the page payload carries a build-time `experiments` block, and nothing
8
- * otherwise. createPage appends it to the page tree exactly once per page;
9
+ * otherwise. Its client commit hook also signals empty pages so SPA
10
+ * attribution clears when leaving an experiment. createPage appends it to the page tree exactly once per page;
9
11
  * sites composing their own pages can render it directly. The JSON body is
10
12
  * HTML-safe (assignmentsScriptJSON \u-escapes angle brackets).
11
13
  */
12
14
  export function AssignmentsScript({ page }) {
13
15
  const json = assignmentsScriptJSON(page);
14
- if (!json)
15
- return null;
16
- return (_jsx("script", { type: "application/json", "data-aci-assignments": "", dangerouslySetInnerHTML: { __html: json } }));
16
+ return (_jsxs(_Fragment, { children: [json ? _jsx("script", { type: "application/json", "data-aci-assignments": "", dangerouslySetInnerHTML: { __html: json } }) : null, _jsx(AssignmentsNavigation, { json: json })] }));
17
17
  }
@@ -17,6 +17,10 @@ export interface NextResolvedErrorPage extends ResolvedErrorPage {
17
17
  * warn posture (D-5). Never throws: an unreachable site config degrades to
18
18
  * the shipped default — an error surface must not re-enter the failing
19
19
  * system (ANTI-2).
20
+ *
21
+ * The seat receives no route params, so on a hosted request its release
22
+ * comes from the router's signed release context (resolveReleaseId): the
23
+ * same release the catch-all of that request was rewritten to.
20
24
  */
21
25
  export declare function resolveErrorPage(kind: ErrorPageKind, config?: FetchConfig): Promise<NextResolvedErrorPage>;
22
26
  /**
@@ -11,6 +11,10 @@ import { ErrorPageMarker } from './error-page-marker.js';
11
11
  * warn posture (D-5). Never throws: an unreachable site config degrades to
12
12
  * the shipped default — an error surface must not re-enter the failing
13
13
  * system (ANTI-2).
14
+ *
15
+ * The seat receives no route params, so on a hosted request its release
16
+ * comes from the router's signed release context (resolveReleaseId): the
17
+ * same release the catch-all of that request was rewritten to.
14
18
  */
15
19
  export async function resolveErrorPage(kind, config = {}) {
16
20
  let siteConfig = null;
@@ -13,7 +13,8 @@ import type { ErrorSeatPayload } from './error-seat.js';
13
13
  * - present-but-broken bindings — exactly the enumerated REQ-5 failures
14
14
  * (malformed route, unresolved page, unpublished page, audience/experiment
15
15
  * overlays — REQ-11) → `errors` in BOTH postures;
16
- * - ANY other exception (stale/corrupt compiled content, old manifest
16
+ * - selected fragment binding or expansion failures are errors in both postures;
17
+ * - other exceptions (stale/corrupt compiled content, old manifest
17
18
  * shapes) warns-and-defaults under warn and errors only under enforce, so
18
19
  * a stale .aci/compiled tree can never break a binding-less build.
19
20
  *
@@ -1,3 +1,4 @@
1
+ import { FragmentResolutionError, resolveSlotsSync } from '../content/resolve-slots.js';
1
2
  import { existsSync, readFileSync } from 'node:fs';
2
3
  import path from 'node:path';
3
4
  import { ERROR_PAGE_ROUTE_PATTERN } from '../content/error-pages.js';
@@ -86,29 +87,13 @@ export function buildErrorSeatPayload(contentRoot, posture) {
86
87
  const route = bindings.catchAll;
87
88
  const page = readJSON(root, catchAllEntry.payloadRef);
88
89
  const layout = readJSON(root, `layouts/${page.layout}.json`);
89
- const slots = {};
90
- const slotOrder = [];
91
- for (const slot of layout.slots) {
92
- slotOrder.push(slot.name);
93
- const pageBlocks = page.regions?.[slot.name];
94
- if (pageBlocks?.length) {
95
- slots[slot.name] = pageBlocks;
96
- continue;
97
- }
98
- const defaults = layout.defaults?.[slot.name];
99
- if (!defaults?.length)
100
- continue;
101
- const blocks = [];
102
- for (const ref of defaults) {
103
- const fragmentRef = manifest.fragments[ref.fragmentId]?.payloadRef;
104
- if (!fragmentRef)
105
- continue;
106
- const fragment = readJSON(root, fragmentRef);
107
- blocks.push({ id: fragment.id, component: fragment.component, props: fragment.props || {} });
108
- }
109
- if (blocks.length)
110
- slots[slot.name] = blocks;
111
- }
90
+ const slots = resolveSlotsSync(layout, page.regions ?? {}, (id) => {
91
+ const fragmentRef = manifest.fragments[id]?.payloadRef;
92
+ if (!fragmentRef)
93
+ throw new Error(`Fragment not found: ${id}`);
94
+ return readJSON(root, fragmentRef);
95
+ });
96
+ const slotOrder = layout.slots.map((slot) => slot.name);
112
97
  return {
113
98
  payload: {
114
99
  defaulted: false,
@@ -123,7 +108,12 @@ export function buildErrorSeatPayload(contentRoot, posture) {
123
108
  };
124
109
  }
125
110
  catch (error) {
126
- // Not one of the enumerated REQ-5 binding failures (those are pushed to
111
+ if (error instanceof FragmentResolutionError) {
112
+ errors.push(error.message);
113
+ return defaulted();
114
+ }
115
+ // Neither a selected-fragment failure nor an enumerated REQ-5 binding
116
+ // failure (those are pushed to
127
117
  // `errors` above): stale/corrupt compiled content or an old manifest
128
118
  // shape. Warn-and-default under the warn posture so it can never break a
129
119
  // build; fail closed only under enforce (quorum RISK-002).
@@ -69,7 +69,7 @@ function renderPayload(data, registry) {
69
69
  // async and server-oriented). Unknown components are skipped — the error
70
70
  // seat degrades, it never crashes.
71
71
  function renderClientBlocks(blocks, registry) {
72
- return blocks.map((block) => {
72
+ return blocks.map((block, index) => {
73
73
  const entry = registry.find((r) => r.id === block.component);
74
74
  if (!entry)
75
75
  return null;
@@ -78,6 +78,11 @@ function renderClientBlocks(blocks, registry) {
78
78
  if (entry.contract.blockSlots) {
79
79
  componentProps.renderChildren = (children) => renderClientBlocks(children, registry);
80
80
  }
81
- return _jsx(Component, { ...componentProps }, block.id);
81
+ // sdk I-19 (ADR 0051): the error seat is an injection seam too.
82
+ componentProps['data-aci-block'] = block.id;
83
+ componentProps['data-aci-component'] = block.component;
84
+ // Index+id composite: a repeated fragment placement repeats its authored
85
+ // id, and sibling keys must stay unique for React reconciliation.
86
+ return _jsx(Component, { ...componentProps }, `${index}:${block.id}`);
82
87
  });
83
88
  }
@@ -0,0 +1,7 @@
1
+ export type HostedPageTarget = Readonly<{
2
+ kind: 'base' | 'variant';
3
+ route: string;
4
+ pageRef: string;
5
+ variantKey?: string;
6
+ }>;
7
+ export declare function parseHostedPageTarget(rawSegments: readonly string[]): HostedPageTarget | null;
@@ -0,0 +1,39 @@
1
+ const VARIANT_NAMESPACE = '__variant';
2
+ export function parseHostedPageTarget(rawSegments) {
3
+ const segments = decodeSegments(rawSegments);
4
+ if (!segments)
5
+ return null;
6
+ const variantAt = segments.indexOf(VARIANT_NAMESPACE);
7
+ if (variantAt < 0)
8
+ return target('base', segments, segments);
9
+ if (variantAt !== segments.lastIndexOf(VARIANT_NAMESPACE) || variantAt !== segments.length - 2) {
10
+ return null;
11
+ }
12
+ return {
13
+ ...target('variant', segments.slice(0, variantAt), segments),
14
+ variantKey: segments[variantAt + 1],
15
+ };
16
+ }
17
+ function target(kind, routeSegments, targetSegments) {
18
+ return {
19
+ kind,
20
+ route: routeSegments.length === 0 ? '/' : `/${routeSegments.join('/')}/`,
21
+ pageRef: ['routes', ...targetSegments, 'index.json'].join('/'),
22
+ };
23
+ }
24
+ function decodeSegments(rawSegments) {
25
+ const segments = [];
26
+ for (const raw of rawSegments) {
27
+ let segment;
28
+ try {
29
+ segment = decodeURIComponent(raw);
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ if (!segment || segment === '.' || segment === '..' || segment.includes('/'))
35
+ return null;
36
+ segments.push(segment);
37
+ }
38
+ return segments;
39
+ }
@@ -2,10 +2,10 @@ export { DevRefresh, type DevRefreshProps } from './dev-refresh.js';
2
2
  export { withAci, type WithAciOptions } from './config.js';
3
3
  export { isPreviewMode } from './preview-mode.js';
4
4
  export { createPage, type CreatePageOptions, type SlotPropsFn } from './page.js';
5
+ export { renderBlock, renderBlocks } from './render.js';
5
6
  export { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams } from './server.js';
6
7
  export { PageNotFoundError, FragmentNotFoundError, LayoutNotFoundError } from './server.js';
7
8
  export { CollectScript, type CollectScriptProps } from './collect-script.js';
8
- export { aciMiddlewareMatcher } from './middleware.js';
9
9
  export { AssignmentsScript, type AssignmentsScriptProps } from './assignments-script.js';
10
10
  export { createNotFound, renderPageForRoute, resolveErrorPage, type NextResolvedErrorPage, } from './error-pages.js';
11
11
  export { ErrorPageInstrumentation } from './error-page-instrumentation.js';
@@ -2,10 +2,12 @@ export { DevRefresh } from './dev-refresh.js';
2
2
  export { withAci } from './config.js';
3
3
  export { isPreviewMode } from './preview-mode.js';
4
4
  export { createPage } from './page.js';
5
+ // The block renderer seam (sdk I-19, ADR 0051): exported so a site's own
6
+ // conformance test can prove its components carry root identity.
7
+ export { renderBlock, renderBlocks } from './render.js';
5
8
  export { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams } from './server.js';
6
9
  export { PageNotFoundError, FragmentNotFoundError, LayoutNotFoundError } from './server.js';
7
10
  export { CollectScript } from './collect-script.js';
8
- export { aciMiddlewareMatcher } from './middleware.js';
9
11
  export { AssignmentsScript } from './assignments-script.js';
10
12
  export { createNotFound, renderPageForRoute, resolveErrorPage, } from './error-pages.js';
11
13
  export { ErrorPageInstrumentation } from './error-page-instrumentation.js';
@@ -31,12 +31,10 @@ export interface CreatePageOptions {
31
31
  * the collect script tag exactly once per page (design/04 contract tag).
32
32
  *
33
33
  * Release-scoped routes (production): the middleware rewrites a public URL
34
- * to `/__r/{releaseId}/routes/{path}`. The optional catch-all `[[...slug]]`
35
- * receives `['__r', releaseId, 'routes', ...pathSegments]`. createPage
36
- * extracts the releaseId and passes it to the content loader, giving
37
- * each release a unique CDN cache key without a separate route folder.
38
- * The `routes` namespace segment leaves room for future siblings under
39
- * the release prefix (e.g. `/__r/{releaseId}/assets/*`).
34
+ * to `/__r/{releaseId}/{targetRef}`. The target ref selects the exact immutable
35
+ * base or variant page while its prefix identifies the logical public route.
36
+ * createPage passes both identities to the content loader, giving each target
37
+ * a distinct CDN cache key without sending selection headers into Next.
40
38
  *
41
39
  * Dev pass-through (ACI_CONTENT_PROVIDER=file): the middleware passes
42
40
  * requests through unrewritten, so `/` arrives with an empty/undefined
@@ -54,4 +52,29 @@ export declare function createPage(registry: Registry, options?: CreatePageOptio
54
52
  generateMetadata: ({ params }: NextPageProps) => Promise<Metadata>;
55
53
  default: ({ params }: NextPageProps) => Promise<import("react").JSX.Element>;
56
54
  };
55
+ /**
56
+ * Resolves the logical route and releaseId from Next.js catch-all params.
57
+ *
58
+ * Two shapes are supported:
59
+ *
60
+ * 1. **Rewritten (production):** middleware rewrites a public URL to the exact
61
+ * selected target under `/__r/{releaseId}`. A root variant therefore has
62
+ * `['__r', releaseId, '__variant', variantKey]`. The full suffix selects the
63
+ * immutable page object; the segments before the reserved `__variant`
64
+ * namespace form the logical public route.
65
+ *
66
+ * 2. **Dev pass-through (ACI_CONTENT_PROVIDER=file):** middleware passes
67
+ * requests through unrewritten, so the slug is the raw public path
68
+ * segments (possibly empty/undefined for `/`). No releaseId is present;
69
+ * the file provider serves content from disk.
70
+ */
71
+ export declare function resolveRouteAndRelease(params: Promise<{
72
+ slug?: string[];
73
+ }> | {
74
+ slug?: string[];
75
+ }): Promise<{
76
+ route: string;
77
+ releaseId?: string;
78
+ pageRef?: string;
79
+ }>;
57
80
  export {};