astro 5.9.2 → 5.9.3
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/dist/container/pipeline.js +2 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/core/app/pipeline.js +2 -1
- package/dist/core/app/types.d.ts +1 -0
- package/dist/core/base-pipeline.d.ts +1 -2
- package/dist/core/build/generate.js +31 -13
- package/dist/core/build/pipeline.js +2 -1
- package/dist/core/build/plugins/plugin-manifest.js +1 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/csp/config.d.ts +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/render-context.js +1 -0
- package/dist/core/routing/manifest/create.js +1 -1
- package/dist/core/routing/rewrite.d.ts +2 -1
- package/dist/core/routing/rewrite.js +14 -2
- package/dist/integrations/hooks.d.ts +4 -2
- package/dist/integrations/hooks.js +5 -3
- package/dist/runtime/server/render/head.js +15 -14
- package/dist/runtime/server/render/page.js +12 -4
- package/dist/runtime/server/render/server-islands.js +1 -1
- package/dist/types/public/integrations.d.ts +12 -1
- package/dist/types/public/internal.d.ts +12 -2
- package/dist/vite-plugin-astro-server/pipeline.js +2 -1
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/package.json +1 -1
|
@@ -56,7 +56,8 @@ class ContainerPipeline extends Pipeline {
|
|
|
56
56
|
routes: this.manifest?.routes.map((r) => r.routeData),
|
|
57
57
|
trailingSlash: this.manifest.trailingSlash,
|
|
58
58
|
buildFormat: this.manifest.buildFormat,
|
|
59
|
-
base: this.manifest.base
|
|
59
|
+
base: this.manifest.base,
|
|
60
|
+
outDir: this.manifest.outDir
|
|
60
61
|
});
|
|
61
62
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
62
63
|
return { componentInstance, routeData, newUrl, pathname };
|
|
@@ -164,7 +164,7 @@ ${contentConfig.error.message}`);
|
|
|
164
164
|
logger.info("Content config changed");
|
|
165
165
|
shouldClear = true;
|
|
166
166
|
}
|
|
167
|
-
if (previousAstroVersion && previousAstroVersion !== "5.9.
|
|
167
|
+
if (previousAstroVersion && previousAstroVersion !== "5.9.3") {
|
|
168
168
|
logger.info("Astro version changed");
|
|
169
169
|
shouldClear = true;
|
|
170
170
|
}
|
|
@@ -172,8 +172,8 @@ ${contentConfig.error.message}`);
|
|
|
172
172
|
logger.info("Clearing content store");
|
|
173
173
|
this.#store.clearAll();
|
|
174
174
|
}
|
|
175
|
-
if ("5.9.
|
|
176
|
-
await this.#store.metaStore().set("astro-version", "5.9.
|
|
175
|
+
if ("5.9.3") {
|
|
176
|
+
await this.#store.metaStore().set("astro-version", "5.9.3");
|
|
177
177
|
}
|
|
178
178
|
if (currentConfigDigest) {
|
|
179
179
|
await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
@@ -65,7 +65,8 @@ class AppPipeline extends Pipeline {
|
|
|
65
65
|
routes: this.manifest?.routes.map((r) => r.routeData),
|
|
66
66
|
trailingSlash: this.manifest.trailingSlash,
|
|
67
67
|
buildFormat: this.manifest.buildFormat,
|
|
68
|
-
base: this.manifest.base
|
|
68
|
+
base: this.manifest.base,
|
|
69
|
+
outDir: this.manifest.outDir
|
|
69
70
|
});
|
|
70
71
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
71
72
|
return { newUrl, pathname, componentInstance, routeData };
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -91,6 +91,7 @@ export type SSRManifestI18n = {
|
|
|
91
91
|
domainLookupTable: Record<string, string>;
|
|
92
92
|
};
|
|
93
93
|
export type SSRManifestCSP = {
|
|
94
|
+
cspDestination: 'adapter' | 'meta' | 'header' | undefined;
|
|
94
95
|
algorithm: CspAlgorithm;
|
|
95
96
|
scriptHashes: string[];
|
|
96
97
|
scriptResources: string[];
|
|
@@ -3,8 +3,7 @@ import type { ActionAccept, ActionClient } from '../actions/runtime/virtual/serv
|
|
|
3
3
|
import type { ComponentInstance } from '../types/astro.js';
|
|
4
4
|
import type { MiddlewareHandler, RewritePayload } from '../types/public/common.js';
|
|
5
5
|
import type { RuntimeMode } from '../types/public/config.js';
|
|
6
|
-
import type { RouteData, SSRLoadedRenderer, SSRManifest, SSRResult } from '../types/public/internal.js';
|
|
7
|
-
import type { SSRActions } from './app/types.js';
|
|
6
|
+
import type { RouteData, SSRActions, SSRLoadedRenderer, SSRManifest, SSRResult } from '../types/public/internal.js';
|
|
8
7
|
import type { Logger } from './logger/core.js';
|
|
9
8
|
import { RouteCache } from './render/route-cache.js';
|
|
10
9
|
/**
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
removeTrailingForwardSlash
|
|
17
17
|
} from "../../core/path.js";
|
|
18
18
|
import { toFallbackType, toRoutingStrategy } from "../../i18n/utils.js";
|
|
19
|
-
import { runHookBuildGenerated } from "../../integrations/hooks.js";
|
|
19
|
+
import { runHookBuildGenerated, toIntegrationResolvedRoute } from "../../integrations/hooks.js";
|
|
20
20
|
import { getServerOutputDirectory } from "../../prerender/utils.js";
|
|
21
21
|
import {
|
|
22
22
|
getAlgorithm,
|
|
@@ -77,6 +77,7 @@ async function generatePages(options, internals) {
|
|
|
77
77
|
${bgGreen(black(` ${verb} static routes `))}`);
|
|
78
78
|
const builtPaths = /* @__PURE__ */ new Set();
|
|
79
79
|
const pagesToGenerate = pipeline.retrieveRoutesToGenerate();
|
|
80
|
+
const routeToHeaders = /* @__PURE__ */ new Map();
|
|
80
81
|
if (ssr) {
|
|
81
82
|
for (const [pageData, filePath] of pagesToGenerate) {
|
|
82
83
|
if (pageData.route.prerender) {
|
|
@@ -88,13 +89,13 @@ ${bgGreen(black(` ${verb} static routes `))}`);
|
|
|
88
89
|
}
|
|
89
90
|
const ssrEntryPage = await pipeline.retrieveSsrEntry(pageData.route, filePath);
|
|
90
91
|
const ssrEntry = ssrEntryPage;
|
|
91
|
-
await generatePage(pageData, ssrEntry, builtPaths, pipeline);
|
|
92
|
+
await generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHeaders);
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
95
|
} else {
|
|
95
96
|
for (const [pageData, filePath] of pagesToGenerate) {
|
|
96
97
|
const entry = await pipeline.retrieveSsrEntry(pageData.route, filePath);
|
|
97
|
-
await generatePage(pageData, entry, builtPaths, pipeline);
|
|
98
|
+
await generatePage(pageData, entry, builtPaths, pipeline, routeToHeaders);
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
logger.info(
|
|
@@ -121,10 +122,14 @@ ${bgGreen(black(` ${verb} static routes `))}`);
|
|
|
121
122
|
`));
|
|
122
123
|
delete globalThis?.astroAsset?.addStaticImage;
|
|
123
124
|
}
|
|
124
|
-
await runHookBuildGenerated({
|
|
125
|
+
await runHookBuildGenerated({
|
|
126
|
+
settings: options.settings,
|
|
127
|
+
logger,
|
|
128
|
+
experimentalRouteToHeaders: routeToHeaders
|
|
129
|
+
});
|
|
125
130
|
}
|
|
126
131
|
const THRESHOLD_SLOW_RENDER_TIME_MS = 500;
|
|
127
|
-
async function generatePage(pageData, ssrEntry, builtPaths, pipeline) {
|
|
132
|
+
async function generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHeaders) {
|
|
128
133
|
const { config, logger } = pipeline;
|
|
129
134
|
const pageModulePromise = ssrEntry.page;
|
|
130
135
|
const styles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
|
|
@@ -150,7 +155,7 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline) {
|
|
|
150
155
|
if (!isConcurrent) {
|
|
151
156
|
logger.info(null, ` ${blue(lineIcon)} ${dim(filePath)}`, false);
|
|
152
157
|
}
|
|
153
|
-
const created = await generatePath(path, pipeline, generationOptions, route);
|
|
158
|
+
const created = await generatePath(path, pipeline, generationOptions, route, routeToHeaders);
|
|
154
159
|
const timeEnd = performance.now();
|
|
155
160
|
const isSlow = timeEnd - timeStart > THRESHOLD_SLOW_RENDER_TIME_MS;
|
|
156
161
|
const timeIncrease = (isSlow ? red : dim)(`(+${getTimeStat(timeStart, timeEnd)})`);
|
|
@@ -287,18 +292,27 @@ function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType)
|
|
|
287
292
|
}
|
|
288
293
|
return new URL(buildPathname, origin);
|
|
289
294
|
}
|
|
290
|
-
async function generatePath(pathname, pipeline, gopts, route) {
|
|
295
|
+
async function generatePath(pathname, pipeline, gopts, route, routeToHeaders) {
|
|
291
296
|
const { mod } = gopts;
|
|
292
297
|
const { config, logger, options } = pipeline;
|
|
293
298
|
logger.debug("build", `Generating: ${pathname}`);
|
|
294
299
|
if (route.type === "page") {
|
|
295
300
|
addPageName(pathname, options);
|
|
296
301
|
}
|
|
297
|
-
if (route.type === "fallback" &&
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
+
if (route.type === "fallback" && route.pathname !== "/") {
|
|
303
|
+
let locale = removeLeadingForwardSlash(pathname).split("/")[0];
|
|
304
|
+
if (Object.values(options.allPages).some((val) => {
|
|
305
|
+
if (val.route.pattern.test(pathname)) {
|
|
306
|
+
if (val.route.segments && val.route.segments.length !== 0) {
|
|
307
|
+
if (val.route.segments[0][0].content !== locale) return false;
|
|
308
|
+
}
|
|
309
|
+
return true;
|
|
310
|
+
} else {
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
})) {
|
|
314
|
+
return void 0;
|
|
315
|
+
}
|
|
302
316
|
}
|
|
303
317
|
const url = getUrlForPath(
|
|
304
318
|
pathname,
|
|
@@ -332,6 +346,9 @@ async function generatePath(pathname, pipeline, gopts, route) {
|
|
|
332
346
|
}
|
|
333
347
|
throw err;
|
|
334
348
|
}
|
|
349
|
+
if (pipeline.settings.adapter?.adapterFeatures?.experimentalStaticHeaders && pipeline.settings.config.experimental?.csp) {
|
|
350
|
+
routeToHeaders.set(toIntegrationResolvedRoute(route), response.headers);
|
|
351
|
+
}
|
|
335
352
|
if (response.status >= 300 && response.status < 400) {
|
|
336
353
|
if (routeIsRedirect(route) && !config.build.redirects) {
|
|
337
354
|
return void 0;
|
|
@@ -401,6 +418,7 @@ async function createBuildManifest(settings, internals, renderers, middleware, a
|
|
|
401
418
|
...await trackStyleHashes(internals, settings, algorithm)
|
|
402
419
|
];
|
|
403
420
|
csp = {
|
|
421
|
+
cspDestination: settings.adapter?.adapterFeatures?.experimentalStaticHeaders ? "adapter" : void 0,
|
|
404
422
|
styleHashes,
|
|
405
423
|
styleResources: getStyleResources(settings.config.experimental.csp),
|
|
406
424
|
scriptHashes,
|
|
@@ -423,7 +441,7 @@ async function createBuildManifest(settings, internals, renderers, middleware, a
|
|
|
423
441
|
entryModules: Object.fromEntries(internals.entrySpecifierToBundleMap.entries()),
|
|
424
442
|
inlinedScripts: internals.inlinedScripts,
|
|
425
443
|
routes: [],
|
|
426
|
-
adapterName: "",
|
|
444
|
+
adapterName: settings.adapter?.name ?? "",
|
|
427
445
|
clientDirectives: settings.clientDirectives,
|
|
428
446
|
compressHTML: settings.config.compressHTML,
|
|
429
447
|
renderers,
|
|
@@ -201,7 +201,8 @@ class BuildPipeline extends Pipeline {
|
|
|
201
201
|
routes: this.options.routesList.routes,
|
|
202
202
|
trailingSlash: this.config.trailingSlash,
|
|
203
203
|
buildFormat: this.config.build.format,
|
|
204
|
-
base: this.config.base
|
|
204
|
+
base: this.config.base,
|
|
205
|
+
outDir: this.manifest.outDir
|
|
205
206
|
});
|
|
206
207
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
207
208
|
return { routeData, componentInstance, newUrl, pathname };
|
|
@@ -245,6 +245,7 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
245
245
|
...await trackStyleHashes(internals, settings, algorithm)
|
|
246
246
|
];
|
|
247
247
|
csp = {
|
|
248
|
+
cspDestination: settings.adapter?.adapterFeatures?.experimentalStaticHeaders ? "adapter" : void 0,
|
|
248
249
|
scriptHashes,
|
|
249
250
|
scriptResources: getScriptResources(settings.config.experimental.csp),
|
|
250
251
|
styleHashes,
|
package/dist/core/constants.js
CHANGED
|
@@ -10,7 +10,7 @@ export declare const cspAlgorithmSchema: z.ZodDefault<z.ZodOptional<z.ZodEnum<["
|
|
|
10
10
|
export declare const cspHashSchema: z.ZodType<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, z.ZodTypeDef, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
11
11
|
export type CspHash = z.infer<typeof cspHashSchema>;
|
|
12
12
|
declare const ALLOWED_DIRECTIVES: readonly ["base-uri", "child-src", "connect-src", "default-src", "fenced-frame-src", "font-src", "form-action", "frame-ancestors", "frame-src", "img-src", "manifest-src", "media-src", "object-src", "referrer", "report-to", "require-trusted-types-for", "sandbox", "trusted-types", "upgrade-insecure-requests", "worker-src"];
|
|
13
|
+
type AllowedDirectives = (typeof ALLOWED_DIRECTIVES)[number];
|
|
13
14
|
export type CspDirective = `${AllowedDirectives} ${string}`;
|
|
14
15
|
export declare const allowedDirectivesSchema: z.ZodType<`base-uri ${string}` | `child-src ${string}` | `connect-src ${string}` | `default-src ${string}` | `fenced-frame-src ${string}` | `font-src ${string}` | `form-action ${string}` | `frame-ancestors ${string}` | `frame-src ${string}` | `img-src ${string}` | `manifest-src ${string}` | `media-src ${string}` | `object-src ${string}` | `referrer ${string}` | `report-to ${string}` | `require-trusted-types-for ${string}` | `sandbox ${string}` | `trusted-types ${string}` | `upgrade-insecure-requests ${string}` | `worker-src ${string}`, z.ZodTypeDef, `base-uri ${string}` | `child-src ${string}` | `connect-src ${string}` | `default-src ${string}` | `fenced-frame-src ${string}` | `font-src ${string}` | `form-action ${string}` | `frame-ancestors ${string}` | `frame-src ${string}` | `img-src ${string}` | `manifest-src ${string}` | `media-src ${string}` | `object-src ${string}` | `referrer ${string}` | `report-to ${string}` | `require-trusted-types-for ${string}` | `sandbox ${string}` | `trusted-types ${string}` | `upgrade-insecure-requests ${string}` | `worker-src ${string}`>;
|
|
15
|
-
type AllowedDirectives = (typeof ALLOWED_DIRECTIVES)[number];
|
|
16
16
|
export {};
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
|
|
|
22
22
|
await telemetry.record([]);
|
|
23
23
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
24
24
|
const logger = restart.container.logger;
|
|
25
|
-
const currentVersion = "5.9.
|
|
25
|
+
const currentVersion = "5.9.3";
|
|
26
26
|
const isPrerelease = currentVersion.includes("-");
|
|
27
27
|
if (!isPrerelease) {
|
|
28
28
|
try {
|
package/dist/core/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ function serverStart({
|
|
|
37
37
|
host,
|
|
38
38
|
base
|
|
39
39
|
}) {
|
|
40
|
-
const version = "5.9.
|
|
40
|
+
const version = "5.9.3";
|
|
41
41
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
42
42
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
43
43
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -274,7 +274,7 @@ function printHelp({
|
|
|
274
274
|
message.push(
|
|
275
275
|
linebreak(),
|
|
276
276
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
277
|
-
`v${"5.9.
|
|
277
|
+
`v${"5.9.3"}`
|
|
278
278
|
)} ${headline}`
|
|
279
279
|
);
|
|
280
280
|
}
|
|
@@ -415,6 +415,7 @@ class RenderContext {
|
|
|
415
415
|
extraScriptHashes: [],
|
|
416
416
|
propagators: /* @__PURE__ */ new Set()
|
|
417
417
|
},
|
|
418
|
+
cspDestination: manifest.csp?.cspDestination ?? (routeData.prerender ? "meta" : "header"),
|
|
418
419
|
shouldInjectCspMetaTags: !!manifest.csp,
|
|
419
420
|
cspAlgorithm: manifest.csp?.algorithm ?? "SHA-256",
|
|
420
421
|
// The following arrays must be cloned, otherwise they become mutable across routes.
|
|
@@ -253,7 +253,7 @@ function createRedirectRoutes({ settings }, routeMap) {
|
|
|
253
253
|
component: from,
|
|
254
254
|
generate,
|
|
255
255
|
pathname: pathname || void 0,
|
|
256
|
-
prerender:
|
|
256
|
+
prerender: getPrerenderDefault(config),
|
|
257
257
|
redirect: to,
|
|
258
258
|
redirectRoute: routeMap.get(destination),
|
|
259
259
|
fallbackRoutes: [],
|
|
@@ -9,6 +9,7 @@ type FindRouteToRewrite = {
|
|
|
9
9
|
trailingSlash: AstroConfig['trailingSlash'];
|
|
10
10
|
buildFormat: AstroConfig['build']['format'];
|
|
11
11
|
base: AstroConfig['base'];
|
|
12
|
+
outDir: AstroConfig['outDir'] | string;
|
|
12
13
|
};
|
|
13
14
|
interface FindRouteToRewriteResult {
|
|
14
15
|
routeData: RouteData;
|
|
@@ -20,7 +21,7 @@ interface FindRouteToRewriteResult {
|
|
|
20
21
|
* 1. The new `Request` object. It contains `base`
|
|
21
22
|
* 2.
|
|
22
23
|
*/
|
|
23
|
-
export declare function findRouteToRewrite({ payload, routes, request, trailingSlash, buildFormat, base, }: FindRouteToRewrite): FindRouteToRewriteResult;
|
|
24
|
+
export declare function findRouteToRewrite({ payload, routes, request, trailingSlash, buildFormat, base, outDir, }: FindRouteToRewrite): FindRouteToRewriteResult;
|
|
24
25
|
/**
|
|
25
26
|
* Utility function that creates a new `Request` with a new URL from an old `Request`.
|
|
26
27
|
*
|
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
appendForwardSlash,
|
|
6
6
|
joinPaths,
|
|
7
7
|
prependForwardSlash,
|
|
8
|
-
removeTrailingForwardSlash
|
|
8
|
+
removeTrailingForwardSlash,
|
|
9
|
+
trimSlashes
|
|
9
10
|
} from "../path.js";
|
|
10
11
|
import { createRequest } from "../request.js";
|
|
11
12
|
import { DEFAULT_404_ROUTE } from "./astro-designed-error-pages.js";
|
|
@@ -15,7 +16,8 @@ function findRouteToRewrite({
|
|
|
15
16
|
request,
|
|
16
17
|
trailingSlash,
|
|
17
18
|
buildFormat,
|
|
18
|
-
base
|
|
19
|
+
base,
|
|
20
|
+
outDir
|
|
19
21
|
}) {
|
|
20
22
|
let newUrl = void 0;
|
|
21
23
|
if (payload instanceof URL) {
|
|
@@ -42,6 +44,9 @@ function findRouteToRewrite({
|
|
|
42
44
|
if (pathname === "/" && base !== "/" && !shouldAppendSlash) {
|
|
43
45
|
pathname = "";
|
|
44
46
|
}
|
|
47
|
+
if (buildFormat === "file") {
|
|
48
|
+
pathname = pathname.replace(/\.html$/, "");
|
|
49
|
+
}
|
|
45
50
|
if (base !== "/" && (pathname === "" || pathname === "/") && !shouldAppendSlash) {
|
|
46
51
|
newUrl.pathname = removeTrailingForwardSlash(base);
|
|
47
52
|
} else {
|
|
@@ -51,6 +56,13 @@ function findRouteToRewrite({
|
|
|
51
56
|
let foundRoute;
|
|
52
57
|
for (const route of routes) {
|
|
53
58
|
if (route.pattern.test(decodedPathname)) {
|
|
59
|
+
if (route.params && route.params.length !== 0 && route.distURL && route.distURL.length !== 0) {
|
|
60
|
+
if (!route.distURL.find(
|
|
61
|
+
(url) => url.href.replace(outDir.toString(), "").replace(/(?:\/index\.html|\.html)$/, "") == trimSlashes(decodedPathname)
|
|
62
|
+
)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
54
66
|
foundRoute = route;
|
|
55
67
|
break;
|
|
56
68
|
}
|
|
@@ -6,7 +6,7 @@ import type { PageBuildData } from '../core/build/types.js';
|
|
|
6
6
|
import type { Logger } from '../core/logger/core.js';
|
|
7
7
|
import type { AstroSettings } from '../types/astro.js';
|
|
8
8
|
import type { AstroConfig } from '../types/public/config.js';
|
|
9
|
-
import type { RouteOptions } from '../types/public/integrations.js';
|
|
9
|
+
import type { IntegrationResolvedRoute, RouteOptions } from '../types/public/integrations.js';
|
|
10
10
|
import type { RouteData } from '../types/public/internal.js';
|
|
11
11
|
export declare function getToolbarServerCommunicationHelpers(server: ViteDevServer): {
|
|
12
12
|
/**
|
|
@@ -84,9 +84,10 @@ type RunHookBuildSsr = {
|
|
|
84
84
|
middlewareEntryPoint: URL | undefined;
|
|
85
85
|
};
|
|
86
86
|
export declare function runHookBuildSsr({ config, manifest, logger, entryPoints, middlewareEntryPoint, }: RunHookBuildSsr): Promise<void>;
|
|
87
|
-
export declare function runHookBuildGenerated({ settings, logger, }: {
|
|
87
|
+
export declare function runHookBuildGenerated({ settings, logger, experimentalRouteToHeaders, }: {
|
|
88
88
|
settings: AstroSettings;
|
|
89
89
|
logger: Logger;
|
|
90
|
+
experimentalRouteToHeaders: Map<IntegrationResolvedRoute, Headers>;
|
|
90
91
|
}): Promise<void>;
|
|
91
92
|
type RunHookBuildDone = {
|
|
92
93
|
settings: AstroSettings;
|
|
@@ -105,4 +106,5 @@ export declare function runHookRoutesResolved({ routes, settings, logger, }: {
|
|
|
105
106
|
settings: AstroSettings;
|
|
106
107
|
logger: Logger;
|
|
107
108
|
}): Promise<void>;
|
|
109
|
+
export declare function toIntegrationResolvedRoute(route: RouteData): IntegrationResolvedRoute;
|
|
108
110
|
export {};
|
|
@@ -432,7 +432,8 @@ async function runHookBuildSsr({
|
|
|
432
432
|
}
|
|
433
433
|
async function runHookBuildGenerated({
|
|
434
434
|
settings,
|
|
435
|
-
logger
|
|
435
|
+
logger,
|
|
436
|
+
experimentalRouteToHeaders
|
|
436
437
|
}) {
|
|
437
438
|
const dir = settings.buildOutput === "server" ? settings.config.build.client : settings.config.outDir;
|
|
438
439
|
for (const integration of settings.config.integrations) {
|
|
@@ -440,7 +441,7 @@ async function runHookBuildGenerated({
|
|
|
440
441
|
integration,
|
|
441
442
|
hookName: "astro:build:generated",
|
|
442
443
|
logger,
|
|
443
|
-
params: () => ({ dir })
|
|
444
|
+
params: () => ({ dir, experimentalRouteToHeaders })
|
|
444
445
|
});
|
|
445
446
|
}
|
|
446
447
|
}
|
|
@@ -553,5 +554,6 @@ export {
|
|
|
553
554
|
runHookRoutesResolved,
|
|
554
555
|
runHookServerDone,
|
|
555
556
|
runHookServerSetup,
|
|
556
|
-
runHookServerStart
|
|
557
|
+
runHookServerStart,
|
|
558
|
+
toIntegrationResolvedRoute
|
|
557
559
|
};
|
|
@@ -9,6 +9,20 @@ const uniqueElements = (item, index, all) => {
|
|
|
9
9
|
};
|
|
10
10
|
function renderAllHeadContent(result) {
|
|
11
11
|
result._metadata.hasRenderedHead = true;
|
|
12
|
+
let content = "";
|
|
13
|
+
if (result.shouldInjectCspMetaTags && result.cspDestination === "meta") {
|
|
14
|
+
content += renderElement(
|
|
15
|
+
"meta",
|
|
16
|
+
{
|
|
17
|
+
props: {
|
|
18
|
+
"http-equiv": "content-security-policy",
|
|
19
|
+
content: renderCspContent(result)
|
|
20
|
+
},
|
|
21
|
+
children: ""
|
|
22
|
+
},
|
|
23
|
+
false
|
|
24
|
+
);
|
|
25
|
+
}
|
|
12
26
|
const styles = Array.from(result.styles).filter(uniqueElements).map(
|
|
13
27
|
(style) => style.props.rel === "stylesheet" ? renderElement("link", style) : renderElement("style", style)
|
|
14
28
|
);
|
|
@@ -20,25 +34,12 @@ function renderAllHeadContent(result) {
|
|
|
20
34
|
return renderElement("script", script, false);
|
|
21
35
|
});
|
|
22
36
|
const links = Array.from(result.links).filter(uniqueElements).map((link) => renderElement("link", link, false));
|
|
23
|
-
|
|
37
|
+
content += styles.join("\n") + links.join("\n") + scripts.join("\n");
|
|
24
38
|
if (result._metadata.extraHead.length > 0) {
|
|
25
39
|
for (const part of result._metadata.extraHead) {
|
|
26
40
|
content += part;
|
|
27
41
|
}
|
|
28
42
|
}
|
|
29
|
-
if (result.shouldInjectCspMetaTags) {
|
|
30
|
-
content += renderElement(
|
|
31
|
-
"meta",
|
|
32
|
-
{
|
|
33
|
-
props: {
|
|
34
|
-
"http-equiv": "content-security-policy",
|
|
35
|
-
content: renderCspContent(result)
|
|
36
|
-
},
|
|
37
|
-
children: ""
|
|
38
|
-
},
|
|
39
|
-
false
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
43
|
return markHTMLString(content);
|
|
43
44
|
}
|
|
44
45
|
function renderHead() {
|
|
@@ -2,6 +2,7 @@ import { isAstroComponentFactory } from "./astro/index.js";
|
|
|
2
2
|
import { renderToAsyncIterable, renderToReadableStream, renderToString } from "./astro/render.js";
|
|
3
3
|
import { encoder } from "./common.js";
|
|
4
4
|
import { renderComponentToString } from "./component.js";
|
|
5
|
+
import { renderCspContent } from "./csp.js";
|
|
5
6
|
import { isDeno, isNode } from "./util.js";
|
|
6
7
|
async function renderPage(result, componentFactory, props, children, streaming, route) {
|
|
7
8
|
if (!isAstroComponentFactory(componentFactory)) {
|
|
@@ -17,11 +18,15 @@ async function renderPage(result, componentFactory, props, children, streaming,
|
|
|
17
18
|
route
|
|
18
19
|
);
|
|
19
20
|
const bytes = encoder.encode(str);
|
|
21
|
+
const headers2 = new Headers([
|
|
22
|
+
["Content-Type", "text/html"],
|
|
23
|
+
["Content-Length", bytes.byteLength.toString()]
|
|
24
|
+
]);
|
|
25
|
+
if (result.cspDestination === "header" || result.cspDestination === "adapter") {
|
|
26
|
+
headers2.set("content-security-policy", renderCspContent(result));
|
|
27
|
+
}
|
|
20
28
|
return new Response(bytes, {
|
|
21
|
-
headers:
|
|
22
|
-
["Content-Type", "text/html"],
|
|
23
|
-
["Content-Length", bytes.byteLength.toString()]
|
|
24
|
-
])
|
|
29
|
+
headers: headers2
|
|
25
30
|
});
|
|
26
31
|
}
|
|
27
32
|
result._metadata.headInTree = result.componentMetadata.get(componentFactory.moduleId)?.containsHead ?? false;
|
|
@@ -46,6 +51,9 @@ async function renderPage(result, componentFactory, props, children, streaming,
|
|
|
46
51
|
if (body instanceof Response) return body;
|
|
47
52
|
const init = result.response;
|
|
48
53
|
const headers = new Headers(init.headers);
|
|
54
|
+
if (result.shouldInjectCspMetaTags && result.cspDestination === "header" || result.cspDestination === "adapter") {
|
|
55
|
+
headers.set("content-security-policy", renderCspContent(result));
|
|
56
|
+
}
|
|
49
57
|
if (!streaming && typeof body === "string") {
|
|
50
58
|
body = encoder.encode(body);
|
|
51
59
|
headers.set("Content-Length", body.byteLength.toString());
|
|
@@ -99,7 +99,7 @@ let response = await fetch('${serverIslandUrl}', {
|
|
|
99
99
|
});`
|
|
100
100
|
);
|
|
101
101
|
const content = `${method}replaceServerIsland('${hostId}', response);`;
|
|
102
|
-
if (this.result.
|
|
102
|
+
if (this.result.cspDestination) {
|
|
103
103
|
this.result._metadata.extraScriptHashes.push(
|
|
104
104
|
await generateCspDigest(SERVER_ISLAND_REPLACER, this.result.cspAlgorithm)
|
|
105
105
|
);
|
|
@@ -73,6 +73,16 @@ export interface AstroAdapterFeatures {
|
|
|
73
73
|
* Determine the type of build output the adapter is intended for. Defaults to `server`;
|
|
74
74
|
*/
|
|
75
75
|
buildOutput?: 'static' | 'server';
|
|
76
|
+
/**
|
|
77
|
+
* If supported by the adapter and enabled, Astro won't add any `<meta http-equiv>` tags
|
|
78
|
+
* in the static pages, instead it will return a mapping in the
|
|
79
|
+
* `astro:build:generated` hook, so adapters can consume them and add them inside
|
|
80
|
+
* their hosting headers configuration file.
|
|
81
|
+
*
|
|
82
|
+
* NOTE: the semantics and list of headers might change until the feature
|
|
83
|
+
* is out of experimental
|
|
84
|
+
*/
|
|
85
|
+
experimentalStaticHeaders?: boolean;
|
|
76
86
|
}
|
|
77
87
|
export interface AstroAdapter {
|
|
78
88
|
name: string;
|
|
@@ -90,7 +100,7 @@ export interface AstroAdapter {
|
|
|
90
100
|
}
|
|
91
101
|
export type AstroAdapterFeatureMap = {
|
|
92
102
|
/**
|
|
93
|
-
* The adapter is able serve static pages
|
|
103
|
+
* The adapter is able to serve static pages
|
|
94
104
|
*/
|
|
95
105
|
staticOutput?: AdapterSupport;
|
|
96
106
|
/**
|
|
@@ -194,6 +204,7 @@ export interface BaseIntegrationHooks {
|
|
|
194
204
|
'astro:build:generated': (options: {
|
|
195
205
|
dir: URL;
|
|
196
206
|
logger: AstroIntegrationLogger;
|
|
207
|
+
experimentalRouteToHeaders: Map<IntegrationResolvedRoute, Headers>;
|
|
197
208
|
}) => void | Promise<void>;
|
|
198
209
|
'astro:build:done': (options: {
|
|
199
210
|
pages: {
|
|
@@ -6,7 +6,7 @@ import type { Params } from './common.js';
|
|
|
6
6
|
import type { AstroConfig, RedirectConfig } from './config.js';
|
|
7
7
|
import type { AstroGlobal, AstroGlobalPartial } from './context.js';
|
|
8
8
|
import type { AstroRenderer } from './integrations.js';
|
|
9
|
-
export type { SSRManifest } from '../../core/app/types.js';
|
|
9
|
+
export type { SSRManifest, SSRManifestCSP, SSRActions } from '../../core/app/types.js';
|
|
10
10
|
export interface NamedSSRLoadedRendererValue extends SSRLoadedRendererValue {
|
|
11
11
|
name: string;
|
|
12
12
|
}
|
|
@@ -225,8 +225,18 @@ export interface SSRResult {
|
|
|
225
225
|
key: Promise<CryptoKey>;
|
|
226
226
|
_metadata: SSRMetadata;
|
|
227
227
|
/**
|
|
228
|
-
*
|
|
228
|
+
* `header`:
|
|
229
|
+
* - <meta> for static pages
|
|
230
|
+
* - Response header for dynamic pages
|
|
231
|
+
*
|
|
232
|
+
* `meta`:
|
|
233
|
+
* - <meta> for all pages
|
|
234
|
+
*
|
|
235
|
+
* `adapter`:
|
|
236
|
+
* - nothing for static pages (the adapter does this)
|
|
237
|
+
* - Response header for dynamic pages
|
|
229
238
|
*/
|
|
239
|
+
cspDestination: NonNullable<SSRManifestCSP['cspDestination']>;
|
|
230
240
|
shouldInjectCspMetaTags: boolean;
|
|
231
241
|
cspAlgorithm: SSRManifestCSP['algorithm'];
|
|
232
242
|
scriptHashes: SSRManifestCSP['scriptHashes'];
|
|
@@ -146,7 +146,8 @@ class DevPipeline extends Pipeline {
|
|
|
146
146
|
routes: this.routesList?.routes,
|
|
147
147
|
trailingSlash: this.config.trailingSlash,
|
|
148
148
|
buildFormat: this.config.build.format,
|
|
149
|
-
base: this.config.base
|
|
149
|
+
base: this.config.base,
|
|
150
|
+
outDir: this.manifest.outDir
|
|
150
151
|
});
|
|
151
152
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
152
153
|
return { newUrl, pathname, componentInstance, routeData };
|
|
@@ -144,6 +144,7 @@ function createDevelopmentManifest(settings) {
|
|
|
144
144
|
}
|
|
145
145
|
if (shouldTrackCspHashes(settings.config.experimental.csp)) {
|
|
146
146
|
csp = {
|
|
147
|
+
cspDestination: settings.adapter?.adapterFeatures?.experimentalStaticHeaders ? "adapter" : void 0,
|
|
147
148
|
scriptHashes: getScriptHashes(settings.config.experimental.csp),
|
|
148
149
|
scriptResources: getScriptResources(settings.config.experimental.csp),
|
|
149
150
|
styleHashes: getStyleHashes(settings.config.experimental.csp),
|
|
@@ -167,7 +168,7 @@ function createDevelopmentManifest(settings) {
|
|
|
167
168
|
assets: /* @__PURE__ */ new Set(),
|
|
168
169
|
entryModules: {},
|
|
169
170
|
routes: [],
|
|
170
|
-
adapterName: settings?.adapter?.name
|
|
171
|
+
adapterName: settings?.adapter?.name ?? "",
|
|
171
172
|
clientDirectives: settings.clientDirectives,
|
|
172
173
|
renderers: [],
|
|
173
174
|
base: settings.config.base,
|