@gradial/aci 0.1.31 → 0.1.33
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 +4 -4
- package/bin/aci-darwin-arm64 +0 -0
- package/bin/aci.js +29 -31
- package/dist/astro/assets.d.ts +46 -0
- package/dist/astro/assets.js +51 -0
- package/dist/astro/index.d.ts +2 -0
- package/dist/astro/index.js +8 -0
- package/dist/astro/page.d.ts +88 -0
- package/dist/astro/page.js +117 -0
- package/dist/dev/content-watch.d.ts +1 -0
- package/dist/dev/content-watch.js +1 -1
- package/dist/next/config.d.ts +6 -0
- package/dist/next/config.js +20 -13
- package/dist/next/content-watch.d.ts +1 -0
- package/dist/next/content-watch.js +2 -2
- package/dist/next/index.d.ts +1 -0
- package/dist/next/index.js +1 -0
- package/dist/next/middleware.d.ts +3 -2
- package/dist/next/middleware.js +40 -7
- package/dist/next/page.d.ts +13 -5
- package/dist/next/page.js +42 -17
- package/dist/next/server.d.ts +1 -1
- package/dist/next/server.js +7 -8
- package/dist/testing/conformance/checks.d.ts +12 -0
- package/dist/testing/conformance/checks.js +483 -0
- package/dist/testing/conformance/index.d.ts +3 -0
- package/dist/testing/conformance/index.js +2 -0
- package/dist/testing/conformance/preset.d.ts +14 -0
- package/dist/testing/conformance/preset.js +98 -0
- package/dist/testing/conformance/types.d.ts +45 -0
- package/dist/testing/conformance/types.js +7 -0
- package/package.json +17 -9
- package/src/cli/materialize-template.mjs +133 -0
- package/src/cli/validate-content.mjs +0 -0
- package/src/cli/verify-next-cdn-routes.mjs +10 -19
- package/templates/astro/starter-content/src/cms/contracts/components/button.contract.ts +19 -0
- package/templates/astro/starter-content/src/cms/contracts/components/container.contract.ts +19 -0
- package/templates/astro/starter-content/src/cms/contracts/components/featureCard.contract.ts +15 -0
- package/templates/astro/starter-content/src/cms/contracts/components/featureGrid.contract.ts +16 -0
- package/templates/astro/starter-content/src/cms/contracts/components/homeHero.contract.ts +36 -0
- package/templates/astro/starter-content/src/cms/contracts/components/index.ts +21 -0
- package/templates/astro/starter-content/src/cms/contracts/components/statsBar.contract.ts +19 -0
- package/templates/astro/starter-content/src/cms/registry.ts +28 -0
- package/templates/astro/template/{.aci.yaml → .aci.yaml.tmpl} +1 -1
- package/templates/astro/template/README.md.tmpl +53 -0
- package/templates/astro/template/gitignore +12 -0
- package/templates/astro/template/package.json.tmpl +5 -3
- package/templates/astro/template/src/cms/contracts/components/index.ts +3 -0
- package/templates/astro/template/src/cms/registry.ts +3 -26
- package/templates/astro/template/src/pages/[...slug].astro +13 -35
- package/templates/astro/template/tests/conformance.test.ts.tmpl +12 -0
- package/templates/common/.agents/AGENTS.md +3 -5
- package/templates/common/.agents/skills/aci/SKILL.md +72 -23
- package/templates/common/.agents/skills/authoring/SKILL.md +53 -14
- package/templates/common/.agents/skills/authoring/references/block-registry.md +109 -15
- package/templates/common/.agents/skills/authoring/references/contracts.md +23 -7
- package/templates/common/.agents/skills/authoring/references/repo-structure.md +35 -19
- package/templates/common/.agents/skills/authoring/references/sdk-server-functions.md +75 -17
- package/templates/common/.agents/skills/migration/SKILL.md +7 -1
- package/templates/common/.agents/skills/migration/references/canon-migration.md +471 -0
- package/templates/common/.content/config/site.json.tmpl +15 -0
- package/templates/common/.content/pages/home/_index.json +4 -103
- package/templates/common/.nvmrc +1 -0
- package/templates/common/README.md.tmpl +32 -11
- package/templates/common/contracts/components/index.ts +1 -19
- package/templates/common/design-system/tokens/colors.css +34 -10
- package/templates/common/starter-content/.content/config/robots.txt +2 -0
- package/templates/common/starter-content/.content/pages/home/_index.json +112 -0
- package/templates/common/starter-content/.content/schemas/site.schema.json +138 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/container.contract.ts +19 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/featureCard.contract.ts +15 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/featureGrid.contract.ts +16 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/index.ts +21 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/siteFooter.contract.ts +45 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/siteNavigation.contract.ts +30 -0
- package/templates/nextjs/starter-content/src/cms/contracts/components/statsBar.contract.ts +19 -0
- package/templates/nextjs/starter-content/src/cms/registry.ts +28 -0
- package/templates/nextjs/template/{.aci.yaml → .aci.yaml.tmpl} +1 -1
- package/templates/nextjs/template/README.md.tmpl +52 -0
- package/templates/nextjs/template/gitignore +15 -0
- package/templates/nextjs/template/next.config.mjs +1 -6
- package/templates/nextjs/template/package.json.tmpl +5 -3
- package/templates/nextjs/template/src/app/gradial/assets/[...path]/route.ts +1 -4
- package/templates/nextjs/template/src/cms/contracts/components/index.ts +1 -13
- package/templates/nextjs/template/src/cms/registry.ts +3 -26
- package/templates/nextjs/template/src/design-system/styles.css +346 -0
- package/templates/nextjs/template/src/design-system/tokens/colors.css +110 -0
- package/templates/nextjs/template/src/design-system/tokens/components.css +86 -0
- package/templates/nextjs/template/src/design-system/tokens/index.css +6 -0
- package/templates/nextjs/template/src/design-system/tokens/radii.css +5 -0
- package/templates/nextjs/template/src/design-system/tokens/shadows.css +9 -0
- package/templates/nextjs/template/src/design-system/tokens/spacing.css +26 -0
- package/templates/nextjs/template/src/design-system/tokens/typography.css +32 -0
- package/templates/nextjs/template/src/middleware.ts.tmpl +12 -0
- package/templates/nextjs/template/tests/conformance.test.ts.tmpl +12 -0
- package/templates/nextjs/template/src/cms/contracts/components/container.contract.ts +0 -20
- package/templates/nextjs/template/src/middleware.ts +0 -7
- /package/templates/{nextjs/template → astro/starter-content}/src/cms/contracts/components/siteFooter.contract.ts +0 -0
- /package/templates/{nextjs/template → astro/starter-content}/src/cms/contracts/components/siteNavigation.contract.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/components/chrome/Footer.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/chrome/Header.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/AtomicBlock.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/AtomicBlocks.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/Button.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/ButtonBlock.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/Container.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/Icon.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/Logo.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/elements/RemoteImage.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/sections/ContainerSection.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/sections/FeatureCard.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/sections/FeatureGrid.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/sections/HomeHero.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/components/sections/StatsBar.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/fixtures/atomicBlocks.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/fixtures/composition.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/fixtures/index.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/fixtures/sections.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/render/RenderPage.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/stories/CompositionStoryFrame.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/stories/HomeHero.stories.ts +0 -0
- /package/templates/astro/{template → starter-content}/src/stories/SectionStoryFrame.astro +0 -0
- /package/templates/astro/{template → starter-content}/src/stories/StoryDocFrame.astro +0 -0
- /package/templates/common/{.content → starter-content/.content}/.gradial-dam/blobs/sha256/7f/bf/7fbfc7fe230ff12688c496f660119e41d9725c4504d82e310c15665c73c09292 +0 -0
- /package/templates/common/{.content → starter-content/.content}/.gradial-dam/blobs/sha256/a0/f5/a0f506689de9b15a7055f70103a3f02cd3ba105771ae2de6754df2ede1210d3a +0 -0
- /package/templates/common/{.content → starter-content/.content}/.gradial-dam/blobs/sha256/dd/b7/ddb7e9642be08317bcd4b2bd26b58ba8d0d34dd7239e03e684a4f3634fa3845b +0 -0
- /package/templates/common/{.content → starter-content/.content}/.gradial-dam/blobs/sha256/fb/32/fb3260e8286ea8231ea1c77b9c0be92d6edd9026565731eb14cfdcfd6b1b75b3 +0 -0
- /package/templates/common/{.content → starter-content/.content}/config/site.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_about_hero/asset.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_about_hero/editorial.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_about_hero/governance.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_about_hero/versions/v0001.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_home_hero/asset.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_home_hero/editorial.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_home_hero/governance.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/dam/folders/seed/ast_site_home_hero/versions/v0001.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/fragments/navbar/_index.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/fragments/site-footer/_index.json +0 -0
- /package/templates/common/{.content → starter-content/.content}/pages/about/_index.json +0 -0
- /package/templates/common/{public → starter-content/public}/assets/Dwire-model.png +0 -0
- /package/templates/common/{public → starter-content/public}/assets/seattle.avif +0 -0
- /package/templates/nextjs/{template → starter-content}/src/cms/contracts/components/button.contract.ts +0 -0
- /package/templates/nextjs/{template → starter-content}/src/cms/contracts/components/homeHero.contract.ts +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/chrome/Footer.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/chrome/Header.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/AtomicBlock.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/Button.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/ButtonBlock.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/Container.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/Icon.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/elements/Logo.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/sections/ContainerSection.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/sections/FeatureCard.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/sections/FeatureGrid.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/sections/HomeHero.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/components/sections/StatsBar.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/stories/Button.stories.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/stories/Header.stories.tsx +0 -0
- /package/templates/nextjs/{template → starter-content}/src/stories/HomeHero.stories.tsx +0 -0
package/dist/next/middleware.js
CHANGED
|
@@ -2,9 +2,15 @@ import { NextResponse } from 'next/server.js';
|
|
|
2
2
|
import { getUncachedEdgeConfigValue } from './edge-config.js';
|
|
3
3
|
import { PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, extractPreviewToken, resolvePreviewContext, createPreviewCookies, previewSignKey, } from '../preview/core.js';
|
|
4
4
|
const RELEASE_SCOPED_PREFIX = '/__r';
|
|
5
|
+
// CMS document paths (robots.txt, sitemap.xml) pass through the middleware
|
|
6
|
+
// and are served by Next.js rewrites configured in withAci().
|
|
7
|
+
const CMS_DOCUMENT_PATHS = new Set(['/robots.txt', '/sitemap.xml']);
|
|
5
8
|
const PUBLIC_PATHS = new Set(typeof __ACI_PUBLIC_PATHS__ !== 'undefined' ? __ACI_PUBLIC_PATHS__ : []);
|
|
6
9
|
const PASSTHROUGH_ROUTES = (typeof __ACI_PASSTHROUGH_ROUTES__ !== 'undefined' ? __ACI_PASSTHROUGH_ROUTES__ : []);
|
|
7
|
-
|
|
10
|
+
const ASSET_PREFIX = typeof __ACI_ASSET_PREFIX__ !== 'undefined'
|
|
11
|
+
? __ACI_ASSET_PREFIX__
|
|
12
|
+
: '/.gradial-dam';
|
|
13
|
+
export function createGradialMiddleware(config) {
|
|
8
14
|
return async function middleware(request) {
|
|
9
15
|
const url = request.nextUrl;
|
|
10
16
|
// ?leave_preview=1 → clear cookies, redirect to clean URL
|
|
@@ -18,6 +24,14 @@ export function createGradialMiddleware(config = {}) {
|
|
|
18
24
|
if (PUBLIC_PATHS.has(url.pathname)) {
|
|
19
25
|
return NextResponse.next();
|
|
20
26
|
}
|
|
27
|
+
if (CMS_DOCUMENT_PATHS.has(url.pathname)) {
|
|
28
|
+
return NextResponse.next();
|
|
29
|
+
}
|
|
30
|
+
// DAM asset requests are NOT release-scoped; they rewrite to S3 via
|
|
31
|
+
// withAci() rewrites. Pass them through so the rewrite fires.
|
|
32
|
+
if (isAssetPath(url.pathname)) {
|
|
33
|
+
return NextResponse.next();
|
|
34
|
+
}
|
|
21
35
|
if (isPassthroughRoute(url.pathname)) {
|
|
22
36
|
return NextResponse.next();
|
|
23
37
|
}
|
|
@@ -31,11 +45,24 @@ export function createGradialMiddleware(config = {}) {
|
|
|
31
45
|
// Try preview token first; if valid, use that release.
|
|
32
46
|
// If no token or invalid, fall through to active release from edge config.
|
|
33
47
|
const preview = await resolvePreviewFromRequest(request, config);
|
|
48
|
+
// Local file-backed development has no release-indexed artifact tree. A
|
|
49
|
+
// valid preview token is still useful there—it proves signing, expiry, and
|
|
50
|
+
// cookie propagation—but rewriting to /__r/{releaseId}/{path} would create
|
|
51
|
+
// a path the file provider cannot serve. Keep the public route and mark
|
|
52
|
+
// the response private, matching preview's cache semantics.
|
|
53
|
+
if (process.env.ACI_CONTENT_PROVIDER === 'file') {
|
|
54
|
+
const response = NextResponse.next();
|
|
55
|
+
const previewReleaseID = preview?.releaseId;
|
|
56
|
+
if (preview?.token && preview.isPreview && previewReleaseID) {
|
|
57
|
+
response.headers.set('Cache-Control', 'private, no-store');
|
|
58
|
+
for (const cookie of createPreviewCookies(preview.token, previewReleaseID)) {
|
|
59
|
+
response.cookies.set(cookie.name, cookie.value, cookie.options);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return response;
|
|
63
|
+
}
|
|
34
64
|
const releaseId = preview?.releaseId || await activeReleaseFromEdgeConfig(config);
|
|
35
65
|
if (!releaseId) {
|
|
36
|
-
if (process.env.ACI_CONTENT_PROVIDER === 'file') {
|
|
37
|
-
return NextResponse.next();
|
|
38
|
-
}
|
|
39
66
|
if (!siteIdForConfig(config)) {
|
|
40
67
|
return new Response('ACI site id is not configured', {
|
|
41
68
|
status: 500,
|
|
@@ -61,7 +88,7 @@ export function createGradialMiddleware(config = {}) {
|
|
|
61
88
|
return response;
|
|
62
89
|
}
|
|
63
90
|
// Rewrite public URL to release-scoped internal path for CDN cache isolation.
|
|
64
|
-
// Each release gets a unique URL (/__r/{releaseId}
|
|
91
|
+
// Each release gets a unique URL (/__r/{releaseId}/...) so the CDN
|
|
65
92
|
// cache key is per-release. New release = new URL = cache miss = fresh content.
|
|
66
93
|
const response = rewriteToReleaseScopedPath(request, releaseId, Boolean(preview?.isPreview));
|
|
67
94
|
// Persist preview token as cookie so navigation stays in preview
|
|
@@ -159,7 +186,7 @@ async function activeReleaseFromEdgeConfig(config) {
|
|
|
159
186
|
return clampRelease(active.releaseId, active.sequence || 0, compatibility);
|
|
160
187
|
}
|
|
161
188
|
function siteIdForConfig(config) {
|
|
162
|
-
return config.siteId
|
|
189
|
+
return config.siteId;
|
|
163
190
|
}
|
|
164
191
|
async function getEdgeConfigJSON(edgeConfig, key) {
|
|
165
192
|
const value = await getEdgeConfigValue(edgeConfig, key);
|
|
@@ -216,6 +243,9 @@ function clampRelease(activeReleaseId, activeSequence, compatibility) {
|
|
|
216
243
|
function edgeKeySegment(value) {
|
|
217
244
|
return value.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
218
245
|
}
|
|
246
|
+
function isAssetPath(pathname) {
|
|
247
|
+
return pathname === ASSET_PREFIX || pathname.startsWith(`${ASSET_PREFIX}/`);
|
|
248
|
+
}
|
|
219
249
|
function isPassthroughRoute(pathname) {
|
|
220
250
|
return PASSTHROUGH_ROUTES.some((route) => routeMatches(pathname, route));
|
|
221
251
|
}
|
|
@@ -241,6 +271,9 @@ function normalizeRoutePath(value) {
|
|
|
241
271
|
const pathname = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
242
272
|
return pathname.replace(/\/{2,}/g, '/').replace(/\/$/, '') || '/';
|
|
243
273
|
}
|
|
274
|
+
export const aciMiddlewareMatcher = [
|
|
275
|
+
'/((?!_next(?:/|$)|api(?:/|$)|favicon\\.ico$|\\.gradial-dam(?:/|$)).*)',
|
|
276
|
+
];
|
|
244
277
|
export const config = {
|
|
245
|
-
matcher:
|
|
278
|
+
matcher: aciMiddlewareMatcher,
|
|
246
279
|
};
|
package/dist/next/page.d.ts
CHANGED
|
@@ -30,11 +30,19 @@ 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
|
-
* Release-scoped routes:
|
|
34
|
-
* `/__r/{releaseId}/routes/{path}
|
|
35
|
-
* `['__r', releaseId, 'routes', ...pathSegments]`. createPage
|
|
36
|
-
*
|
|
37
|
-
*
|
|
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/*`).
|
|
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.
|
|
38
46
|
*
|
|
39
47
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
40
48
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
package/dist/next/page.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { notFound } from 'next/navigation.js';
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
|
-
import { PageNotFoundError,
|
|
4
|
+
import { PageNotFoundError, getRenderInput, getLayout, getFragment, } from './server.js';
|
|
5
5
|
import { routeMetadataForContent, resolveSlots, } from '../content/index.js';
|
|
6
6
|
import { renderBlocks } from './render.js';
|
|
7
7
|
import { CollectScript } from './collect-script.js';
|
|
@@ -25,11 +25,19 @@ import { CollectScript } from './collect-script.js';
|
|
|
25
25
|
* When the site config enables personalization, the page tree also carries
|
|
26
26
|
* the collect script tag exactly once per page (design/04 contract tag).
|
|
27
27
|
*
|
|
28
|
-
* Release-scoped routes:
|
|
29
|
-
* `/__r/{releaseId}/routes/{path}
|
|
30
|
-
* `['__r', releaseId, 'routes', ...pathSegments]`. createPage
|
|
31
|
-
*
|
|
32
|
-
*
|
|
28
|
+
* Release-scoped routes (production): the middleware rewrites a public URL
|
|
29
|
+
* to `/__r/{releaseId}/routes/{path}`. The optional catch-all `[[...slug]]`
|
|
30
|
+
* receives `['__r', releaseId, 'routes', ...pathSegments]`. createPage
|
|
31
|
+
* extracts the releaseId and passes it to the content loader, giving
|
|
32
|
+
* each release a unique CDN cache key without a separate route folder.
|
|
33
|
+
* The `routes` namespace segment leaves room for future siblings under
|
|
34
|
+
* the release prefix (e.g. `/__r/{releaseId}/assets/*`).
|
|
35
|
+
*
|
|
36
|
+
* Dev pass-through (ACI_CONTENT_PROVIDER=file): the middleware passes
|
|
37
|
+
* requests through unrewritten, so `/` arrives with an empty/undefined
|
|
38
|
+
* slug and `/about` arrives as `['about']`. The optional catch-all
|
|
39
|
+
* `[[...slug]]` handles both cases. No releaseId is present; the file
|
|
40
|
+
* provider serves content directly from disk.
|
|
33
41
|
*
|
|
34
42
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
35
43
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
|
@@ -87,26 +95,43 @@ export function createPage(registry, options) {
|
|
|
87
95
|
};
|
|
88
96
|
}
|
|
89
97
|
/**
|
|
90
|
-
* Resolves the logical route and
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
98
|
+
* Resolves the logical route and releaseId from Next.js catch-all params.
|
|
99
|
+
*
|
|
100
|
+
* Two shapes are supported:
|
|
101
|
+
*
|
|
102
|
+
* 1. **Rewritten (production):** middleware rewrites a public URL to
|
|
103
|
+
* `/__r/{releaseId}/routes/{path}`, so slug is
|
|
104
|
+
* `['__r', releaseId, 'routes', ...pathSegments]`. The releaseId is
|
|
105
|
+
* extracted; the remaining segments form the content route. The `routes`
|
|
106
|
+
* segment is the namespace for page routes (siblings like `assets/` live
|
|
107
|
+
* under the same release prefix).
|
|
108
|
+
*
|
|
109
|
+
* 2. **Dev pass-through (ACI_CONTENT_PROVIDER=file):** middleware passes
|
|
110
|
+
* requests through unrewritten, so the slug is the raw public path
|
|
111
|
+
* segments (possibly empty/undefined for `/`). No releaseId is present;
|
|
112
|
+
* the file provider serves content from disk.
|
|
94
113
|
*/
|
|
95
114
|
async function resolveRouteAndRelease(params) {
|
|
96
115
|
const resolved = await params;
|
|
97
|
-
const slug = resolved
|
|
98
|
-
if (slug
|
|
116
|
+
const slug = resolved.slug ?? [];
|
|
117
|
+
if (slug.length >= 2 && slug[0] === '__r') {
|
|
99
118
|
const releaseId = decodeURIComponent(slug[1]);
|
|
100
119
|
if (!releaseId || releaseId.includes('/') || releaseId === '.' || releaseId === '..') {
|
|
101
120
|
return { route: '/' };
|
|
102
121
|
}
|
|
103
|
-
|
|
104
|
-
|
|
122
|
+
// Skip the 'routes' namespace segment when present.
|
|
123
|
+
const rest = slug.length >= 3 && slug[2] === 'routes' ? slug.slice(3) : slug.slice(2);
|
|
124
|
+
if (rest.length === 0)
|
|
105
125
|
return { route: '/', releaseId };
|
|
106
|
-
if (
|
|
126
|
+
if (rest.some((s) => s === '' || s === '.' || s === '..'))
|
|
107
127
|
return { route: '/' };
|
|
108
|
-
return { route: `/${
|
|
128
|
+
return { route: `/${rest.join('/')}/`, releaseId };
|
|
109
129
|
}
|
|
110
|
-
const route =
|
|
130
|
+
const route = routeFromSlug(slug);
|
|
111
131
|
return { route };
|
|
112
132
|
}
|
|
133
|
+
function routeFromSlug(slug) {
|
|
134
|
+
if (slug.length === 0)
|
|
135
|
+
return '/';
|
|
136
|
+
return `/${slug.join('/')}/`;
|
|
137
|
+
}
|
package/dist/next/server.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare function getRoutes(config?: FetchConfig): Promise<string[]>;
|
|
|
34
34
|
export declare function getRenderInput<TPage, TSite extends SiteConfig = SiteConfig>(route?: string, config?: FetchConfig): Promise<ServerRenderInput<TPage, TSite>>;
|
|
35
35
|
export declare function getPageRuntimeRenderInput(): Promise<RenderInput | null>;
|
|
36
36
|
export { isPreviewMode } from './preview-mode.js';
|
|
37
|
-
export declare function routeFromNextParams(params
|
|
37
|
+
export declare function routeFromNextParams(params: Promise<{
|
|
38
38
|
slug?: string[];
|
|
39
39
|
}> | {
|
|
40
40
|
slug?: string[];
|
package/dist/next/server.js
CHANGED
|
@@ -100,21 +100,20 @@ async function pageFromFunctionRef(provider) {
|
|
|
100
100
|
}
|
|
101
101
|
export { isPreviewMode } from './preview-mode.js';
|
|
102
102
|
export async function routeFromNextParams(params) {
|
|
103
|
-
if (!params)
|
|
104
|
-
return '/';
|
|
105
103
|
const resolved = await params;
|
|
106
|
-
|
|
104
|
+
const slug = resolved.slug ?? [];
|
|
105
|
+
if (slug.length === 0)
|
|
107
106
|
return '/';
|
|
108
|
-
return `/${
|
|
107
|
+
return `/${slug.join('/')}/`;
|
|
109
108
|
}
|
|
110
109
|
export async function generateStaticParams() {
|
|
111
110
|
const { FileContentProvider } = await import('../providers/file.js');
|
|
112
111
|
const provider = new FileContentProvider();
|
|
113
112
|
const routes = await provider.listRoutes();
|
|
114
|
-
return routes
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
return routes.map((entry) => ({
|
|
114
|
+
slug: entry.path === '/'
|
|
115
|
+
? ['index']
|
|
116
|
+
: entry.path.replace(/^\/|\/$/g, '').split('/'),
|
|
118
117
|
}));
|
|
119
118
|
}
|
|
120
119
|
export class ReleaseAssetNotFoundError extends Error {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ConformanceCheckResult, ConformanceCheckName, ConformanceContext } from './types.js';
|
|
2
|
+
export declare function checkConfig(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
3
|
+
export declare function checkRegistry(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
4
|
+
export declare function checkPageEntry(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
5
|
+
export declare function checkMiddleware(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
6
|
+
export declare function checkNoFileContentProvider(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
7
|
+
export declare function checkNoCustomContent(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
8
|
+
export declare function checkNoLegacyAssetRoute(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
9
|
+
export declare function checkBuildSucceeds(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
10
|
+
export declare function checkContentCompile(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
11
|
+
export declare function checkSdkVersion(ctx: ConformanceContext): ConformanceCheckResult[];
|
|
12
|
+
export declare const CHECK_REGISTRY: Record<ConformanceCheckName, (ctx: ConformanceContext) => ConformanceCheckResult[]>;
|