@gradial/aci 0.1.48 → 0.1.51-ssr.2
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/README.md +13 -20
- package/dist/astro/assets.d.ts +6 -6
- package/dist/astro/assets.js +6 -6
- package/dist/astro/index.d.ts +0 -2
- package/dist/astro/index.js +0 -4
- package/dist/cli/emit-error-pages.mjs +0 -1
- package/dist/cli/verify-next-cdn-routes.mjs +3 -4
- package/dist/collect/aci.js +1 -1
- package/dist/collect/aci.js.sha256 +1 -1
- package/dist/collect/webvitals.d.ts +0 -3
- package/dist/collect/webvitals.js +11 -21
- package/dist/content/cache.d.ts +1 -9
- package/dist/content/cache.js +2 -37
- package/dist/content/error-pages.d.ts +1 -2
- package/dist/content/index.d.ts +0 -1
- package/dist/content/index.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/internal/domain/edge/identity.d.ts +14 -0
- package/dist/internal/domain/edge/identity.js +214 -0
- package/dist/internal/domain/edge/index.d.ts +4 -0
- package/dist/internal/domain/edge/index.js +6 -0
- package/dist/internal/domain/edge/personalization-core.d.ts +24 -0
- package/dist/{edge → internal/domain/edge}/personalization-core.js +165 -64
- package/dist/internal/domain/edge/record/codec.d.ts +71 -0
- package/dist/internal/domain/edge/record/codec.js +401 -0
- package/dist/internal/domain/edge/resolve.d.ts +2 -0
- package/dist/internal/domain/edge/resolve.js +76 -0
- package/dist/{next/personalization-host.d.ts → internal/domain/edge/types.d.ts} +110 -61
- package/dist/internal/domain/edge/types.js +7 -0
- package/dist/internal/platform/collectionstore/errors.d.ts +5 -0
- package/dist/internal/platform/collectionstore/errors.js +7 -0
- package/dist/next/config.d.ts +0 -8
- package/dist/next/config.js +3 -78
- package/dist/next/error-pages.d.ts +2 -3
- package/dist/next/error-pages.js +5 -5
- package/dist/next/error-seat.d.ts +2 -3
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +1 -2
- package/dist/next/page.d.ts +3 -13
- package/dist/next/page.js +39 -51
- package/dist/next/server.d.ts +12 -32
- package/dist/next/server.js +66 -295
- package/dist/providers/object.d.ts +24 -0
- package/dist/providers/object.js +105 -0
- package/dist/providers/vercel-object-reader.d.ts +20 -0
- package/dist/providers/vercel-object-reader.js +45 -0
- package/dist/testing/conformance/checks.d.ts +1 -1
- package/dist/testing/conformance/checks.js +14 -144
- package/dist/testing/conformance/index.d.ts +1 -1
- package/dist/testing/conformance/index.js +1 -1
- package/dist/testing/conformance/preset.js +1 -1
- package/dist/testing/conformance/types.d.ts +1 -1
- package/dist/types/config.d.ts +0 -4
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.js +0 -2
- package/dist/types/page.d.ts +0 -10
- package/package.json +11 -35
- package/src/cli/emit-error-pages.mjs +0 -1
- package/src/cli/verify-next-cdn-routes.mjs +8 -11
- package/src/types/config.ts +0 -5
- package/src/types/index.ts +0 -2
- package/src/types/page.ts +0 -11
- package/templates/astro/template/.aci.yaml.tmpl +0 -11
- package/templates/common/.agents/skills/aci/SKILL.md +8 -9
- package/templates/common/.agents/skills/authoring/SKILL.md +3 -4
- package/templates/common/.agents/skills/authoring/references/block-registry.md +13 -36
- package/templates/common/.agents/skills/authoring/references/contracts.md +10 -17
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +2 -2
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +45 -95
- package/templates/common/.agents/skills/migration/references/canon-migration.md +17 -37
- package/templates/nextjs/template/.aci.yaml.tmpl +0 -11
- package/templates/nextjs/template/README.md.tmpl +0 -1
- package/templates/nextjs/template/src/app/[[...slug]]/page.tsx +1 -1
- package/dist/content/assets.d.ts +0 -18
- package/dist/content/assets.js +0 -66
- package/dist/edge/personalization-core.d.ts +0 -11
- package/dist/internal/render-proof.d.ts +0 -1
- package/dist/internal/render-proof.js +0 -197
- package/dist/next/asset-route.d.ts +0 -10
- package/dist/next/asset-route.js +0 -45
- package/dist/next/collect-route.d.ts +0 -19
- package/dist/next/collect-route.js +0 -422
- package/dist/next/edge-config.d.ts +0 -1
- package/dist/next/edge-config.js +0 -92
- package/dist/next/envelope-digest.d.ts +0 -21
- package/dist/next/envelope-digest.js +0 -58
- package/dist/next/middleware.d.ts +0 -40
- package/dist/next/middleware.js +0 -462
- package/dist/next/personalization-host.js +0 -257
- package/dist/next/vercel-collect-sdk-route.d.ts +0 -27
- package/dist/next/vercel-collect-sdk-route.js +0 -181
- package/dist/next/vercel-edge-projection-v1.d.ts +0 -24
- package/dist/next/vercel-edge-projection-v1.js +0 -880
- package/dist/next/vercel-personalization.d.ts +0 -4
- package/dist/next/vercel-personalization.js +0 -4
- package/dist/next/vercel-s3-personalization.d.ts +0 -79
- package/dist/next/vercel-s3-personalization.js +0 -570
- package/dist/providers/s3.d.ts +0 -47
- package/dist/providers/s3.js +0 -434
- package/dist/types/render-mode.d.ts +0 -2
- package/dist/types/render-mode.js +0 -1
- package/dist/types/renderer.d.ts +0 -71
- package/dist/types/renderer.js +0 -1
- package/src/types/render-mode.ts +0 -10
- package/src/types/renderer.ts +0 -83
- package/templates/nextjs/starter-content/src/middleware.ts +0 -41
- package/templates/nextjs/template/src/app/gradial/assets/[...path]/route.ts +0 -1
- package/templates/nextjs/template/src/middleware.ts +0 -41
- package/templates/nextjs/template/src/middleware.ts.tmpl +0 -40
package/dist/next/config.d.ts
CHANGED
|
@@ -8,13 +8,5 @@ export interface WithAciOptions {
|
|
|
8
8
|
assetOrigin?: string;
|
|
9
9
|
/** Asset rewrite prefix. Defaults to '/.gradial-dam' */
|
|
10
10
|
assetPrefix?: string;
|
|
11
|
-
/**
|
|
12
|
-
* Customer-owned routes that ACI middleware should leave to Next.
|
|
13
|
-
*
|
|
14
|
-
* Use exact paths such as '/healthz' or simple Next-style catch-alls such as
|
|
15
|
-
* '/checkout/:path*'. CMS document routes such as '/robots.txt' and
|
|
16
|
-
* '/sitemap.xml' should be omitted so they stay release-scoped.
|
|
17
|
-
*/
|
|
18
|
-
passthroughRoutes?: string[];
|
|
19
11
|
}
|
|
20
12
|
export declare function withAci(nextConfig?: NextConfig, options?: WithAciOptions): NextConfig;
|
package/dist/next/config.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { readdirSync, existsSync } from 'fs';
|
|
2
|
-
import { join, relative } from 'path';
|
|
3
1
|
import { createRequire } from 'module';
|
|
4
2
|
import { createContentWatchWebpackPlugin } from './content-watch.js';
|
|
5
3
|
import { buildErrorSeatPayload } from './error-seat-payload.js';
|
|
@@ -7,11 +5,10 @@ const require = createRequire(import.meta.url);
|
|
|
7
5
|
export function withAci(nextConfig = {}, options = {}) {
|
|
8
6
|
if (process.env.TURBOPACK) {
|
|
9
7
|
throw new Error('withAci does not support Turbopack yet: ACI dev-mode content ' +
|
|
10
|
-
'compilation and
|
|
11
|
-
'
|
|
8
|
+
'compilation and build-time error-page payload are wired through the ' +
|
|
9
|
+
'webpack() callback, which Turbopack never invokes. Run ' +
|
|
12
10
|
'`next dev` / `next build` without --turbopack.');
|
|
13
11
|
}
|
|
14
|
-
const publicPaths = collectPublicPaths(join(process.cwd(), 'public'));
|
|
15
12
|
// Authorable error pages (D-9): the Next error seat is client-only, so the
|
|
16
13
|
// bound catchAll page's content is serialized here — while next.config is
|
|
17
14
|
// evaluated — and injected into the bundle via DefinePlugin below. The D-5
|
|
@@ -27,32 +24,15 @@ export function withAci(nextConfig = {}, options = {}) {
|
|
|
27
24
|
for (const warning of errorSeat.warnings) {
|
|
28
25
|
console.warn(`\n[aci error-pages] WARNING: ${warning}\n`);
|
|
29
26
|
}
|
|
30
|
-
const passthroughRoutes = normalizePassthroughRoutes(options.passthroughRoutes ?? []);
|
|
31
27
|
const assetPrefix = options.assetPrefix || '/.gradial-dam';
|
|
32
28
|
const assetOrigin = options.assetOrigin || '';
|
|
33
29
|
const userRewrites = nextConfig.rewrites;
|
|
34
|
-
const userHeaders = nextConfig.headers;
|
|
35
30
|
const userWebpack = nextConfig.webpack;
|
|
36
31
|
return {
|
|
37
32
|
...nextConfig,
|
|
38
33
|
output: 'standalone',
|
|
39
34
|
outputFileTracingRoot: nextConfig.outputFileTracingRoot ?? process.cwd(),
|
|
40
|
-
headers:
|
|
41
|
-
const gradialHeaders = [
|
|
42
|
-
{
|
|
43
|
-
source: '/__r/:releaseId/:path*',
|
|
44
|
-
headers: [
|
|
45
|
-
{ key: 'Cache-Control', value: 'public, max-age=0, must-revalidate' },
|
|
46
|
-
{ key: 'CDN-Cache-Control', value: 'max-age=31536000' },
|
|
47
|
-
{ key: 'Vercel-CDN-Cache-Control', value: 'max-age=31536000' },
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
];
|
|
51
|
-
if (!userHeaders)
|
|
52
|
-
return gradialHeaders;
|
|
53
|
-
const userResult = await (typeof userHeaders === 'function' ? userHeaders() : userHeaders);
|
|
54
|
-
return [...gradialHeaders, ...userResult];
|
|
55
|
-
},
|
|
35
|
+
headers: nextConfig.headers,
|
|
56
36
|
rewrites: async () => {
|
|
57
37
|
const rewrites = [];
|
|
58
38
|
if (assetOrigin) {
|
|
@@ -61,21 +41,6 @@ export function withAci(nextConfig = {}, options = {}) {
|
|
|
61
41
|
destination: `${assetOrigin}${assetPrefix}/:path*`,
|
|
62
42
|
});
|
|
63
43
|
}
|
|
64
|
-
else {
|
|
65
|
-
// Without an external asset origin (the deliberate CDN override),
|
|
66
|
-
// DAM requests must be served by the app itself: on Vercel nothing
|
|
67
|
-
// else maps `/.gradial-dam/*` to the hosting bucket. Route them to
|
|
68
|
-
// the asset handler, which serves DAM keys from the bucket root.
|
|
69
|
-
rewrites.push({
|
|
70
|
-
source: `${assetPrefix}/:path*`,
|
|
71
|
-
destination: `/gradial/assets/${assetPrefix.replace(/^\/+/, '')}/:path*`,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// CMS document rewrites: robots.txt and sitemap.xml are release-scoped
|
|
75
|
-
// artifacts served via the asset route handler (#40). The middleware
|
|
76
|
-
// passes them through (CMS_DOCUMENT_PATHS) so these rewrites fire and
|
|
77
|
-
// route to the asset handler which resolves the active release.
|
|
78
|
-
rewrites.push({ source: '/robots.txt', destination: '/gradial/assets/robots.txt' }, { source: '/sitemap.xml', destination: '/gradial/assets/sitemap.xml' });
|
|
79
44
|
if (!userRewrites)
|
|
80
45
|
return rewrites;
|
|
81
46
|
const userResult = await (typeof userRewrites === 'function' ? userRewrites() : userRewrites);
|
|
@@ -95,9 +60,6 @@ export function withAci(nextConfig = {}, options = {}) {
|
|
|
95
60
|
}
|
|
96
61
|
const webpack = require('webpack');
|
|
97
62
|
config.plugins.push(new webpack.DefinePlugin({
|
|
98
|
-
'__ACI_PUBLIC_PATHS__': JSON.stringify(publicPaths),
|
|
99
|
-
'__ACI_PASSTHROUGH_ROUTES__': JSON.stringify(passthroughRoutes),
|
|
100
|
-
'__ACI_ASSET_PREFIX__': JSON.stringify(assetPrefix),
|
|
101
63
|
'__ACI_ERROR_PAGE__': JSON.stringify(errorSeat.payload),
|
|
102
64
|
}));
|
|
103
65
|
return typeof userWebpack === 'function'
|
|
@@ -106,40 +68,3 @@ export function withAci(nextConfig = {}, options = {}) {
|
|
|
106
68
|
},
|
|
107
69
|
};
|
|
108
70
|
}
|
|
109
|
-
function normalizePassthroughRoutes(routes) {
|
|
110
|
-
const out = [];
|
|
111
|
-
const seen = new Set();
|
|
112
|
-
for (const route of routes) {
|
|
113
|
-
const clean = normalizeRoutePattern(route);
|
|
114
|
-
if (!clean || seen.has(clean))
|
|
115
|
-
continue;
|
|
116
|
-
seen.add(clean);
|
|
117
|
-
out.push(clean);
|
|
118
|
-
}
|
|
119
|
-
return out;
|
|
120
|
-
}
|
|
121
|
-
function normalizeRoutePattern(route) {
|
|
122
|
-
const trimmed = route.trim();
|
|
123
|
-
if (!trimmed)
|
|
124
|
-
return '';
|
|
125
|
-
const withSlash = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
126
|
-
return withSlash.replace(/\/{2,}/g, '/').replace(/\/$/, '') || '/';
|
|
127
|
-
}
|
|
128
|
-
function collectPublicPaths(publicDir) {
|
|
129
|
-
if (!existsSync(publicDir))
|
|
130
|
-
return [];
|
|
131
|
-
const paths = [];
|
|
132
|
-
const walk = (dir) => {
|
|
133
|
-
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
134
|
-
const full = join(dir, entry.name);
|
|
135
|
-
if (entry.isDirectory()) {
|
|
136
|
-
walk(full);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
paths.push('/' + relative(publicDir, full).split('\\').join('/'));
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
walk(publicDir);
|
|
144
|
-
return paths;
|
|
145
|
-
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
|
-
import { type FetchConfig } from './server.js';
|
|
3
2
|
import { type ErrorPageKind, type ErrorPagePush, type ResolvedErrorPage } from '../content/error-pages.js';
|
|
4
3
|
import type { KernelSiteConfig } from '../content/types.js';
|
|
5
4
|
import type { Registry } from '../registry.js';
|
|
@@ -18,7 +17,7 @@ export interface NextResolvedErrorPage extends ResolvedErrorPage {
|
|
|
18
17
|
* the shipped default — an error surface must not re-enter the failing
|
|
19
18
|
* system (ANTI-2).
|
|
20
19
|
*/
|
|
21
|
-
export declare function resolveErrorPage(kind: ErrorPageKind
|
|
20
|
+
export declare function resolveErrorPage(kind: ErrorPageKind): Promise<NextResolvedErrorPage>;
|
|
22
21
|
/**
|
|
23
22
|
* Renders the content page bound to `route` through the normal page
|
|
24
23
|
* pipeline (createPage: layout slots, fragments, registry blocks, collect/
|
|
@@ -47,6 +46,6 @@ export declare function DefaultErrorPageContent(): import("react").JSX.Element;
|
|
|
47
46
|
* `pushErrorPageView` (D-15): the tenant-owned policy module's push,
|
|
48
47
|
* forwarded to ErrorPageInstrumentation; omitted → the SDK default.
|
|
49
48
|
*/
|
|
50
|
-
export declare function createNotFound(registry: Registry,
|
|
49
|
+
export declare function createNotFound(registry: Registry, options?: {
|
|
51
50
|
pushErrorPageView?: ErrorPagePush;
|
|
52
51
|
}): () => Promise<ReactElement>;
|
package/dist/next/error-pages.js
CHANGED
|
@@ -12,11 +12,11 @@ import { ErrorPageMarker } from './error-page-marker.js';
|
|
|
12
12
|
* the shipped default — an error surface must not re-enter the failing
|
|
13
13
|
* system (ANTI-2).
|
|
14
14
|
*/
|
|
15
|
-
export async function resolveErrorPage(kind
|
|
15
|
+
export async function resolveErrorPage(kind) {
|
|
16
16
|
let siteConfig = null;
|
|
17
17
|
const warnings = [];
|
|
18
18
|
try {
|
|
19
|
-
siteConfig = await getSiteConfig(
|
|
19
|
+
siteConfig = await getSiteConfig();
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
22
|
warnings.push(`site config unavailable at the error seat: ${String(error)}`);
|
|
@@ -58,7 +58,7 @@ export function DefaultErrorPageContent() {
|
|
|
58
58
|
* `pushErrorPageView` (D-15): the tenant-owned policy module's push,
|
|
59
59
|
* forwarded to ErrorPageInstrumentation; omitted → the SDK default.
|
|
60
60
|
*/
|
|
61
|
-
export function createNotFound(registry,
|
|
61
|
+
export function createNotFound(registry, options = {}) {
|
|
62
62
|
return async function NotFound() {
|
|
63
63
|
// Force dynamic rendering: Next prerenders /_not-found at build time,
|
|
64
64
|
// where no content provider is reachable. The DYNAMIC_SERVER_USAGE
|
|
@@ -73,7 +73,7 @@ export function createNotFound(registry, config = {}) {
|
|
|
73
73
|
if (typeof digest === 'string' && digest.startsWith('DYNAMIC_SERVER_USAGE'))
|
|
74
74
|
throw error;
|
|
75
75
|
}
|
|
76
|
-
const resolved = await resolveErrorPage('notFound'
|
|
76
|
+
const resolved = await resolveErrorPage('notFound');
|
|
77
77
|
for (const warning of resolved.warnings) {
|
|
78
78
|
console.warn(`[aci error-pages] ${warning}`);
|
|
79
79
|
}
|
|
@@ -89,6 +89,6 @@ export function createNotFound(registry, config = {}) {
|
|
|
89
89
|
content = null;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
return (_jsxs(_Fragment, { children: [content ?? _jsx(DefaultErrorPageContent, {}), _jsx(ErrorPageMarker, { kind: "notFound" }), _jsx(ErrorPageInstrumentation, { kind: "notFound", push:
|
|
92
|
+
return (_jsxs(_Fragment, { children: [content ?? _jsx(DefaultErrorPageContent, {}), _jsx(ErrorPageMarker, { kind: "notFound" }), _jsx(ErrorPageInstrumentation, { kind: "notFound", push: options.pushErrorPageView })] }));
|
|
93
93
|
};
|
|
94
94
|
}
|
|
@@ -6,9 +6,8 @@ import type { Registry } from '../registry.js';
|
|
|
6
6
|
* D-9): Next's error seat is client-only and cannot reach the server content
|
|
7
7
|
* provider, so withAci() resolves `site.json#errorPages.catchAll` while
|
|
8
8
|
* next.config is evaluated and injects the page's resolved slots into the
|
|
9
|
-
* bundle as the `__ACI_ERROR_PAGE__` webpack define
|
|
10
|
-
*
|
|
11
|
-
* therefore require a code build — accepted by D-4.
|
|
9
|
+
* bundle as the `__ACI_ERROR_PAGE__` webpack define. Content edits to the
|
|
10
|
+
* bound page therefore require a code build — accepted by D-4.
|
|
12
11
|
*/
|
|
13
12
|
export interface ErrorSeatPayload {
|
|
14
13
|
/** True when no binding is authored: render the shipped default (REQ-4). */
|
package/dist/next/index.d.ts
CHANGED
|
@@ -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 { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams } from './server.js';
|
|
5
|
+
export { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams, setReleaseObjectReader } from './server.js';
|
|
6
|
+
export type { HostedContentContext } 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';
|
package/dist/next/index.js
CHANGED
|
@@ -2,10 +2,9 @@ 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
|
-
export { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams } from './server.js';
|
|
5
|
+
export { getSiteConfig, getFragment, getLayout, getPage, getRenderInput, routeFromNextParams, setReleaseObjectReader } from './server.js';
|
|
6
6
|
export { PageNotFoundError, FragmentNotFoundError, LayoutNotFoundError } from './server.js';
|
|
7
7
|
export { CollectScript } from './collect-script.js';
|
|
8
|
-
export { aciMiddlewareMatcher } from './middleware.js';
|
|
9
8
|
export { AssignmentsScript } from './assignments-script.js';
|
|
10
9
|
export { createNotFound, renderPageForRoute, resolveErrorPage, } from './error-pages.js';
|
|
11
10
|
export { ErrorPageInstrumentation } from './error-page-instrumentation.js';
|
package/dist/next/page.d.ts
CHANGED
|
@@ -30,19 +30,9 @@ export interface CreatePageOptions {
|
|
|
30
30
|
* When the site config enables personalization, the page tree also carries
|
|
31
31
|
* the collect script tag exactly once per page (design/04 contract tag).
|
|
32
32
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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/*`).
|
|
40
|
-
*
|
|
41
|
-
* Dev pass-through (ACI_CONTENT_PROVIDER=file): the middleware passes
|
|
42
|
-
* requests through unrewritten, so `/` arrives with an empty/undefined
|
|
43
|
-
* slug and `/about` arrives as `['about']`. The optional catch-all
|
|
44
|
-
* `[[...slug]]` handles both cases. No releaseId is present; the file
|
|
45
|
-
* provider serves content directly from disk.
|
|
33
|
+
* In SSR delivery the provider edge rewrites to an immutable release/page
|
|
34
|
+
* path. The SDK derives the exact JSON ref from that path and renders it with
|
|
35
|
+
* the same registry used by static publishing.
|
|
46
36
|
*
|
|
47
37
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
48
38
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
package/dist/next/page.js
CHANGED
|
@@ -6,7 +6,6 @@ import { routeMetadataForContent, resolveSlots, } from '../content/index.js';
|
|
|
6
6
|
import { renderBlocks } from './render.js';
|
|
7
7
|
import { AssignmentsScript } from './assignments-script.js';
|
|
8
8
|
import { CollectScript } from './collect-script.js';
|
|
9
|
-
import { renderProofContentFor } from '../internal/render-proof.js';
|
|
10
9
|
/**
|
|
11
10
|
* Creates the catch-all route handler for a Next.js ACI site.
|
|
12
11
|
*
|
|
@@ -27,19 +26,9 @@ import { renderProofContentFor } from '../internal/render-proof.js';
|
|
|
27
26
|
* When the site config enables personalization, the page tree also carries
|
|
28
27
|
* the collect script tag exactly once per page (design/04 contract tag).
|
|
29
28
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* extracts the releaseId and passes it to the content loader, giving
|
|
34
|
-
* each release a unique CDN cache key without a separate route folder.
|
|
35
|
-
* The `routes` namespace segment leaves room for future siblings under
|
|
36
|
-
* the release prefix (e.g. `/__r/{releaseId}/assets/*`).
|
|
37
|
-
*
|
|
38
|
-
* Dev pass-through (ACI_CONTENT_PROVIDER=file): the middleware passes
|
|
39
|
-
* requests through unrewritten, so `/` arrives with an empty/undefined
|
|
40
|
-
* slug and `/about` arrives as `['about']`. The optional catch-all
|
|
41
|
-
* `[[...slug]]` handles both cases. No releaseId is present; the file
|
|
42
|
-
* provider serves content directly from disk.
|
|
29
|
+
* In SSR delivery the provider edge rewrites to an immutable release/page
|
|
30
|
+
* path. The SDK derives the exact JSON ref from that path and renders it with
|
|
31
|
+
* the same registry used by static publishing.
|
|
43
32
|
*
|
|
44
33
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
45
34
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
|
@@ -47,10 +36,14 @@ import { renderProofContentFor } from '../internal/render-proof.js';
|
|
|
47
36
|
* be CMS-managed fragments instead of hardcoded component imports.
|
|
48
37
|
*/
|
|
49
38
|
export function createPage(registry, options) {
|
|
39
|
+
// The compiler invokes this route repeatedly against isolated content
|
|
40
|
+
// snapshots while producing immutable HTML. It must not let Next cache the
|
|
41
|
+
// first snapshot. Deployed CMS traffic is intercepted by the provider
|
|
42
|
+
// gateway and never reaches this framework route.
|
|
50
43
|
const dynamic = 'force-dynamic';
|
|
51
44
|
async function generateMetadata({ params }) {
|
|
52
|
-
const
|
|
53
|
-
const input = await getRenderInput(route,
|
|
45
|
+
const resolved = await resolveRoute(params);
|
|
46
|
+
const input = await getRenderInput(resolved.route, resolved.context);
|
|
54
47
|
const meta = routeMetadataForContent(input.siteConfig, input.page);
|
|
55
48
|
return {
|
|
56
49
|
title: meta.title,
|
|
@@ -64,15 +57,14 @@ export function createPage(registry, options) {
|
|
|
64
57
|
};
|
|
65
58
|
}
|
|
66
59
|
async function CatchAllPage({ params }) {
|
|
67
|
-
const
|
|
68
|
-
const
|
|
60
|
+
const resolved = await resolveRoute(params);
|
|
61
|
+
const context = resolved.context;
|
|
69
62
|
try {
|
|
70
|
-
const input = await getRenderInput(route,
|
|
63
|
+
const input = await getRenderInput(resolved.route, context);
|
|
71
64
|
if (!input.page)
|
|
72
65
|
notFound();
|
|
73
|
-
const
|
|
74
|
-
const
|
|
75
|
-
const resolvedSlots = await resolveSlots(layout, input.page.regions || {}, (id) => getFragment(id, fetchConfig));
|
|
66
|
+
const layout = await getLayout(input.page.layout, context);
|
|
67
|
+
const resolvedSlots = await resolveSlots(layout, input.page.regions || {}, (id) => getFragment(id, context));
|
|
76
68
|
const renderedSlots = await Promise.all(layout.slots.map(async (slot) => {
|
|
77
69
|
const blocks = resolvedSlots[slot.name];
|
|
78
70
|
if (!blocks?.length)
|
|
@@ -84,9 +76,7 @@ export function createPage(registry, options) {
|
|
|
84
76
|
}
|
|
85
77
|
return (_jsx(Fragment, { children: renderedBlocks }, slot.name));
|
|
86
78
|
}));
|
|
87
|
-
return (_jsxs(_Fragment, { children: [
|
|
88
|
-
? _jsx("meta", { name: "aci-render-proof", content: renderProofContent })
|
|
89
|
-
: null, renderedSlots.filter(Boolean), _jsx(AssignmentsScript, { page: input.page }), _jsx(CollectScript, { siteConfig: input.siteConfig })] }));
|
|
79
|
+
return (_jsxs(_Fragment, { children: [renderedSlots.filter(Boolean), _jsx(AssignmentsScript, { page: input.page }), _jsx(CollectScript, { siteConfig: input.siteConfig })] }));
|
|
90
80
|
}
|
|
91
81
|
catch (error) {
|
|
92
82
|
if (error instanceof PageNotFoundError)
|
|
@@ -101,43 +91,41 @@ export function createPage(registry, options) {
|
|
|
101
91
|
};
|
|
102
92
|
}
|
|
103
93
|
/**
|
|
104
|
-
* Resolves the logical route
|
|
105
|
-
*
|
|
106
|
-
* Two shapes are supported:
|
|
107
|
-
*
|
|
108
|
-
* 1. **Rewritten (production):** middleware rewrites a public URL to
|
|
109
|
-
* `/__r/{releaseId}/routes/{path}`, so slug is
|
|
110
|
-
* `['__r', releaseId, 'routes', ...pathSegments]`. The releaseId is
|
|
111
|
-
* extracted; the remaining segments form the content route. The `routes`
|
|
112
|
-
* segment is the namespace for page routes (siblings like `assets/` live
|
|
113
|
-
* under the same release prefix).
|
|
114
|
-
*
|
|
115
|
-
* 2. **Dev pass-through (ACI_CONTENT_PROVIDER=file):** middleware passes
|
|
116
|
-
* requests through unrewritten, so the slug is the raw public path
|
|
117
|
-
* segments (possibly empty/undefined for `/`). No releaseId is present;
|
|
118
|
-
* the file provider serves content from disk.
|
|
94
|
+
* Resolves the logical source route used while building static output.
|
|
119
95
|
*/
|
|
120
|
-
async function
|
|
96
|
+
async function resolveRoute(params) {
|
|
121
97
|
const resolved = await params;
|
|
122
98
|
const slug = resolved.slug ?? [];
|
|
123
99
|
if (slug.length >= 2 && slug[0] === '__r') {
|
|
124
|
-
const releaseId =
|
|
125
|
-
|
|
100
|
+
const releaseId = slug[1];
|
|
101
|
+
const selected = slug.slice(2);
|
|
102
|
+
if (!portableReleaseId(releaseId) || selected.some((part) => !portablePathPart(part))) {
|
|
126
103
|
return { route: '/' };
|
|
127
104
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (rest.length === 0)
|
|
131
|
-
return { route: '/', releaseId };
|
|
132
|
-
if (rest.some((s) => s === '' || s === '.' || s === '..'))
|
|
105
|
+
const variantAt = selected.indexOf('__variant');
|
|
106
|
+
if (variantAt >= 0 && (variantAt !== selected.length - 2 || !selected[variantAt + 1])) {
|
|
133
107
|
return { route: '/' };
|
|
134
|
-
|
|
108
|
+
}
|
|
109
|
+
const routeParts = variantAt < 0 ? selected : selected.slice(0, variantAt);
|
|
110
|
+
const route = routeFromSlug(routeParts);
|
|
111
|
+
const pageRef = [
|
|
112
|
+
'routes',
|
|
113
|
+
...routeParts,
|
|
114
|
+
...(variantAt < 0 ? [] : ['__variant', selected[variantAt + 1]]),
|
|
115
|
+
'index.json',
|
|
116
|
+
].join('/');
|
|
117
|
+
return { route, context: { releaseId, pageRef } };
|
|
135
118
|
}
|
|
136
|
-
|
|
137
|
-
return { route };
|
|
119
|
+
return { route: routeFromSlug(slug) };
|
|
138
120
|
}
|
|
139
121
|
function routeFromSlug(slug) {
|
|
140
122
|
if (slug.length === 0)
|
|
141
123
|
return '/';
|
|
142
124
|
return `/${slug.join('/')}/`;
|
|
143
125
|
}
|
|
126
|
+
function portableReleaseId(value) {
|
|
127
|
+
return value.length <= 128 && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value);
|
|
128
|
+
}
|
|
129
|
+
function portablePathPart(value) {
|
|
130
|
+
return value.length > 0 && value !== '.' && value !== '..' && !value.includes('/');
|
|
131
|
+
}
|
package/dist/next/server.d.ts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
import { FragmentNotFoundError, LayoutNotFoundError, PageNotFoundError } from '../content/provider.js';
|
|
2
|
-
import type
|
|
2
|
+
import { type ReleaseObjectReader } from '../providers/object.js';
|
|
3
3
|
export { FragmentNotFoundError, PageNotFoundError, LayoutNotFoundError };
|
|
4
|
-
export interface FetchConfig {
|
|
5
|
-
siteId?: string;
|
|
6
|
-
bucket?: string;
|
|
7
|
-
keyPrefix?: string;
|
|
8
|
-
region?: string;
|
|
9
|
-
accessKeyId?: string;
|
|
10
|
-
secretAccessKey?: string;
|
|
11
|
-
sessionToken?: string;
|
|
12
|
-
roleArn?: string;
|
|
13
|
-
endpoint?: string;
|
|
14
|
-
releaseId?: string;
|
|
15
|
-
edgeConfig?: string;
|
|
16
|
-
deploymentId?: string;
|
|
17
|
-
}
|
|
18
4
|
export interface ServerRenderInput<TPage, TSite extends SiteConfig = SiteConfig> {
|
|
19
5
|
route: string;
|
|
20
6
|
domain: string;
|
|
@@ -27,13 +13,17 @@ export interface SiteConfig {
|
|
|
27
13
|
domain?: string;
|
|
28
14
|
defaultLocale?: string;
|
|
29
15
|
}
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export declare function
|
|
35
|
-
export declare function
|
|
36
|
-
export declare function
|
|
16
|
+
export interface HostedContentContext {
|
|
17
|
+
releaseId?: string;
|
|
18
|
+
pageRef?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function setReleaseObjectReader(reader: ReleaseObjectReader | undefined): void;
|
|
21
|
+
export declare function getPage<T = unknown>(route?: string, context?: HostedContentContext): Promise<T>;
|
|
22
|
+
export declare function getSiteConfig<T extends SiteConfig = SiteConfig>(context?: HostedContentContext): Promise<T>;
|
|
23
|
+
export declare function getFragment<T = unknown>(name: string, context?: HostedContentContext): Promise<T>;
|
|
24
|
+
export declare function getLayout<T = unknown>(name: string, context?: HostedContentContext): Promise<T>;
|
|
25
|
+
export declare function getRoutes(context?: HostedContentContext): Promise<string[]>;
|
|
26
|
+
export declare function getRenderInput<TPage, TSite extends SiteConfig = SiteConfig>(route?: string, context?: HostedContentContext): Promise<ServerRenderInput<TPage, TSite>>;
|
|
37
27
|
export { isPreviewMode } from './preview-mode.js';
|
|
38
28
|
export declare function routeFromNextParams(params: Promise<{
|
|
39
29
|
slug?: string[];
|
|
@@ -43,13 +33,3 @@ export declare function routeFromNextParams(params: Promise<{
|
|
|
43
33
|
export declare function generateStaticParams(): Promise<Array<{
|
|
44
34
|
slug?: string[];
|
|
45
35
|
}>>;
|
|
46
|
-
export declare class ReleaseAssetNotFoundError extends Error {
|
|
47
|
-
constructor(releaseId: string, assetPath: string, cause?: unknown);
|
|
48
|
-
}
|
|
49
|
-
export declare function getReleaseAssetResponse(releaseId: string, assetPath: string, config?: FetchConfig): Promise<Response>;
|
|
50
|
-
export declare function isDamAssetPath(assetPath: string): boolean;
|
|
51
|
-
export declare class DamAssetNotFoundError extends Error {
|
|
52
|
-
constructor(assetPath: string, cause?: unknown);
|
|
53
|
-
}
|
|
54
|
-
export declare function getDamAssetResponse(assetPath: string, config?: FetchConfig): Promise<Response>;
|
|
55
|
-
export declare function resolveReleaseId(config?: FetchConfig): Promise<string>;
|