@gradial/aci 0.1.45 → 0.1.47

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 (90) hide show
  1. package/README.md +4 -4
  2. package/dist/astro/error-page.d.ts +56 -0
  3. package/dist/astro/error-page.js +79 -0
  4. package/dist/astro/index.d.ts +4 -0
  5. package/dist/astro/index.js +9 -0
  6. package/dist/audience-data-models.d.ts +142 -2
  7. package/dist/audience-data-models.js +2 -0
  8. package/dist/cli/compile-registry.d.mts +1 -5
  9. package/dist/cli/compile-registry.mjs +10 -25
  10. package/dist/cli/emit-error-pages.d.mts +39 -0
  11. package/dist/cli/emit-error-pages.mjs +402 -0
  12. package/dist/cli/validate-content.d.mts +1 -31
  13. package/dist/cli/validate-content.mjs +12 -50
  14. package/dist/cli/verify-next-cdn-routes.mjs +1 -0
  15. package/dist/content/default-error-page-html.d.ts +2 -0
  16. package/dist/content/default-error-page-html.js +6 -0
  17. package/dist/content/default-error-page.d.ts +23 -0
  18. package/dist/content/default-error-page.js +34 -0
  19. package/dist/content/error-page-kind.d.ts +57 -0
  20. package/dist/content/error-page-kind.js +106 -0
  21. package/dist/content/error-pages.d.ts +88 -0
  22. package/dist/content/error-pages.js +120 -0
  23. package/dist/content/index.d.ts +2 -0
  24. package/dist/content/index.js +2 -0
  25. package/dist/content/provider.d.ts +1 -1
  26. package/dist/content/resolve-slots.js +0 -1
  27. package/dist/content/types.d.ts +12 -2
  28. package/dist/internal/render-proof.d.ts +1 -0
  29. package/dist/internal/render-proof.js +197 -0
  30. package/dist/next/config.js +17 -0
  31. package/dist/next/error-page-instrumentation.d.ts +23 -0
  32. package/dist/next/error-page-instrumentation.js +36 -0
  33. package/dist/next/error-page-marker.d.ts +11 -0
  34. package/dist/next/error-page-marker.js +20 -0
  35. package/dist/next/error-pages.d.ts +52 -0
  36. package/dist/next/error-pages.js +94 -0
  37. package/dist/next/error-seat-payload.d.ts +33 -0
  38. package/dist/next/error-seat-payload.js +143 -0
  39. package/dist/next/error-seat.d.ts +57 -0
  40. package/dist/next/error-seat.js +83 -0
  41. package/dist/next/index.d.ts +4 -0
  42. package/dist/next/index.js +8 -0
  43. package/dist/next/middleware.js +9 -54
  44. package/dist/next/page.js +9 -4
  45. package/dist/next/personalization-host.d.ts +5 -0
  46. package/dist/next/server.js +88 -75
  47. package/dist/next/vercel-collect-sdk-route.js +6 -30
  48. package/dist/next/vercel-edge-projection-v1.d.ts +24 -0
  49. package/dist/next/vercel-edge-projection-v1.js +880 -0
  50. package/dist/next/vercel-s3-personalization.js +7 -11
  51. package/dist/providers/s3.d.ts +2 -4
  52. package/dist/providers/s3.js +173 -19
  53. package/dist/types/block-ref.d.ts +0 -2
  54. package/dist/types/block-ref.js +0 -1
  55. package/package.json +15 -9
  56. package/src/cli/compile-registry.mjs +10 -24
  57. package/src/cli/emit-error-pages.mjs +424 -0
  58. package/src/cli/validate-content.mjs +13 -52
  59. package/src/cli/verify-next-cdn-routes.mjs +6 -0
  60. package/src/types/block-ref.ts +0 -2
  61. package/templates/astro/starter-content/src/fixtures/atomicBlocks.ts +6 -7
  62. package/templates/astro/starter-content/src/fixtures/composition.ts +2 -3
  63. package/templates/astro/starter-content/src/fixtures/sections.ts +1 -2
  64. package/templates/astro/template/package.json.tmpl +1 -1
  65. package/templates/astro/template/src/aci/error-page-instrumentation.mjs +33 -0
  66. package/templates/astro/template/src/pages/404.astro +54 -0
  67. package/templates/astro/template/src/pages/500.astro +53 -0
  68. package/templates/astro/template/src/pages/[...slug].astro +15 -2
  69. package/templates/common/.agents/skills/authoring/SKILL.md +74 -11
  70. package/templates/common/.agents/skills/authoring/references/block-slots.md +0 -3
  71. package/templates/common/.content/config/robots.txt +4 -0
  72. package/templates/common/.content/config/site.json.tmpl +4 -0
  73. package/templates/common/.content/pages/404/_index.json +31 -0
  74. package/templates/common/.content/pages/error/_index.json +31 -0
  75. package/templates/common/.content/pages/home/_index.json +0 -10
  76. package/templates/common/.content/schemas/site.schema.json +9 -0
  77. package/templates/common/starter-content/.content/config/robots.txt +2 -0
  78. package/templates/common/starter-content/.content/config/site.json +4 -0
  79. package/templates/common/starter-content/.content/pages/404/_index.json +31 -0
  80. package/templates/common/starter-content/.content/pages/about/_index.json +0 -3
  81. package/templates/common/starter-content/.content/pages/error/_index.json +31 -0
  82. package/templates/common/starter-content/.content/pages/home/_index.json +21 -14
  83. package/templates/common/starter-content/.content/schemas/site.schema.json +9 -0
  84. package/templates/nextjs/template/package.json.tmpl +1 -1
  85. package/templates/nextjs/template/src/aci/error-page-instrumentation.d.mts +4 -0
  86. package/templates/nextjs/template/src/aci/error-page-instrumentation.mjs +38 -0
  87. package/templates/nextjs/template/src/app/error.tsx +18 -0
  88. package/templates/nextjs/template/src/app/not-found.tsx +13 -0
  89. package/src/types/block-ref.test.ts +0 -45
  90. package/templates/nextjs/template/src/app/collect/route.ts +0 -18
@@ -4,14 +4,13 @@
4
4
  "status": "published",
5
5
  "layout": "default",
6
6
  "metadata": {
7
- "title": "Meridian — Global Satellite Internet",
7
+ "title": "Meridian \u2014 Global Satellite Internet",
8
8
  "description": "Connect from anywhere on Earth. Low-latency satellite internet for homes, businesses, and beyond.",
9
9
  "canonical": "https://www.meridian.local/"
10
10
  },
11
11
  "regions": {
12
12
  "main": [
13
13
  {
14
- "$type": "component",
15
14
  "id": "hero",
16
15
  "component": "home_hero",
17
16
  "props": {
@@ -28,7 +27,6 @@
28
27
  }
29
28
  },
30
29
  {
31
- "$type": "component",
32
30
  "id": "why-meridian",
33
31
  "component": "feature_grid",
34
32
  "props": {
@@ -36,7 +34,6 @@
36
34
  "subtitle": "Engineered for the edges of the world.",
37
35
  "features": [
38
36
  {
39
- "$type": "component",
40
37
  "id": "global-coverage",
41
38
  "component": "feature_card",
42
39
  "props": {
@@ -46,7 +43,6 @@
46
43
  }
47
44
  },
48
45
  {
49
- "$type": "component",
50
46
  "id": "low-latency",
51
47
  "component": "feature_card",
52
48
  "props": {
@@ -56,7 +52,6 @@
56
52
  }
57
53
  },
58
54
  {
59
- "$type": "component",
60
55
  "id": "easy-setup",
61
56
  "component": "feature_card",
62
57
  "props": {
@@ -69,20 +64,34 @@
69
64
  }
70
65
  },
71
66
  {
72
- "$type": "component",
73
67
  "id": "stats",
74
68
  "component": "stats_bar",
75
69
  "props": {
76
70
  "stats": [
77
- { "label": "Network uptime", "value": "99.9", "suffix": "%" },
78
- { "label": "Average latency", "value": "<50", "suffix": "ms" },
79
- { "label": "Countries covered", "value": "40", "suffix": "+" },
80
- { "label": "Orbital satellites", "value": "2,400", "suffix": "" }
71
+ {
72
+ "label": "Network uptime",
73
+ "value": "99.9",
74
+ "suffix": "%"
75
+ },
76
+ {
77
+ "label": "Average latency",
78
+ "value": "<50",
79
+ "suffix": "ms"
80
+ },
81
+ {
82
+ "label": "Countries covered",
83
+ "value": "40",
84
+ "suffix": "+"
85
+ },
86
+ {
87
+ "label": "Orbital satellites",
88
+ "value": "2,400",
89
+ "suffix": ""
90
+ }
81
91
  ]
82
92
  }
83
93
  },
84
94
  {
85
- "$type": "component",
86
95
  "id": "cta",
87
96
  "component": "container",
88
97
  "props": {
@@ -90,7 +99,6 @@
90
99
  "className": "items-center justify-center text-center",
91
100
  "content": [
92
101
  {
93
- "$type": "component",
94
102
  "id": "cta-primary",
95
103
  "component": "button",
96
104
  "props": {
@@ -102,7 +110,6 @@
102
110
  }
103
111
  },
104
112
  {
105
- "$type": "component",
106
113
  "id": "cta-secondary",
107
114
  "component": "button",
108
115
  "props": {
@@ -7,6 +7,15 @@
7
7
  "additionalProperties": true,
8
8
  "properties": {
9
9
  "$type": { "const": "site" },
10
+ "errorPages": {
11
+ "type": "object",
12
+ "required": ["notFound", "catchAll"],
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "notFound": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" },
16
+ "catchAll": { "type": "string", "pattern": "^/(?:[A-Za-z0-9._~-]+/)+$" }
17
+ }
18
+ },
10
19
  "id": { "type": "string", "minLength": 1 },
11
20
  "status": { "type": "string", "minLength": 1 },
12
21
  "title": { "type": "string", "minLength": 1 },
@@ -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": "next build",
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",
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",
@@ -0,0 +1,4 @@
1
+ // Type surface for the customer-owned policy module beside this file
2
+ // (authorable-error-pages D-15). Edit the .mjs; this declaration only needs
3
+ // touching if you change the function's signature.
4
+ export declare function pushErrorPageView(pageType: 'not_found' | 'error'): void;
@@ -0,0 +1,38 @@
1
+ // Error-page analytics policy — THIS FILE IS YOURS (customer-owned;
2
+ // code-organization R-14 / authorable-error-pages D-15). The ACI SDK owns
3
+ // the delivery mechanism (when this runs, serialization, the
4
+ // data-aci-error-page marker); this file owns WHAT is pushed.
5
+ //
6
+ // Contract:
7
+ // - pushErrorPageView MUST stay self-contained: browser globals only — no
8
+ // imports, no closed-over identifiers. The Astro seats and the 500.html
9
+ // emitter execute it STRINGIFIED via toString(), so anything outside the
10
+ // function body is lost.
11
+ // - Emptying the body to a no-op disables error-page analytics on every
12
+ // surface (Next seats, Astro seats, 500.html) — the sanctioned
13
+ // alternative to GTM-container-side suppression.
14
+ // - Plain .mjs on purpose: it is consumed verbatim, never transpiled.
15
+ //
16
+ // 'use client' (Next only, inert elsewhere): the not-found seat is a server
17
+ // component and can only hand a function to the client-side instrumentation
18
+ // component as a client reference.
19
+ 'use client';
20
+
21
+ /**
22
+ * Pushes one `page_view` event per error-surface view (D-14 default
23
+ * payload). `page_path` is the visitor's requested path, so 404 reports
24
+ * double as a broken-link inventory.
25
+ *
26
+ * @param {'not_found' | 'error'} pageType
27
+ */
28
+ export function pushErrorPageView(pageType) {
29
+ window.dataLayer = window.dataLayer || [];
30
+ window.dataLayer.push({
31
+ event: 'page_view',
32
+ page_type: pageType,
33
+ page_path: window.location.pathname,
34
+ page_location: window.location.href,
35
+ page_referrer: document.referrer || '(direct)',
36
+ page_title: document.title,
37
+ });
38
+ }
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import { ErrorSeat } from '@gradial/aci/next/error-seat';
4
+ import { registry } from '@/cms/registry';
5
+ import { pushErrorPageView } from '../aci/error-page-instrumentation.mjs';
6
+
7
+ // Next's app-error seat (client-only by contract). ErrorSeat renders the
8
+ // page bound by site.json#errorPages.catchAll from content serialized into
9
+ // the bundle at build time — nothing is fetched while the app is failing.
10
+ // The analytics push comes from the site-owned policy module (D-15):
11
+ // edit src/aci/error-page-instrumentation.mjs to customize or disable it.
12
+ //
13
+ // Coverage: render errors below the root layout. NOT covered here: root
14
+ // layout errors (global-error), middleware failures, and platform 5xx —
15
+ // those are served the static public/500.html emitted by the build.
16
+ export default function AppError({ error }: { error: Error & { digest?: string } }) {
17
+ return <ErrorSeat registry={registry} error={error} pushErrorPageView={pushErrorPageView} />;
18
+ }
@@ -0,0 +1,13 @@
1
+ import { createNotFound } from '@gradial/aci/next';
2
+ import { registry } from '@/cms/registry';
3
+ import { pushErrorPageView } from '../aci/error-page-instrumentation.mjs';
4
+
5
+ // Next's native not-found seat: the SDK catch-all invokes notFound() on
6
+ // missing content, and this renders the page bound by
7
+ // site.json#errorPages.notFound with a real HTTP 404. If that page is itself
8
+ // missing at request time, the SDK falls back to its shipped default inline —
9
+ // this seat never recurses and never throws.
10
+ //
11
+ // The analytics push comes from the site-owned policy module (D-15):
12
+ // edit src/aci/error-page-instrumentation.mjs to customize or disable it.
13
+ export default createNotFound(registry, { pushErrorPageView });
@@ -1,45 +0,0 @@
1
- import assert from 'node:assert/strict';
2
- import test from 'node:test';
3
- import { z } from 'zod';
4
-
5
- import { compileSchema } from '../compiler/zod-to-jsonschema.js';
6
- import { defineComponentContract } from '../define-component.js';
7
- import { blockRefArray } from './block-ref.js';
8
-
9
- const childContract = defineComponentContract({
10
- id: 'child',
11
- props: z.object({
12
- label: z.string(),
13
- }),
14
- });
15
-
16
- test('block references require and accept the component discriminator', () => {
17
- const schema = blockRefArray([childContract]);
18
- const typed = {
19
- $type: 'component',
20
- id: 'child-1',
21
- component: 'child',
22
- props: { label: 'Hello' },
23
- };
24
-
25
- assert.equal(schema.safeParse([typed]).success, true);
26
- assert.equal(schema.safeParse([{
27
- id: typed.id,
28
- component: typed.component,
29
- props: typed.props,
30
- }]).success, false);
31
- });
32
-
33
- test('compiled block-reference schema exposes the component discriminator', () => {
34
- const compiled = compileSchema(blockRefArray([childContract])) as {
35
- items?: {
36
- properties?: Record<string, { const?: string }>;
37
- required?: string[];
38
- additionalProperties?: boolean;
39
- };
40
- };
41
-
42
- assert.equal(compiled.items?.properties?.$type?.const, 'component');
43
- assert.equal(compiled.items?.required?.includes('$type'), true);
44
- assert.equal(compiled.items?.additionalProperties, false);
45
- });
@@ -1,18 +0,0 @@
1
- import {
2
- createPersonalizationCollectRoute,
3
- createVercelCollectionFromEnv,
4
- } from '@gradial/aci/next/vercel-personalization';
5
-
6
- export const runtime = 'nodejs';
7
-
8
- const personalization = createVercelCollectionFromEnv();
9
- const unavailable = async () => new Response('personalization host is not configured', {
10
- status: 503,
11
- headers: { 'Cache-Control': 'private, no-store' },
12
- });
13
- const collect = personalization
14
- ? createPersonalizationCollectRoute(personalization)
15
- : unavailable;
16
-
17
- export const POST = collect;
18
- export const OPTIONS = collect;