@gradial/aci 0.1.22 → 0.1.24
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/bin/aci-darwin-arm64 +0 -0
- package/dist/content/assets.js +1 -1
- package/dist/dev/content-watch.js +1 -1
- package/dist/next/asset-route.d.ts +0 -1
- package/dist/next/asset-route.js +5 -6
- package/dist/next/config.js +25 -1
- package/dist/next/content-watch.js +1 -2
- package/dist/next/middleware.d.ts +2 -2
- package/dist/next/middleware.js +42 -25
- package/dist/next/page.d.ts +6 -0
- package/dist/next/page.js +34 -4
- package/dist/next/preview-mode.js +6 -7
- package/dist/next/server.js +4 -20
- package/dist/preview/core.d.ts +0 -2
- package/dist/preview/core.js +1 -3
- package/dist/react/Media.d.ts +1 -1
- package/dist/react/Media.js +1 -1
- package/dist/react/VideoPlayer.d.ts +307 -6
- package/dist/react/VideoPlayer.js +19 -5
- package/dist/react/index.d.ts +1 -1
- package/dist/types/image.d.ts +2 -2
- package/dist/types/media.d.ts +3 -0
- package/dist/types/video.d.ts +14 -8
- package/dist/types/video.js +3 -0
- package/package.json +2 -3
- package/src/cli/compile-registry.mjs +68 -43
- package/src/cli/verify-next-cdn-routes.mjs +101 -0
- package/src/types/component.ts +55 -0
- package/src/types/config.ts +37 -0
- package/src/types/data.ts +47 -0
- package/src/types/image.ts +4 -3
- package/src/types/index.ts +11 -0
- package/src/types/layout.ts +29 -0
- package/src/types/link.ts +100 -0
- package/src/types/media.ts +34 -0
- package/src/types/page.ts +47 -0
- package/src/types/render-mode.ts +10 -0
- package/src/types/renderer.ts +83 -0
- package/src/types/rich-text.ts +64 -0
- package/src/types/video.ts +76 -0
- package/templates/astro/template/package.json.tmpl +4 -5
- package/templates/nextjs/template/package.json.tmpl +4 -5
- package/templates/nextjs/template/src/app/gradial/assets/[...path]/route.ts +4 -0
- package/templates/nextjs/template/src/app/gradial/assets/[releaseId]/[...path]/route.ts +0 -31
package/bin/aci-darwin-arm64
CHANGED
|
Binary file
|
package/dist/content/assets.js
CHANGED
|
@@ -31,7 +31,7 @@ export async function getReleaseAssetResponse(input) {
|
|
|
31
31
|
copyHeader(res.headers, headers, 'content-length');
|
|
32
32
|
copyHeader(res.headers, headers, 'etag');
|
|
33
33
|
copyHeader(res.headers, headers, 'last-modified');
|
|
34
|
-
headers.set('cache-control', 'public, max-age=
|
|
34
|
+
headers.set('cache-control', 'public, max-age=300, must-revalidate');
|
|
35
35
|
return new Response(res.body, { status: 200, headers });
|
|
36
36
|
}
|
|
37
37
|
function cleanAssetPath(value) {
|
|
@@ -23,7 +23,7 @@ function recompileContent(options, reason) {
|
|
|
23
23
|
const out = path.resolve(options.compiledRoot || process.env.ACI_CONTENT_ROOT || '.aci/compiled');
|
|
24
24
|
const bin = resolveBin(options);
|
|
25
25
|
console.log(`[aci] compiling content (${reason})`);
|
|
26
|
-
const result = spawnSync(bin, ['-s', siteDir, '
|
|
26
|
+
const result = spawnSync(bin, ['-s', siteDir, 'content', 'compile', '--content', src, '--out', out], {
|
|
27
27
|
cwd: siteDir,
|
|
28
28
|
stdio: 'inherit',
|
|
29
29
|
env: process.env,
|
package/dist/next/asset-route.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { FileContentProvider } from '../providers/file.js';
|
|
2
|
-
import { getReleaseAssetResponse } from '
|
|
3
|
-
const LOCAL_RELEASE_ID = 'local';
|
|
2
|
+
import { getReleaseAssetResponse, resolveReleaseId } from './server.js';
|
|
4
3
|
export const runtime = 'nodejs';
|
|
5
4
|
export const dynamic = 'force-dynamic';
|
|
6
5
|
export async function GET(_request, { params }) {
|
|
7
6
|
const resolvedParams = await params;
|
|
8
|
-
const releaseId = resolvedParams.releaseId || '';
|
|
9
7
|
const assetPath = '/' + (resolvedParams.path || []).join('/');
|
|
10
|
-
if (
|
|
8
|
+
if (assetPath === '/') {
|
|
11
9
|
return new Response('asset not found', { status: 404 });
|
|
12
10
|
}
|
|
13
|
-
if (
|
|
11
|
+
if (process.env.ACI_CONTENT_PROVIDER === 'file') {
|
|
14
12
|
const provider = new FileContentProvider();
|
|
15
13
|
return provider.fetchRaw(assetPath);
|
|
16
14
|
}
|
|
17
15
|
try {
|
|
18
|
-
|
|
16
|
+
const releaseId = await resolveReleaseId();
|
|
17
|
+
return await getReleaseAssetResponse(releaseId, assetPath);
|
|
19
18
|
}
|
|
20
19
|
catch {
|
|
21
20
|
return new Response('asset not found', { status: 404 });
|
package/dist/next/config.js
CHANGED
|
@@ -2,14 +2,38 @@ import { createContentWatchWebpackPlugin } from './content-watch.js';
|
|
|
2
2
|
export function withAci(nextConfig = {}, options = {}) {
|
|
3
3
|
const assetPrefix = options.assetPrefix || '/.gradial-dam';
|
|
4
4
|
const userRewrites = nextConfig.rewrites;
|
|
5
|
+
const userHeaders = nextConfig.headers;
|
|
5
6
|
const userWebpack = nextConfig.webpack;
|
|
6
7
|
return {
|
|
7
8
|
...nextConfig,
|
|
9
|
+
headers: async () => {
|
|
10
|
+
const gradialHeaders = [
|
|
11
|
+
{
|
|
12
|
+
source: '/__r/:releaseId/routes/:path*',
|
|
13
|
+
headers: [
|
|
14
|
+
{ key: 'Cache-Control', value: 'public, max-age=0, must-revalidate' },
|
|
15
|
+
{ key: 'CDN-Cache-Control', value: 'max-age=31536000' },
|
|
16
|
+
{ key: 'Vercel-CDN-Cache-Control', value: 'max-age=31536000' },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
source: '/gradial/assets/:path*',
|
|
21
|
+
headers: [
|
|
22
|
+
{ key: 'Cache-Control', value: 'public, max-age=300, must-revalidate' },
|
|
23
|
+
{ key: 'CDN-Cache-Control', value: 'max-age=300' },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
if (!userHeaders)
|
|
28
|
+
return gradialHeaders;
|
|
29
|
+
const userResult = await (typeof userHeaders === 'function' ? userHeaders() : userHeaders);
|
|
30
|
+
return [...gradialHeaders, ...userResult];
|
|
31
|
+
},
|
|
8
32
|
rewrites: async () => {
|
|
9
33
|
const rewrites = [
|
|
10
34
|
{
|
|
11
35
|
source: `${assetPrefix}/:path*`,
|
|
12
|
-
destination: `/gradial/assets
|
|
36
|
+
destination: `/gradial/assets${assetPrefix}/:path*`,
|
|
13
37
|
},
|
|
14
38
|
];
|
|
15
39
|
if (!userRewrites)
|
|
@@ -21,10 +21,9 @@ function recompileContent(reason) {
|
|
|
21
21
|
console.log(`[aci] compiling content (${reason})`);
|
|
22
22
|
const result = spawnSync(bin, [
|
|
23
23
|
'-s', siteDir,
|
|
24
|
-
'
|
|
24
|
+
'content', 'compile',
|
|
25
25
|
'--content', src,
|
|
26
26
|
'--out', out,
|
|
27
|
-
'--skip-code',
|
|
28
27
|
], {
|
|
29
28
|
cwd: siteDir,
|
|
30
29
|
stdio: 'inherit',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type NextRequest } from 'next/server.js';
|
|
2
2
|
export interface GradialMiddlewareConfig {
|
|
3
3
|
siteId?: string;
|
|
4
4
|
edgeConfig?: string;
|
|
@@ -6,7 +6,7 @@ export interface GradialMiddlewareConfig {
|
|
|
6
6
|
deploymentId?: string;
|
|
7
7
|
deploymentProtectionBypass?: string;
|
|
8
8
|
}
|
|
9
|
-
export declare function createGradialMiddleware(config?: GradialMiddlewareConfig): (request: NextRequest) => Promise<
|
|
9
|
+
export declare function createGradialMiddleware(config?: GradialMiddlewareConfig): (request: NextRequest) => Promise<Response>;
|
|
10
10
|
export declare const config: {
|
|
11
11
|
matcher: string[];
|
|
12
12
|
};
|
package/dist/next/middleware.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server.js';
|
|
2
2
|
import { getUncachedEdgeConfigValue } from './edge-config.js';
|
|
3
|
-
import { PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE,
|
|
4
|
-
const
|
|
5
|
-
const DISPATCH_HEADER = 'x-gradial-dispatch';
|
|
3
|
+
import { PREVIEW_TOKEN_COOKIE, PREVIEW_RELEASE_COOKIE, extractPreviewToken, resolvePreviewContext, createPreviewCookies, previewSignKey, } from '../preview/core.js';
|
|
4
|
+
const RELEASE_SCOPED_PREFIX = '/__r';
|
|
6
5
|
export function createGradialMiddleware(config = {}) {
|
|
7
6
|
return async function middleware(request) {
|
|
8
7
|
const url = request.nextUrl;
|
|
@@ -14,20 +13,32 @@ export function createGradialMiddleware(config = {}) {
|
|
|
14
13
|
response.cookies.delete(PREVIEW_RELEASE_COOKIE);
|
|
15
14
|
return response;
|
|
16
15
|
}
|
|
17
|
-
|
|
16
|
+
// Block direct access to /__r/... — only middleware rewrites may use it.
|
|
17
|
+
if (isReleaseScopedPath(url.pathname, RELEASE_SCOPED_PREFIX)) {
|
|
18
|
+
return new Response('not found', {
|
|
19
|
+
status: 404,
|
|
20
|
+
headers: { 'Cache-Control': 'private, no-store' },
|
|
21
|
+
});
|
|
22
|
+
}
|
|
18
23
|
// Try preview token first; if valid, use that release.
|
|
19
24
|
// If no token or invalid, fall through to active release from edge config.
|
|
20
25
|
const preview = await resolvePreviewFromRequest(request, config);
|
|
21
26
|
const releaseId = preview?.releaseId || await activeReleaseFromEdgeConfig(config);
|
|
22
27
|
if (!releaseId) {
|
|
23
|
-
|
|
28
|
+
if (process.env.ACI_CONTENT_PROVIDER === 'file') {
|
|
29
|
+
return NextResponse.next();
|
|
30
|
+
}
|
|
31
|
+
return new Response('no active release', {
|
|
32
|
+
status: 503,
|
|
33
|
+
headers: { 'Cache-Control': 'private, no-store' },
|
|
34
|
+
});
|
|
24
35
|
}
|
|
25
36
|
// Cross-deployment preview: if the token was staged on a different Vercel
|
|
26
37
|
// deployment, rewrite the request to that deployment. This keeps the browser
|
|
27
38
|
// on the production domain while the correct code runtime serves the request.
|
|
28
39
|
const rewriteTarget = preview ? previewRewriteTarget(request, preview, config) : null;
|
|
29
40
|
if (rewriteTarget) {
|
|
30
|
-
const response = NextResponse.rewrite(rewriteTarget
|
|
41
|
+
const response = NextResponse.rewrite(rewriteTarget);
|
|
31
42
|
if (preview?.token && preview.isPreview) {
|
|
32
43
|
for (const cookie of createPreviewCookies(preview.token, releaseId)) {
|
|
33
44
|
response.cookies.set(cookie.name, cookie.value, cookie.options);
|
|
@@ -35,13 +46,10 @@ export function createGradialMiddleware(config = {}) {
|
|
|
35
46
|
}
|
|
36
47
|
return response;
|
|
37
48
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
requestHeaders.set(PREVIEW_HEADER, '1');
|
|
43
|
-
}
|
|
44
|
-
const response = NextResponse.next({ request: { headers: requestHeaders } });
|
|
49
|
+
// Rewrite public URL to release-scoped internal path for CDN cache isolation.
|
|
50
|
+
// Each release gets a unique URL (/__r/{releaseId}/routes/...) so the CDN
|
|
51
|
+
// cache key is per-release. New release = new URL = cache miss = fresh content.
|
|
52
|
+
const response = rewriteToReleaseScopedPath(request, releaseId, Boolean(preview?.isPreview));
|
|
45
53
|
// Persist preview token as cookie so navigation stays in preview
|
|
46
54
|
if (preview?.token && preview.isPreview) {
|
|
47
55
|
for (const cookie of createPreviewCookies(preview.token, releaseId)) {
|
|
@@ -51,6 +59,27 @@ export function createGradialMiddleware(config = {}) {
|
|
|
51
59
|
return response;
|
|
52
60
|
};
|
|
53
61
|
}
|
|
62
|
+
function rewriteToReleaseScopedPath(request, releaseId, isPreview) {
|
|
63
|
+
const rewriteURL = new URL(request.url);
|
|
64
|
+
rewriteURL.pathname = releaseScopedPath(RELEASE_SCOPED_PREFIX, releaseId, request.nextUrl.pathname);
|
|
65
|
+
const response = NextResponse.rewrite(rewriteURL);
|
|
66
|
+
if (isPreview) {
|
|
67
|
+
response.headers.set('Cache-Control', 'private, no-store');
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
response.headers.set('Cache-Control', 'public, max-age=0, must-revalidate');
|
|
71
|
+
response.headers.set('CDN-Cache-Control', 'max-age=31536000');
|
|
72
|
+
response.headers.set('Vercel-CDN-Cache-Control', 'max-age=31536000');
|
|
73
|
+
}
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
function isReleaseScopedPath(pathname, prefix) {
|
|
77
|
+
return pathname === prefix || pathname.startsWith(`${prefix}/`);
|
|
78
|
+
}
|
|
79
|
+
function releaseScopedPath(prefix, releaseId, pathname) {
|
|
80
|
+
const suffix = pathname === '/' ? '' : pathname;
|
|
81
|
+
return `${prefix}/${encodeURIComponent(releaseId)}/routes${suffix}`;
|
|
82
|
+
}
|
|
54
83
|
function previewRewriteTarget(request, preview, config) {
|
|
55
84
|
const claims = preview.claims;
|
|
56
85
|
if (!claims?.deploymentId || !claims?.deploymentUrl || !preview.token) {
|
|
@@ -77,14 +106,6 @@ function buildDeploymentUrl(value) {
|
|
|
77
106
|
}
|
|
78
107
|
return `https://${value}`;
|
|
79
108
|
}
|
|
80
|
-
function gradialHeaders(headers) {
|
|
81
|
-
const next = new Headers(headers);
|
|
82
|
-
next.delete(RELEASE_HEADER);
|
|
83
|
-
next.delete(ROUTE_HEADER);
|
|
84
|
-
next.delete(DISPATCH_HEADER);
|
|
85
|
-
next.delete(PREVIEW_HEADER);
|
|
86
|
-
return next;
|
|
87
|
-
}
|
|
88
109
|
async function resolvePreviewFromRequest(request, config) {
|
|
89
110
|
const token = extractPreviewToken({
|
|
90
111
|
query: request.nextUrl.searchParams,
|
|
@@ -177,10 +198,6 @@ function clampRelease(activeReleaseId, activeSequence, compatibility) {
|
|
|
177
198
|
function edgeKeySegment(value) {
|
|
178
199
|
return value.replace(/[^A-Za-z0-9_-]/g, '_');
|
|
179
200
|
}
|
|
180
|
-
// Default matcher. _next/static is included so that cross-deployment previews
|
|
181
|
-
// can rewrite static assets to the staged deployment. _next/image is excluded
|
|
182
|
-
// because it is a generic optimization endpoint and does not carry code-specific
|
|
183
|
-
// assets in most configurations. Consumers can override this if needed.
|
|
184
201
|
export const config = {
|
|
185
202
|
matcher: ['/((?!_next/image|favicon.ico|\\.gradial-dam|api/baremetal-assets|gradial/assets).*)'],
|
|
186
203
|
};
|
package/dist/next/page.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export interface CreatePageOptions {
|
|
|
28
28
|
* The SDK owns param normalization, content loading, metadata generation,
|
|
29
29
|
* notFound handling, layout resolution, and block rendering via the registry.
|
|
30
30
|
*
|
|
31
|
+
* Release-scoped routes: when the middleware rewrites a public URL to
|
|
32
|
+
* `/__r/{releaseId}/routes/{path}`, the catch-all slug becomes
|
|
33
|
+
* `['__r', releaseId, 'routes', ...pathSegments]`. createPage detects this
|
|
34
|
+
* prefix, extracts the releaseId, and passes it to the content loader. This
|
|
35
|
+
* gives each release a unique CDN cache key without a separate route folder.
|
|
36
|
+
*
|
|
31
37
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
32
38
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
|
33
39
|
* the layout's fragment defaults (loaded via getFragment). This lets chrome
|
package/dist/next/page.js
CHANGED
|
@@ -22,6 +22,12 @@ import { renderBlocks } from './render.js';
|
|
|
22
22
|
* The SDK owns param normalization, content loading, metadata generation,
|
|
23
23
|
* notFound handling, layout resolution, and block rendering via the registry.
|
|
24
24
|
*
|
|
25
|
+
* Release-scoped routes: when the middleware rewrites a public URL to
|
|
26
|
+
* `/__r/{releaseId}/routes/{path}`, the catch-all slug becomes
|
|
27
|
+
* `['__r', releaseId, 'routes', ...pathSegments]`. createPage detects this
|
|
28
|
+
* prefix, extracts the releaseId, and passes it to the content loader. This
|
|
29
|
+
* gives each release a unique CDN cache key without a separate route folder.
|
|
30
|
+
*
|
|
25
31
|
* Layout slots: createPage loads the page's layout, iterates all slots, and
|
|
26
32
|
* fills each from the page's regions. If a slot is empty, it falls back to
|
|
27
33
|
* the layout's fragment defaults (loaded via getFragment). This lets chrome
|
|
@@ -30,8 +36,8 @@ import { renderBlocks } from './render.js';
|
|
|
30
36
|
export function createPage(registry, options) {
|
|
31
37
|
const dynamic = 'force-dynamic';
|
|
32
38
|
async function generateMetadata({ params }) {
|
|
33
|
-
const route = await
|
|
34
|
-
const input = await getRenderInput(route);
|
|
39
|
+
const { route, releaseId } = await resolveRouteAndRelease(params);
|
|
40
|
+
const input = await getRenderInput(route, { releaseId });
|
|
35
41
|
const meta = routeMetadataForContent(input.siteConfig, input.page);
|
|
36
42
|
return {
|
|
37
43
|
title: meta.title,
|
|
@@ -45,9 +51,9 @@ export function createPage(registry, options) {
|
|
|
45
51
|
};
|
|
46
52
|
}
|
|
47
53
|
async function CatchAllPage({ params }) {
|
|
48
|
-
const route = await
|
|
54
|
+
const { route, releaseId } = await resolveRouteAndRelease(params);
|
|
49
55
|
try {
|
|
50
|
-
const input = await getRenderInput(route);
|
|
56
|
+
const input = await getRenderInput(route, { releaseId });
|
|
51
57
|
if (!input.page)
|
|
52
58
|
notFound();
|
|
53
59
|
const layout = await getLayout(input.page.layout);
|
|
@@ -77,3 +83,27 @@ export function createPage(registry, options) {
|
|
|
77
83
|
default: CatchAllPage,
|
|
78
84
|
};
|
|
79
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolves the logical route and optional releaseId from Next.js catch-all
|
|
88
|
+
* params. When the middleware rewrites to /__r/{releaseId}/routes/{path},
|
|
89
|
+
* the slug is ['__r', releaseId, 'routes', ...pathSegments]. Otherwise the
|
|
90
|
+
* slug is treated as the public route directly.
|
|
91
|
+
*/
|
|
92
|
+
async function resolveRouteAndRelease(params) {
|
|
93
|
+
const resolved = await params;
|
|
94
|
+
const slug = resolved?.slug;
|
|
95
|
+
if (slug && slug.length >= 3 && slug[0] === '__r' && slug[2] === 'routes') {
|
|
96
|
+
const releaseId = decodeURIComponent(slug[1]);
|
|
97
|
+
if (!releaseId || releaseId.includes('/') || releaseId === '.' || releaseId === '..') {
|
|
98
|
+
return { route: '/' };
|
|
99
|
+
}
|
|
100
|
+
const pathSegments = slug.slice(3);
|
|
101
|
+
if (pathSegments.length === 0)
|
|
102
|
+
return { route: '/', releaseId };
|
|
103
|
+
if (pathSegments.some((s) => s === '' || s === '.' || s === '..'))
|
|
104
|
+
return { route: '/' };
|
|
105
|
+
return { route: `/${pathSegments.join('/')}/`, releaseId };
|
|
106
|
+
}
|
|
107
|
+
const route = await routeFromNextParams(params);
|
|
108
|
+
return { route };
|
|
109
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { cookies } from 'next/headers.js';
|
|
2
|
+
import { PREVIEW_RELEASE_COOKIE, PREVIEW_TOKEN_COOKIE } from '../preview/core.js';
|
|
3
3
|
export async function isPreviewMode() {
|
|
4
|
-
const current = await
|
|
5
|
-
if (current.get(
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
return '';
|
|
4
|
+
const current = await cookies();
|
|
5
|
+
if (!current.get(PREVIEW_TOKEN_COOKIE)?.value)
|
|
6
|
+
return '';
|
|
7
|
+
return current.get(PREVIEW_RELEASE_COOKIE)?.value || '';
|
|
9
8
|
}
|
package/dist/next/server.js
CHANGED
|
@@ -4,8 +4,6 @@ import { getCachedManifest, getCachedSiteConfig } from '../content/cache.js';
|
|
|
4
4
|
import { S3ContentProvider } from '../providers/s3.js';
|
|
5
5
|
import { GRADIAL_RENDER_INPUT_HEADER, getPendingRenderInput } from '../runtime/page.js';
|
|
6
6
|
import { getUncachedEdgeConfigValue } from './edge-config.js';
|
|
7
|
-
const RELEASE_HEADER = 'x-gradial-release-id';
|
|
8
|
-
const PREVIEW_HEADER = 'x-gradial-preview';
|
|
9
7
|
export { FragmentNotFoundError, PageNotFoundError, LayoutNotFoundError };
|
|
10
8
|
export async function getPage(route = '', config = {}) {
|
|
11
9
|
const runtimeInput = await getPageRuntimeRenderInput();
|
|
@@ -125,7 +123,7 @@ export async function getReleaseAssetResponse(releaseId, assetPath, config = {})
|
|
|
125
123
|
copyHeader(res.headers, headers, 'content-length');
|
|
126
124
|
copyHeader(res.headers, headers, 'etag');
|
|
127
125
|
copyHeader(res.headers, headers, 'last-modified');
|
|
128
|
-
headers.set('cache-control', 'public, max-age=
|
|
126
|
+
headers.set('cache-control', 'public, max-age=300, must-revalidate');
|
|
129
127
|
return new Response(res.body, { status: 200, headers });
|
|
130
128
|
}
|
|
131
129
|
function cleanAssetPath(value) {
|
|
@@ -150,17 +148,14 @@ async function safeResponseText(res) {
|
|
|
150
148
|
export async function resolveReleaseId(config = {}) {
|
|
151
149
|
if (config.releaseId)
|
|
152
150
|
return config.releaseId;
|
|
153
|
-
const headerReleaseId = await releaseIdFromHeaders();
|
|
154
|
-
if (headerReleaseId)
|
|
155
|
-
return headerReleaseId;
|
|
156
151
|
if (process.env.ACI_RELEASE_ID)
|
|
157
152
|
return process.env.ACI_RELEASE_ID;
|
|
158
153
|
const activeReleaseId = await activeReleaseFromEdgeConfig(config);
|
|
159
154
|
if (activeReleaseId)
|
|
160
155
|
return activeReleaseId;
|
|
161
|
-
throw new Error('ACI release ID is
|
|
156
|
+
throw new Error('ACI release ID is required. Pass releaseId from the release-scoped route or set ACI_RELEASE_ID.');
|
|
162
157
|
}
|
|
163
|
-
async function
|
|
158
|
+
async function resolveS3Provider(config) {
|
|
164
159
|
const releaseId = await resolveReleaseId(config);
|
|
165
160
|
const provider = new S3ContentProvider({
|
|
166
161
|
bucket: config.bucket,
|
|
@@ -180,16 +175,7 @@ async function resolveProviderWithFallback(config) {
|
|
|
180
175
|
const { FileContentProvider } = await import('../providers/file.js');
|
|
181
176
|
return new FileContentProvider();
|
|
182
177
|
}
|
|
183
|
-
return await
|
|
184
|
-
}
|
|
185
|
-
async function releaseIdFromHeaders() {
|
|
186
|
-
try {
|
|
187
|
-
const current = await headers();
|
|
188
|
-
return current.get(RELEASE_HEADER) || '';
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
return '';
|
|
192
|
-
}
|
|
178
|
+
return await resolveS3Provider(config);
|
|
193
179
|
}
|
|
194
180
|
async function activeReleaseFromEdgeConfig(config) {
|
|
195
181
|
const edgeConfig = config.edgeConfig || process.env.EDGE_CONFIG || '';
|
|
@@ -272,5 +258,3 @@ function joinKey(...parts) {
|
|
|
272
258
|
.filter(Boolean)
|
|
273
259
|
.join('/');
|
|
274
260
|
}
|
|
275
|
-
// Note: React cache() would be redundant here since getCachedSiteConfig already
|
|
276
|
-
// returns the same Promise for the same provider instance within a request
|
package/dist/preview/core.d.ts
CHANGED
|
@@ -34,8 +34,6 @@ export interface PreviewCookie {
|
|
|
34
34
|
path: string;
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
export declare const PREVIEW_HEADER = "x-gradial-preview";
|
|
38
|
-
export declare const RELEASE_HEADER = "x-gradial-release-id";
|
|
39
37
|
export declare const PREVIEW_TOKEN_COOKIE = "aci_preview";
|
|
40
38
|
export declare const PREVIEW_RELEASE_COOKIE = "aci_preview_release";
|
|
41
39
|
export declare function validatePreviewToken(token: string, signKey: string): Promise<PreviewClaims | null>;
|
package/dist/preview/core.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export const PREVIEW_HEADER = 'x-gradial-preview';
|
|
2
|
-
export const RELEASE_HEADER = 'x-gradial-release-id';
|
|
3
1
|
export const PREVIEW_TOKEN_COOKIE = 'aci_preview';
|
|
4
2
|
export const PREVIEW_RELEASE_COOKIE = 'aci_preview_release';
|
|
5
3
|
export async function validatePreviewToken(token, signKey) {
|
|
@@ -43,7 +41,7 @@ export function extractPreviewToken(source) {
|
|
|
43
41
|
return undefined;
|
|
44
42
|
}
|
|
45
43
|
export function previewSignKey() {
|
|
46
|
-
return process.env.GRADIAL_PREVIEW_SIGN_KEY || undefined;
|
|
44
|
+
return process.env.GRADIAL_PREVIEW_SIGN_KEY || process.env.ACI_PREVIEW_SIGN_KEY || undefined;
|
|
47
45
|
}
|
|
48
46
|
export async function resolvePreviewContext(options) {
|
|
49
47
|
const token = options.token;
|
package/dist/react/Media.d.ts
CHANGED
|
@@ -19,6 +19,6 @@ export interface MediaProps {
|
|
|
19
19
|
* HTML element based on $type.
|
|
20
20
|
*
|
|
21
21
|
* - gradial.image → <img> with srcset via Picture
|
|
22
|
-
* - gradial.video → <video> via VideoPlayer
|
|
22
|
+
* - gradial.video → <video> or <iframe> via VideoPlayer
|
|
23
23
|
*/
|
|
24
24
|
export declare function Media({ media, className, style, loading, imgProps, videoProps, }: MediaProps): import("react").FunctionComponentElement<import("./VideoPlayer.js").VideoPlayerProps> | import("react").FunctionComponentElement<import("./Picture.js").PictureProps>;
|
package/dist/react/Media.js
CHANGED
|
@@ -6,7 +6,7 @@ import { VideoPlayer } from './VideoPlayer.js';
|
|
|
6
6
|
* HTML element based on $type.
|
|
7
7
|
*
|
|
8
8
|
* - gradial.image → <img> with srcset via Picture
|
|
9
|
-
* - gradial.video → <video> via VideoPlayer
|
|
9
|
+
* - gradial.video → <video> or <iframe> via VideoPlayer
|
|
10
10
|
*/
|
|
11
11
|
export function Media({ media, className, style, loading = 'lazy', imgProps, videoProps, }) {
|
|
12
12
|
switch (media.$type) {
|