@gradial/aci 0.1.53-rc.3 → 0.1.53-rc.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,8 +2,19 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ### Fixed
6
+
7
+ - Astro authored 404/500 helpers use the shared `getPageData` pipeline and
8
+ consume the selected render input during ACI
9
+ preview/publish, preserving authored content and styling in code artifacts
10
+ without compiled content snapshots. Unrelated or personalized inputs cannot
11
+ replace the bound base error page.
12
+
5
13
  ### Added
6
14
 
15
+ - Public `aci schemas compile` and `aci error-pages prepare|emit` commands let
16
+ site build scripts compile code-owned artifacts without invoking SDK internals.
17
+
7
18
  - `AciRootProps` (the new name of `RootIdentityProps`, which stays as an
8
19
  alias) and `aciRootAttrs(props)`, exported from `@gradial/aci`.
9
20
  - The `rootIdentity` check covers every file that calls `createRegistry(`,
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agentic Content Infrastructure SDK
2
2
 
3
- `@gradial/aci` `0.1.53-rc.3` is a pre-1.0 public-surface reset for the ACI
3
+ `@gradial/aci` `0.1.53-rc.5` is a pre-1.0 public-surface reset for the ACI
4
4
  client SDK. Breaking changes from the old `0.1.x` accidental surface are
5
5
  intentional: the root import is framework-neutral, framework runtime behavior is
6
6
  behind explicit subpaths, and the first required customer path is React/Next.
@@ -8,7 +8,7 @@ behind explicit subpaths, and the first required customer path is React/Next.
8
8
  ## Install
9
9
 
10
10
  ```bash
11
- npm install @gradial/aci@0.1.53-rc.3 zod@^4
11
+ npm install @gradial/aci@0.1.53-rc.5 zod@^4
12
12
  ```
13
13
 
14
14
  ## Root Import
@@ -137,13 +137,13 @@ host bundles select and serve immutable release artifacts.
137
137
  The first RC scaffold path is Next:
138
138
 
139
139
  ```bash
140
- npx @gradial/aci@0.1.53-rc.3 init my-site --template next-starter
140
+ npx @gradial/aci@0.1.53-rc.5 init my-site --template next-starter
141
141
  ```
142
142
 
143
143
  List available templates:
144
144
 
145
145
  ```bash
146
- npx @gradial/aci@0.1.53-rc.3 init --list
146
+ npx @gradial/aci@0.1.53-rc.5 init --list
147
147
  ```
148
148
 
149
149
  ## Personalization: The One-Tag Install
@@ -223,3 +223,25 @@ From `packages/sdk`:
223
223
  pnpm run build
224
224
  pnpm run generate-starters
225
225
  ```
226
+
227
+ ## Public code-build commands
228
+
229
+ Use the installed `aci` binary from npm scripts, not files beneath the package's
230
+ `src`, `dist`, or `bin` directories:
231
+
232
+ ```json
233
+ {
234
+ "scripts": {
235
+ "schemas:compile": "aci schemas compile",
236
+ "prebuild": "npm run schemas:compile",
237
+ "build": "aci error-pages prepare && next build && aci error-pages emit",
238
+ "content:compile": "npm run schemas:compile && aci content compile --content ./.content --out ./.aci/compiled"
239
+ }
240
+ }
241
+ ```
242
+
243
+ `schemas compile` reads the component/data registry paths from `.aci.yaml` and
244
+ recompiles contracts without reading authored content. The error commands prepare
245
+ code-owned analytics policy and emit the default hosting fallback (preserving a
246
+ site-owned `public/500.html`). All three honor `--site-dir`; helper failures exit
247
+ nonzero. Local development/content validation must explicitly compile content.
@@ -48,8 +48,9 @@ export interface AstroErrorPageData {
48
48
  * error seats (`404.astro` / `500.astro`). `astro` is the seat's Astro
49
49
  * global; the bound route's content is loaded as if it were the requested
50
50
  * route, so static builds emit it into `dist/404.html`/`dist/500.html` and
51
- * server output renders it at error time from local compiled content — no
52
- * CMS fetch on the failing path (ANTI-2).
51
+ * ACI renders use the already resolved input for the bound base page;
52
+ * local static builds use compiled authoring content. Neither path fetches
53
+ * CMS content on a failure (ANTI-2).
53
54
  */
54
55
  export declare function getErrorPageData(astro: AstroGlobal, kind: ErrorPageKind, options?: {
55
56
  pushErrorPageView?: ErrorPagePush;
@@ -17,7 +17,7 @@
17
17
  * returned page data always carries empty collect/assignment tags.
18
18
  */
19
19
  import { getPageData } from './page.js';
20
- import { defaultPushErrorPageView, errorPageType, resolveErrorPage, serializeErrorPageInstrumentation, } from '../content/error-pages.js';
20
+ import { defaultPushErrorPageView, errorPageType, serializeErrorPageInstrumentation, } from '../content/error-pages.js';
21
21
  import { defaultErrorPageFragmentHtml } from '../content/default-error-page.js';
22
22
  const FALLBACK_META = {
23
23
  notFound: {
@@ -34,37 +34,23 @@ const FALLBACK_META = {
34
34
  * error seats (`404.astro` / `500.astro`). `astro` is the seat's Astro
35
35
  * global; the bound route's content is loaded as if it were the requested
36
36
  * route, so static builds emit it into `dist/404.html`/`dist/500.html` and
37
- * server output renders it at error time from local compiled content — no
38
- * CMS fetch on the failing path (ANTI-2).
37
+ * ACI renders use the already resolved input for the bound base page;
38
+ * local static builds use compiled authoring content. Neither path fetches
39
+ * CMS content on a failure (ANTI-2).
39
40
  */
40
41
  export async function getErrorPageData(astro, kind, options = {}) {
41
42
  const pageType = errorPageType(kind);
42
43
  const instrumentationTag = serializeErrorPageInstrumentation(options.pushErrorPageView ?? defaultPushErrorPageView, kind);
43
44
  try {
44
- const { FileContentProvider } = await import('../providers/file.js');
45
- const siteConfig = await new FileContentProvider().getSiteConfig();
46
- const resolved = await resolveErrorPage(kind, siteConfig);
47
- for (const warning of resolved.warnings) {
48
- console.warn(`[aci error-pages] ${warning}`);
49
- }
50
- if (resolved.route) {
51
- const slug = resolved.route.replace(/^\/+|\/+$/g, '');
52
- const data = await getPageData({
53
- isPrerendered: astro.isPrerendered,
54
- params: { slug },
55
- request: astro.request,
56
- url: astro.url,
57
- });
58
- return {
59
- kind,
60
- pageType,
61
- instrumentationTag,
62
- // Base audience, no personalization on error surfaces (REQ-11).
63
- data: { ...data, collectTag: '', assignmentsTag: '' },
64
- fallbackHtml: null,
65
- meta: data.meta,
66
- };
67
- }
45
+ const data = await getPageData(astro, { errorPageKind: kind });
46
+ return {
47
+ kind,
48
+ pageType,
49
+ instrumentationTag,
50
+ data,
51
+ fallbackHtml: null,
52
+ meta: data.meta,
53
+ };
68
54
  }
69
55
  catch (error) {
70
56
  console.warn(`[aci error-pages] bound ${kind} page failed to load; serving the shipped default: ${String(error)}`);
@@ -32,6 +32,7 @@
32
32
  */
33
33
  import type { KernelPage, KernelSiteConfig, KernelRouteMetadata, KernelPageBlock } from '../content/types.js';
34
34
  import { type LayoutEntry } from '../content/provider.js';
35
+ import { type ErrorPageKind } from '../content/error-pages.js';
35
36
  /**
36
37
  * Minimal Astro global shape — only the properties getPageData reads.
37
38
  * This avoids depending on Astro's own types at the SDK level.
@@ -77,6 +78,8 @@ export interface PageData {
77
78
  assignmentsTag: string;
78
79
  }
79
80
  export interface GetPageDataOptions {
81
+ /** Resolve this authored error binding as an unpersonalized base page. */
82
+ errorPageKind?: ErrorPageKind;
80
83
  /** Path to compiled content root. Defaults to ACI_CONTENT_ROOT env or '.aci/compiled'. */
81
84
  compiledRoot?: string;
82
85
  }
@@ -32,6 +32,7 @@
32
32
  */
33
33
  import { FragmentNotFoundError } from '../content/provider.js';
34
34
  import { normalizeRoute } from '../content/routes.js';
35
+ import { resolveErrorPage } from '../content/error-pages.js';
35
36
  import { routeMetadataForContent } from '../content/provider.js';
36
37
  import { resolveSlots } from '../content/resolve-slots.js';
37
38
  import { assignmentsScriptTagHTML, collectScriptTagHTML } from '../content/personalization.js';
@@ -54,7 +55,7 @@ import { GRADIAL_RENDER_INPUT_HEADER, getPendingRenderInputFromHeaders } from '.
54
55
  * artifacts in S3, no runtime content fetching).
55
56
  */
56
57
  export async function getPageData(astro, options) {
57
- const route = normalizeRoute(astro.params.slug ? `/${astro.params.slug}` : '/');
58
+ let route = normalizeRoute(astro.params.slug ? `/${astro.params.slug}` : '/');
58
59
  // Static Astro generation is explicit; unexpected header access errors and
59
60
  // expired render-input IDs must not turn a selected variant into local base.
60
61
  let runtimeInput = null;
@@ -65,28 +66,29 @@ export async function getPageData(astro, options) {
65
66
  throw new Error(`ACI Astro render input is unavailable for route ${route}; refusing to render local base content`);
66
67
  }
67
68
  }
68
- let siteConfig;
69
- let page;
70
- let providerModule = null;
71
- let provider = null;
72
- let variantKey;
73
- if (runtimeInput) {
74
- variantKey = requireVariantKey(runtimeInput.variantKey, route);
75
- siteConfig = runtimeInput.siteConfig;
76
- page = runtimeInput.page;
77
- }
78
- else {
79
- // Lazy-import FileContentProvider to avoid pulling it in when
80
- // preview render input is available
81
- providerModule = await import('../providers/file.js');
82
- provider = new providerModule.FileContentProvider(options?.compiledRoot);
83
- [siteConfig, page] = await Promise.all([
84
- provider.getSiteConfig(),
85
- provider.getPage(route),
86
- ]);
87
- const entry = (await provider.listRoutes()).find((entry) => normalizeRoute(entry.path) === route);
88
- variantKey = requireVariantKey(entry?.variantKey, route);
69
+ // Source selection is shared by ordinary pages and authored error seats.
70
+ // A supplied renderer input never consults local authoring files.
71
+ const provider = runtimeInput
72
+ ? null
73
+ : new (await import('../providers/file.js')).FileContentProvider(options?.compiledRoot);
74
+ const siteConfig = runtimeInput
75
+ ? runtimeInput.siteConfig
76
+ : await provider.getSiteConfig();
77
+ if (options?.errorPageKind) {
78
+ const resolved = await resolveErrorPage(options.errorPageKind, siteConfig);
79
+ for (const warning of resolved.warnings)
80
+ console.warn(`[aci error-pages] ${warning}`);
81
+ if (!resolved.route)
82
+ throw new Error(`No authored ${options.errorPageKind} page is bound`);
83
+ route = normalizeRoute(resolved.route);
84
+ if (runtimeInput && (normalizeRoute(runtimeInput.route) !== route || runtimeInput.variantKey !== 'base')) {
85
+ throw new Error(`ACI Astro ${options.errorPageKind} input must supply the bound base page ${resolved.route}`);
86
+ }
89
87
  }
88
+ const page = runtimeInput ? runtimeInput.page : await provider.getPage(route);
89
+ const variantKey = runtimeInput
90
+ ? requireVariantKey(runtimeInput.variantKey, route)
91
+ : requireVariantKey((await provider.listRoutes()).find((entry) => normalizeRoute(entry.path) === route)?.variantKey, route);
90
92
  const meta = routeMetadataForContent(siteConfig, page);
91
93
  // Resolve layout: prefer render input, fall back to provider
92
94
  const layout = await resolveLayout(runtimeInput, provider, page.layout, route);
@@ -102,8 +104,9 @@ export async function getPageData(astro, options) {
102
104
  });
103
105
  // Collect tag: suppress in preview mode (authoring surface, not visitor traffic)
104
106
  const isPreview = astro.url.searchParams.has('preview_token');
105
- const collectTag = isPreview ? '' : collectScriptTagHTML(siteConfig);
106
- const assignmentsTag = isPreview ? '' : assignmentsScriptTagHTML(page);
107
+ const suppressCollection = isPreview || Boolean(options?.errorPageKind);
108
+ const collectTag = suppressCollection ? '' : collectScriptTagHTML(siteConfig);
109
+ const assignmentsTag = suppressCollection ? '' : assignmentsScriptTagHTML(page);
107
110
  return { route, variantKey, siteConfig, page, meta, layout, slots, collectTag, assignmentsTag };
108
111
  }
109
112
  function requireVariantKey(value, route) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradial/aci",
3
- "version": "0.1.53-rc.3",
3
+ "version": "0.1.53-rc.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/gradial/bare-metal-go.git",
@@ -164,11 +164,11 @@
164
164
  "astro": "^6.4.8"
165
165
  },
166
166
  "optionalDependencies": {
167
- "@gradial/aci-cli-darwin-arm64": "0.1.53-rc.3",
168
- "@gradial/aci-cli-darwin-x64": "0.1.53-rc.3",
169
- "@gradial/aci-cli-linux-arm64": "0.1.53-rc.3",
170
- "@gradial/aci-cli-linux-x64": "0.1.53-rc.3",
171
- "@gradial/aci-cli-win32-arm64": "0.1.53-rc.3",
172
- "@gradial/aci-cli-win32-x64": "0.1.53-rc.3"
167
+ "@gradial/aci-cli-darwin-arm64": "0.1.53-rc.5",
168
+ "@gradial/aci-cli-darwin-x64": "0.1.53-rc.5",
169
+ "@gradial/aci-cli-linux-arm64": "0.1.53-rc.5",
170
+ "@gradial/aci-cli-linux-x64": "0.1.53-rc.5",
171
+ "@gradial/aci-cli-win32-arm64": "0.1.53-rc.5",
172
+ "@gradial/aci-cli-win32-x64": "0.1.53-rc.5"
173
173
  }
174
174
  }
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "astro dev --host 0.0.0.0",
8
- "build": "node ./node_modules/@gradial/aci/src/cli/emit-error-pages.mjs prepare && astro build",
8
+ "build": "aci error-pages prepare && astro build",
9
9
  "preview": "ACI_CONTENT_ROOT=./.aci/compiled astro preview --host 0.0.0.0",
10
10
  "typecheck": "ACI_CONTENT_ROOT=./.aci/compiled astro check --tsconfig ./tsconfig.json",
11
11
  "test": "node --import tsx --test tests/**/*.test.ts",
@@ -5,7 +5,7 @@
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "ACI_CONTENT_PROVIDER=file next dev -H 0.0.0.0",
8
- "build": "node ./node_modules/@gradial/aci/src/cli/emit-error-pages.mjs prepare && next build && node ./node_modules/@gradial/aci/src/cli/emit-error-pages.mjs emit",
8
+ "build": "aci error-pages prepare && next build && aci error-pages emit",
9
9
  "preview": "next start -H 0.0.0.0",
10
10
  "typecheck": "tsc --noEmit",
11
11
  "test": "node --import tsx --test tests/**/*.test.ts",