astro 7.0.9 → 7.1.1
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/assets/fonts/infra/fs-font-file-content-resolver.js +1 -1
- package/dist/cli/dev/index.d.ts +17 -0
- package/dist/cli/dev/index.js +56 -2
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/consts.d.ts +2 -0
- package/dist/content/consts.js +4 -0
- package/dist/content/content-layer.d.ts +0 -6
- package/dist/content/content-layer.js +4 -9
- package/dist/content/data-store-source.d.ts +36 -0
- package/dist/content/data-store-source.js +30 -0
- package/dist/content/data-store-writer.d.ts +67 -0
- package/dist/content/data-store-writer.js +94 -0
- package/dist/content/data-store.d.ts +15 -0
- package/dist/content/data-store.js +33 -3
- package/dist/content/loaders/glob.d.ts +7 -0
- package/dist/content/loaders/glob.js +2 -2
- package/dist/content/mutable-data-store.d.ts +8 -0
- package/dist/content/mutable-data-store.js +52 -15
- package/dist/content/paths.d.ts +14 -0
- package/dist/content/paths.js +11 -0
- package/dist/content/runtime.js +4 -4
- package/dist/content/vite-plugin-content-virtual-mod.js +29 -2
- package/dist/core/app/dev/pipeline.js +2 -1
- package/dist/core/app/types.d.ts +39 -5
- package/dist/core/base-pipeline.d.ts +1 -1
- package/dist/core/base-pipeline.js +6 -2
- package/dist/core/build/index.js +2 -1
- package/dist/core/build/plugins/plugin-manifest.js +23 -8
- package/dist/core/config/schemas/base.d.ts +38 -5
- package/dist/core/config/schemas/base.js +15 -8
- package/dist/core/config/schemas/relative.d.ts +73 -15
- package/dist/core/constants.js +1 -1
- package/dist/core/csp/common.d.ts +7 -7
- package/dist/core/csp/common.js +8 -9
- package/dist/core/csp/config.d.ts +45 -0
- package/dist/core/csp/config.js +44 -2
- package/dist/core/csp/runtime.d.ts +21 -1
- package/dist/core/csp/runtime.js +31 -0
- package/dist/core/dev/dev.js +9 -4
- package/dist/core/dev/restart.js +7 -1
- package/dist/core/errors/zod-error-map.js +7 -1
- package/dist/core/fetch/fetch-state.js +77 -29
- package/dist/core/i18n/domain.d.ts +1 -1
- package/dist/core/i18n/domain.js +4 -5
- package/dist/core/logger/config.d.ts +1 -1
- package/dist/core/logger/core.d.ts +4 -4
- package/dist/core/logger/impls/console.d.ts +2 -2
- package/dist/core/logger/impls/json.d.ts +2 -2
- package/dist/core/logger/impls/json.js +3 -14
- package/dist/core/logger/impls/node.d.ts +2 -2
- package/dist/core/logger/load.d.ts +2 -2
- package/dist/core/logger/load.js +19 -27
- package/dist/core/messages/runtime.d.ts +8 -0
- package/dist/core/messages/runtime.js +34 -1
- package/dist/core/render/paginate.js +21 -16
- package/dist/core/sync/index.js +23 -8
- package/dist/integrations/hooks.js +8 -0
- package/dist/manifest/serialized.js +21 -6
- package/dist/runtime/server/escape.d.ts +2 -0
- package/dist/runtime/server/escape.js +4 -0
- package/dist/runtime/server/render/csp.js +80 -19
- package/dist/runtime/server/render/server-islands.js +6 -4
- package/dist/runtime/server/transition.js +2 -2
- package/dist/types/astro.d.ts +2 -3
- package/dist/types/public/common.d.ts +13 -0
- package/dist/types/public/config.d.ts +196 -15
- package/dist/types/public/context.d.ts +27 -11
- package/dist/types/public/internal.d.ts +12 -11
- package/dist/vite-plugin-app/pipeline.js +2 -1
- package/dist/vite-plugin-astro-server/route-guard.js +3 -2
- package/package.json +3 -3
|
@@ -14,6 +14,7 @@ import { validateSetAdapter } from "../core/dev/adapter-validation.js";
|
|
|
14
14
|
import { getRouteGenerator } from "../core/routing/generator.js";
|
|
15
15
|
import { getClientOutputDirectory } from "../prerender/utils.js";
|
|
16
16
|
import { validateSupportedFeatures } from "./features-validation.js";
|
|
17
|
+
import { loadLoggerDestination } from "../core/logger/load.js";
|
|
17
18
|
async function withTakingALongTimeMsg({
|
|
18
19
|
name,
|
|
19
20
|
hookName,
|
|
@@ -139,6 +140,7 @@ async function runHookConfigSetup({
|
|
|
139
140
|
let astroJSXRenderer = null;
|
|
140
141
|
for (let i = 0; i < updatedConfig.integrations.length; i++) {
|
|
141
142
|
const integration = updatedConfig.integrations[i];
|
|
143
|
+
let isLoggerUpdated = false;
|
|
142
144
|
const { integrationLogger } = await runHookInternal({
|
|
143
145
|
integration,
|
|
144
146
|
hookName: "astro:config:setup",
|
|
@@ -169,6 +171,9 @@ async function runHookConfigSetup({
|
|
|
169
171
|
updatedSettings.scripts.push({ stage, content });
|
|
170
172
|
},
|
|
171
173
|
updateConfig: (newConfig) => {
|
|
174
|
+
if (newConfig.logger?.entrypoint) {
|
|
175
|
+
isLoggerUpdated = true;
|
|
176
|
+
}
|
|
172
177
|
updatedConfig = mergeConfig(updatedConfig, newConfig);
|
|
173
178
|
return { ...updatedConfig };
|
|
174
179
|
},
|
|
@@ -254,6 +259,9 @@ async function runHookConfigSetup({
|
|
|
254
259
|
}
|
|
255
260
|
try {
|
|
256
261
|
updatedConfig = await validateConfigRefined(updatedConfig);
|
|
262
|
+
if (isLoggerUpdated) {
|
|
263
|
+
logger.setDestination(await loadLoggerDestination(updatedConfig.logger));
|
|
264
|
+
}
|
|
257
265
|
} catch (error) {
|
|
258
266
|
integrationLogger.error("An error occurred while updating the config");
|
|
259
267
|
throw error;
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
getStyleResources,
|
|
15
15
|
shouldTrackCspHashes
|
|
16
16
|
} from "../core/csp/common.js";
|
|
17
|
+
import { partitionByKind } from "../core/csp/runtime.js";
|
|
17
18
|
import { createKey, encodeKey, getEnvironmentKey, hasEnvironmentKey } from "../core/encryption.js";
|
|
18
19
|
import { MIDDLEWARE_MODULE_ID } from "../core/middleware/vite-plugin.js";
|
|
19
20
|
import { SERVER_ISLAND_MANIFEST } from "../core/server-islands/vite-plugin-server-islands.js";
|
|
@@ -131,15 +132,29 @@ async function createSerializedManifest(settings, encodedKey) {
|
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
if (shouldTrackCspHashes(settings.config.security.csp)) {
|
|
135
|
+
const cspConfig = settings.config.security.csp;
|
|
136
|
+
const scriptDirective = {
|
|
137
|
+
resources: getScriptResources(cspConfig),
|
|
138
|
+
hashes: getScriptHashes(cspConfig),
|
|
139
|
+
strictDynamic: getStrictDynamic(cspConfig)
|
|
140
|
+
};
|
|
141
|
+
const styleDirective = {
|
|
142
|
+
resources: getStyleResources(cspConfig),
|
|
143
|
+
hashes: getStyleHashes(cspConfig)
|
|
144
|
+
};
|
|
145
|
+
const scriptDefault = partitionByKind(scriptDirective).default;
|
|
146
|
+
const styleDefault = partitionByKind(styleDirective).default;
|
|
134
147
|
csp = {
|
|
135
148
|
cspDestination: settings.adapter?.adapterFeatures?.staticHeaders ? "adapter" : void 0,
|
|
136
|
-
|
|
137
|
-
scriptResources: getScriptResources(settings.config.security.csp),
|
|
138
|
-
styleHashes: getStyleHashes(settings.config.security.csp),
|
|
139
|
-
styleResources: getStyleResources(settings.config.security.csp),
|
|
140
|
-
algorithm: getAlgorithm(settings.config.security.csp),
|
|
149
|
+
algorithm: getAlgorithm(cspConfig),
|
|
141
150
|
directives: getDirectives(settings),
|
|
142
|
-
|
|
151
|
+
scriptHashes: scriptDefault.hashes,
|
|
152
|
+
scriptResources: scriptDefault.resources,
|
|
153
|
+
isStrictDynamic: scriptDirective.strictDynamic,
|
|
154
|
+
styleHashes: styleDefault.hashes,
|
|
155
|
+
styleResources: styleDefault.resources,
|
|
156
|
+
scriptDirective,
|
|
157
|
+
styleDirective
|
|
143
158
|
};
|
|
144
159
|
}
|
|
145
160
|
let loggerConfig = void 0;
|
|
@@ -7,6 +7,8 @@ export declare const escapeHTML: (str: string) => string;
|
|
|
7
7
|
* @see https://mathiasbynens.be/notes/etago
|
|
8
8
|
*/
|
|
9
9
|
export declare function stringifyForScript(value: any): string;
|
|
10
|
+
/** Escapes CSS text so it can be embedded inside a `<style>` tag. */
|
|
11
|
+
export declare function escapeStyleText(value: string): string;
|
|
10
12
|
export declare class HTMLBytes extends Uint8Array {
|
|
11
13
|
}
|
|
12
14
|
declare const htmlStringSymbol: unique symbol;
|
|
@@ -4,6 +4,9 @@ const escapeHTML = escape;
|
|
|
4
4
|
function stringifyForScript(value) {
|
|
5
5
|
return JSON.stringify(value)?.replace(/</g, "\\u003c");
|
|
6
6
|
}
|
|
7
|
+
function escapeStyleText(value) {
|
|
8
|
+
return value.replaceAll("<", "\\3C ");
|
|
9
|
+
}
|
|
7
10
|
class HTMLBytes extends Uint8Array {
|
|
8
11
|
}
|
|
9
12
|
Object.defineProperty(HTMLBytes.prototype, Symbol.toStringTag, {
|
|
@@ -77,6 +80,7 @@ export {
|
|
|
77
80
|
HTMLBytes,
|
|
78
81
|
HTMLString,
|
|
79
82
|
escapeHTML,
|
|
83
|
+
escapeStyleText,
|
|
80
84
|
isHTMLBytes,
|
|
81
85
|
isHTMLString,
|
|
82
86
|
markHTMLString,
|
|
@@ -1,34 +1,95 @@
|
|
|
1
|
+
import { partitionByKind } from "../../../core/csp/runtime.js";
|
|
1
2
|
function renderCspContent(result) {
|
|
3
|
+
const { scriptDirective, styleDirective, directives } = result;
|
|
4
|
+
const script = partitionByKind(scriptDirective);
|
|
5
|
+
const style = partitionByKind(styleDirective);
|
|
2
6
|
const finalScriptHashes = /* @__PURE__ */ new Set();
|
|
3
|
-
const
|
|
4
|
-
for (const scriptHash of result.scriptHashes) {
|
|
7
|
+
for (const scriptHash of script.default.hashes) {
|
|
5
8
|
finalScriptHashes.add(`'${scriptHash}'`);
|
|
6
9
|
}
|
|
7
|
-
for (const
|
|
10
|
+
for (const scriptHash of result._metadata.extraScriptHashes) {
|
|
11
|
+
finalScriptHashes.add(`'${scriptHash}'`);
|
|
12
|
+
}
|
|
13
|
+
const finalStyleHashes = /* @__PURE__ */ new Set();
|
|
14
|
+
for (const styleHash of style.default.hashes) {
|
|
8
15
|
finalStyleHashes.add(`'${styleHash}'`);
|
|
9
16
|
}
|
|
10
17
|
for (const styleHash of result._metadata.extraStyleHashes) {
|
|
11
18
|
finalStyleHashes.add(`'${styleHash}'`);
|
|
12
19
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let directives;
|
|
17
|
-
if (result.directives.length > 0) {
|
|
18
|
-
directives = result.directives.join(";") + ";";
|
|
20
|
+
let directivesContent;
|
|
21
|
+
if (directives.length > 0) {
|
|
22
|
+
directivesContent = directives.join(";") + ";";
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
const scriptResources = script.default.resources.length > 0 ? script.default.resources.join(" ") : "'self'";
|
|
25
|
+
const styleResources = style.default.resources.length > 0 ? style.default.resources.join(" ") : "'self'";
|
|
26
|
+
const scriptElementDefaultResource = script.default.resources.length > 0 ? "" : "'self'";
|
|
27
|
+
const styleElementDefaultResource = style.default.resources.length > 0 ? "" : "'self'";
|
|
28
|
+
const scriptElemActive = isEnabled(script.element);
|
|
29
|
+
const styleElemActive = isEnabled(style.element);
|
|
30
|
+
const strictDynamicSuffix = scriptDirective.strictDynamic ? ` 'strict-dynamic'` : "";
|
|
31
|
+
const scriptBaselineTokens = [
|
|
32
|
+
...scriptElemActive ? [] : [...finalScriptHashes],
|
|
33
|
+
...scriptDirective.strictDynamic ? [`'strict-dynamic'`] : []
|
|
34
|
+
];
|
|
35
|
+
const scriptSrc = `script-src ${scriptResources} ${scriptBaselineTokens.join(" ")};`;
|
|
36
|
+
const styleSrc = `style-src ${styleResources} ${(styleElemActive ? [] : [...finalStyleHashes]).join(" ")};`;
|
|
37
|
+
const scriptSrcElem = scriptElemActive ? renderSpecificDirective(
|
|
38
|
+
"script-src-elem",
|
|
39
|
+
script.element.resources,
|
|
40
|
+
scriptElementDefaultResource,
|
|
41
|
+
finalScriptHashes,
|
|
42
|
+
script.element.hashes,
|
|
43
|
+
strictDynamicSuffix
|
|
44
|
+
) : void 0;
|
|
45
|
+
const scriptSrcAttr = isEnabled(script.attribute) ? renderSpecificDirective(
|
|
46
|
+
"script-src-attr",
|
|
47
|
+
script.attribute.resources,
|
|
48
|
+
"'none'",
|
|
49
|
+
void 0,
|
|
50
|
+
script.attribute.hashes
|
|
51
|
+
) : void 0;
|
|
52
|
+
const styleSrcElem = styleElemActive ? renderSpecificDirective(
|
|
53
|
+
"style-src-elem",
|
|
54
|
+
style.element.resources,
|
|
55
|
+
styleElementDefaultResource,
|
|
56
|
+
finalStyleHashes,
|
|
57
|
+
style.element.hashes
|
|
58
|
+
) : void 0;
|
|
59
|
+
const styleSrcAttr = isEnabled(style.attribute) ? renderSpecificDirective(
|
|
60
|
+
"style-src-attr",
|
|
61
|
+
style.attribute.resources,
|
|
62
|
+
"'none'",
|
|
63
|
+
void 0,
|
|
64
|
+
style.attribute.hashes
|
|
65
|
+
) : void 0;
|
|
66
|
+
return [
|
|
67
|
+
directivesContent,
|
|
68
|
+
scriptSrc,
|
|
69
|
+
scriptSrcElem,
|
|
70
|
+
scriptSrcAttr,
|
|
71
|
+
styleSrc,
|
|
72
|
+
styleSrcElem,
|
|
73
|
+
styleSrcAttr
|
|
74
|
+
].filter(Boolean).join(" ");
|
|
75
|
+
}
|
|
76
|
+
function isEnabled(sources) {
|
|
77
|
+
return sources.resources.length > 0 || sources.hashes.length > 0;
|
|
78
|
+
}
|
|
79
|
+
function renderSpecificDirective(name, resources, defaultResource, sharedHashes, ownHashes, suffix = "") {
|
|
80
|
+
const hashes = new Set(sharedHashes);
|
|
81
|
+
for (const hash of ownHashes) {
|
|
82
|
+
hashes.add(`'${hash}'`);
|
|
23
83
|
}
|
|
24
|
-
let
|
|
25
|
-
if (
|
|
26
|
-
|
|
84
|
+
let finalResources;
|
|
85
|
+
if (resources.length > 0) {
|
|
86
|
+
finalResources = resources.map((r) => `${r}`).join(" ");
|
|
87
|
+
} else if (defaultResource === "'none'" && hashes.size > 0) {
|
|
88
|
+
finalResources = "";
|
|
89
|
+
} else {
|
|
90
|
+
finalResources = defaultResource;
|
|
27
91
|
}
|
|
28
|
-
|
|
29
|
-
const scriptSrc = `script-src ${scriptResources} ${Array.from(finalScriptHashes).join(" ")}${strictDynamic};`;
|
|
30
|
-
const styleSrc = `style-src ${styleResources} ${Array.from(finalStyleHashes).join(" ")};`;
|
|
31
|
-
return [directives, scriptSrc, styleSrc].filter(Boolean).join(" ");
|
|
92
|
+
return `${name} ${[finalResources, ...hashes].filter(Boolean).join(" ")}${suffix};`;
|
|
32
93
|
}
|
|
33
94
|
export {
|
|
34
95
|
renderCspContent
|
|
@@ -5,6 +5,7 @@ import { createThinHead } from "./astro/head-and-content.js";
|
|
|
5
5
|
import { createRenderInstruction } from "./instruction.js";
|
|
6
6
|
import { SERVER_ISLAND_START } from "./server-islands-shared.js";
|
|
7
7
|
import { renderSlotToString } from "./slot.js";
|
|
8
|
+
import { toAttributeString } from "./util.js";
|
|
8
9
|
const internalProps = /* @__PURE__ */ new Set([
|
|
9
10
|
"server:component-path",
|
|
10
11
|
"server:component-export",
|
|
@@ -148,16 +149,17 @@ class ServerIslandComponent {
|
|
|
148
149
|
serverIslandUrl += "?" + potentialSearchParams.toString();
|
|
149
150
|
this.result._metadata.extraHead.push(
|
|
150
151
|
markHTMLString(
|
|
151
|
-
`<link rel="preload" as="fetch" href="${serverIslandUrl}" crossorigin="anonymous">`
|
|
152
|
+
`<link rel="preload" as="fetch" href="${toAttributeString(serverIslandUrl)}" crossorigin="anonymous">`
|
|
152
153
|
)
|
|
153
154
|
);
|
|
154
155
|
}
|
|
155
156
|
const adapterHeaders = this.result.internalFetchHeaders || {};
|
|
156
157
|
const headersJson = stringifyForScript(adapterHeaders);
|
|
158
|
+
const serverIslandUrlJson = stringifyForScript(serverIslandUrl);
|
|
157
159
|
const method = useGETRequest ? (
|
|
158
160
|
// GET request
|
|
159
161
|
`const headers = new Headers(${headersJson});
|
|
160
|
-
let response = await fetch(
|
|
162
|
+
let response = await fetch(${serverIslandUrlJson}, { headers });`
|
|
161
163
|
) : (
|
|
162
164
|
// POST request
|
|
163
165
|
`let data = {
|
|
@@ -166,13 +168,13 @@ let response = await fetch('${serverIslandUrl}', { headers });`
|
|
|
166
168
|
encryptedSlots: ${stringifyForScript(slotsEncrypted)},
|
|
167
169
|
};
|
|
168
170
|
const headers = new Headers({ 'Content-Type': 'application/json', ...${headersJson} });
|
|
169
|
-
let response = await fetch(
|
|
171
|
+
let response = await fetch(${serverIslandUrlJson}, {
|
|
170
172
|
method: 'POST',
|
|
171
173
|
body: JSON.stringify(data),
|
|
172
174
|
headers,
|
|
173
175
|
});`
|
|
174
176
|
);
|
|
175
|
-
this.islandContent = `${method}replaceServerIsland(
|
|
177
|
+
this.islandContent = `${method}replaceServerIsland(${stringifyForScript(hostId)}, response);`;
|
|
176
178
|
return this.islandContent;
|
|
177
179
|
}
|
|
178
180
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import cssesc from "../../transitions/cssesc.js";
|
|
2
2
|
import { fade, slide } from "../../transitions/index.js";
|
|
3
|
-
import { markHTMLString } from "./escape.js";
|
|
3
|
+
import { escapeStyleText, markHTMLString } from "./escape.js";
|
|
4
4
|
const transitionNameMap = /* @__PURE__ */ new WeakMap();
|
|
5
5
|
function incrementTransitionNumber(result) {
|
|
6
6
|
let num = 1;
|
|
@@ -56,7 +56,7 @@ function renderTransition(result, hash, animationName, transitionName) {
|
|
|
56
56
|
sheet.addAnimationRaw("new", "animation: none; mix-blend-mode: normal;");
|
|
57
57
|
sheet.addModern("group", "animation: none");
|
|
58
58
|
}
|
|
59
|
-
const css = sheet.toString();
|
|
59
|
+
const css = escapeStyleText(sheet.toString());
|
|
60
60
|
result._metadata.extraHead.push(markHTMLString(`<style>${css}</style>`));
|
|
61
61
|
return scope;
|
|
62
62
|
}
|
package/dist/types/astro.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Server } from 'node:http';
|
|
2
|
+
import type { CspHash } from '../core/csp/config.js';
|
|
2
3
|
import type { AstroTimer } from '../core/config/timer.js';
|
|
3
4
|
import type { TSConfig } from '../core/config/tsconfig.js';
|
|
4
5
|
import type { AstroLogger, AstroLoggerLevel } from '../core/logger/core.js';
|
|
@@ -18,7 +19,6 @@ export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern' | 'redi
|
|
|
18
19
|
trailingSlash: AstroConfig['trailingSlash'];
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
|
-
type CspObject = Required<Exclude<AstroConfig['security']['csp'], boolean>>;
|
|
22
22
|
export interface AstroSettings {
|
|
23
23
|
config: AstroConfig;
|
|
24
24
|
adapter: AstroAdapter | undefined;
|
|
@@ -64,7 +64,7 @@ export interface AstroSettings {
|
|
|
64
64
|
buildOutput: undefined | 'static' | 'server';
|
|
65
65
|
injectedCsp: {
|
|
66
66
|
fontResources: Set<string>;
|
|
67
|
-
styleHashes:
|
|
67
|
+
styleHashes: CspHash[];
|
|
68
68
|
};
|
|
69
69
|
logLevel: AstroLoggerLevel;
|
|
70
70
|
fontsHttpServer: Server | null;
|
|
@@ -89,4 +89,3 @@ export interface ImportedDevStyle {
|
|
|
89
89
|
url: string;
|
|
90
90
|
content: string;
|
|
91
91
|
}
|
|
92
|
-
export {};
|
|
@@ -36,6 +36,19 @@ export interface PaginateOptions<PaginateProps extends Props, PaginateParams ext
|
|
|
36
36
|
params?: PaginateParams;
|
|
37
37
|
/** object of props to forward to `page` result */
|
|
38
38
|
props?: PaginateProps;
|
|
39
|
+
/**
|
|
40
|
+
* Transform each pagination URL before it is set on the page result.
|
|
41
|
+
* Useful for adding a file extension (e.g. `.html`) when deploying to a
|
|
42
|
+
* static file server that does not support clean URLs.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* paginate(items, {
|
|
47
|
+
* format: (url) => `${url}.html`,
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
format?: (url: string) => string;
|
|
39
52
|
}
|
|
40
53
|
/**
|
|
41
54
|
* Represents a single page of data in a paginated collection
|
|
@@ -9,7 +9,7 @@ import type { AssetsPrefix } from '../../core/app/types.js';
|
|
|
9
9
|
import type { CacheProviderConfig, RouteRules } from '../../core/cache/types.js';
|
|
10
10
|
import type { AstroConfigType } from '../../core/config/schemas/index.js';
|
|
11
11
|
import type { REDIRECT_STATUS_CODES } from '../../core/constants.js';
|
|
12
|
-
import type { CspAlgorithm, CspDirective, CspHash } from '../../core/csp/config.js';
|
|
12
|
+
import type { CspAlgorithm, CspDirective, CspHash, CspHashEntry, CspKind, CspResourceEntry } from '../../core/csp/config.js';
|
|
13
13
|
import type { AstroLoggerLevel } from '../../core/logger/core.js';
|
|
14
14
|
import type { SessionConfig, SessionDriverConfig, SessionDriverName } from '../../core/session/types.js';
|
|
15
15
|
import type { EnvSchema } from '../../env/schema.js';
|
|
@@ -21,16 +21,16 @@ export type Locales = (string | {
|
|
|
21
21
|
path: string;
|
|
22
22
|
})[];
|
|
23
23
|
export type { FontProvider };
|
|
24
|
-
export type { CspAlgorithm, CspHash };
|
|
24
|
+
export type { CspAlgorithm, CspHash, CspKind, CspResourceEntry, CspHashEntry };
|
|
25
25
|
export type { RemotePattern };
|
|
26
26
|
export type { SvgOptimizer };
|
|
27
27
|
export type CspStyleDirective = {
|
|
28
|
-
hashes?:
|
|
29
|
-
resources?:
|
|
28
|
+
hashes?: CspHashEntry[];
|
|
29
|
+
resources?: CspResourceEntry[];
|
|
30
30
|
};
|
|
31
31
|
export type CspScriptDirective = {
|
|
32
|
-
hashes?:
|
|
33
|
-
resources?:
|
|
32
|
+
hashes?: CspHashEntry[];
|
|
33
|
+
resources?: CspResourceEntry[];
|
|
34
34
|
strictDynamic?: boolean;
|
|
35
35
|
};
|
|
36
36
|
type NormalizeLocales<T extends Locales> = {
|
|
@@ -776,7 +776,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
776
776
|
* @docs
|
|
777
777
|
* @name security.csp.styleDirective.hashes
|
|
778
778
|
* @kind h6
|
|
779
|
-
* @type {
|
|
779
|
+
* @type {CspHashEntry[]}
|
|
780
780
|
* @default `[]`
|
|
781
781
|
* @version 6.0.0
|
|
782
782
|
* @description
|
|
@@ -785,6 +785,13 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
785
785
|
*
|
|
786
786
|
* You must provide hashes that start with `sha384-`, `sha512-` or `sha256-`. Other values will cause a validation error. These hashes are added to all pages.
|
|
787
787
|
*
|
|
788
|
+
* Since Astro v7.1, each entry can be a string or an object. The object allows changing the scope of the hash via the `kind` field. The `kind` field accepts:
|
|
789
|
+
* - `"element"`: it will store the hash in the `style-src-elem` directive
|
|
790
|
+
* - `"attribute"`: it will store the hash in the `style-src-attr` directive
|
|
791
|
+
* - `"default"`: it will store the hash in the `style-src` directive
|
|
792
|
+
*
|
|
793
|
+
* A `"default"` hash goes on `style-src`, or on `style-src-elem` instead once you use `kind: "element"`. It is never added to `style-src-attr`. Astro's generated hashes follow the same rule.
|
|
794
|
+
*
|
|
788
795
|
* ```js title="astro.config.mjs"
|
|
789
796
|
* import { defineConfig } from 'astro/config';
|
|
790
797
|
*
|
|
@@ -813,19 +820,56 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
813
820
|
* "
|
|
814
821
|
* >
|
|
815
822
|
* ```
|
|
823
|
+
*
|
|
824
|
+
* Scoping a hash to `"element"` stores it in `style-src-elem` instead. Astro's generated hashes move there too:
|
|
825
|
+
*
|
|
826
|
+
* ```js title="astro.config.mjs"
|
|
827
|
+
* import { defineConfig } from 'astro/config';
|
|
828
|
+
*
|
|
829
|
+
* export default defineConfig({
|
|
830
|
+
* security: {
|
|
831
|
+
* csp: {
|
|
832
|
+
* styleDirective: {
|
|
833
|
+
* hashes: [{ hash: "sha256-styleHash", kind: "element" }]
|
|
834
|
+
* }
|
|
835
|
+
* }
|
|
836
|
+
* }
|
|
837
|
+
* });
|
|
838
|
+
* ```
|
|
839
|
+
*
|
|
840
|
+
* After the build, the `<meta>` element will include the hash in the `style-src-elem` directive instead of `style-src`:
|
|
841
|
+
*
|
|
842
|
+
* ```html
|
|
843
|
+
* <meta
|
|
844
|
+
* http-equiv="content-security-policy"
|
|
845
|
+
* content="
|
|
846
|
+
* style-src 'self';
|
|
847
|
+
* style-src-elem 'self' 'sha256-styleHash' 'sha256-generatedByAstro';
|
|
848
|
+
* "
|
|
849
|
+
* >
|
|
850
|
+
* ```
|
|
816
851
|
*/
|
|
817
|
-
hashes?:
|
|
852
|
+
hashes?: CspHashEntry[];
|
|
818
853
|
/**
|
|
819
854
|
* @docs
|
|
820
855
|
* @name security.csp.styleDirective.resources
|
|
821
856
|
* @kind h6
|
|
822
|
-
* @type {
|
|
857
|
+
* @type {CspResourceEntry[]}
|
|
823
858
|
* @default `[]`
|
|
824
859
|
* @version 6.0.0
|
|
825
860
|
* @description
|
|
826
861
|
*
|
|
827
862
|
* A list of valid sources for `style-src` directives to override Astro's default sources. This will not include `'self'` by default, and must be included in this list if you wish to keep it. These resources are added to all pages.
|
|
828
863
|
*
|
|
864
|
+
* Since Astro v7.1, each entry can be a string or an object. The object allows changing the scope of the source via the `kind` field. The `kind` field accepts:
|
|
865
|
+
* - `"element"`: it will store the source in the `style-src-elem` directive
|
|
866
|
+
* - `"attribute"`: it will store the source in the `style-src-attr` directive
|
|
867
|
+
* - `"default"`: it will store the source in the `style-src` directive
|
|
868
|
+
*
|
|
869
|
+
* `"attribute"` sources must be one of `'none'`, `'unsafe-hashes'`, `'unsafe-inline'`, or `'report-sample'`, and `'unsafe-hashes'` cannot be used with `"element"`. A common use is allowing inline `style` attributes (for example, from `define:vars` or Shiki) with `{ resource: "'unsafe-inline'", kind: "attribute" }`.
|
|
870
|
+
*
|
|
871
|
+
* Unlike a hash, a `"default"` source is never moved: it stays on `style-src` only. Where there is a mix of "default" and specific resources (e.g. `"element"` or `"attribute"`), Astro emits a warning.
|
|
872
|
+
*
|
|
829
873
|
* ```js title="astro.config.mjs"
|
|
830
874
|
* import { defineConfig } from 'astro/config';
|
|
831
875
|
*
|
|
@@ -856,9 +900,40 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
856
900
|
* </head>
|
|
857
901
|
* ```
|
|
858
902
|
*
|
|
903
|
+
* A `"default"` source is not copied into the more specific directives. Here, a `"default"` source and an `"element"` source render in different directives:
|
|
904
|
+
*
|
|
905
|
+
* ```js title="astro.config.mjs"
|
|
906
|
+
* import { defineConfig } from 'astro/config';
|
|
907
|
+
*
|
|
908
|
+
* export default defineConfig({
|
|
909
|
+
* security: {
|
|
910
|
+
* csp: {
|
|
911
|
+
* styleDirective: {
|
|
912
|
+
* resources: [
|
|
913
|
+
* "https://styles.cdn.example.com",
|
|
914
|
+
* { resource: "https://elements.cdn.example.com", kind: "element" }
|
|
915
|
+
* ]
|
|
916
|
+
* }
|
|
917
|
+
* }
|
|
918
|
+
* }
|
|
919
|
+
* });
|
|
920
|
+
* ```
|
|
921
|
+
*
|
|
922
|
+
* After the build, the `<meta>` element keeps `https://styles.cdn.example.com` on `style-src` only. This means that this value is not added to `style-src-elem` and does not apply to `<style>` and `<link>` elements (the generated hash, by contrast, does move there):
|
|
923
|
+
*
|
|
924
|
+
* ```html
|
|
925
|
+
* <meta
|
|
926
|
+
* http-equiv="content-security-policy"
|
|
927
|
+
* content="
|
|
928
|
+
* style-src https://styles.cdn.example.com;
|
|
929
|
+
* style-src-elem https://elements.cdn.example.com 'sha256-generatedByAstro';
|
|
930
|
+
* "
|
|
931
|
+
* >
|
|
932
|
+
* ```
|
|
933
|
+
*
|
|
859
934
|
* When resources are inserted multiple times or from multiple sources (e.g. defined in your `csp` config and added using [the CSP runtime API](/en/reference/api-reference/#csp)), Astro will merge and deduplicate all resources to create your `<meta>` element.
|
|
860
935
|
*/
|
|
861
|
-
resources?:
|
|
936
|
+
resources?: CspResourceEntry[];
|
|
862
937
|
};
|
|
863
938
|
/**
|
|
864
939
|
* @docs
|
|
@@ -876,7 +951,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
876
951
|
* @docs
|
|
877
952
|
* @name security.csp.scriptDirective.hashes
|
|
878
953
|
* @kind h6
|
|
879
|
-
* @type {
|
|
954
|
+
* @type {CspHashEntry[]}
|
|
880
955
|
* @default `[]`
|
|
881
956
|
* @version 6.0.0
|
|
882
957
|
* @description
|
|
@@ -885,6 +960,13 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
885
960
|
*
|
|
886
961
|
* You must provide hashes that start with `sha384-`, `sha512-` or `sha256-`. Other values will cause a validation error. These hashes are added to all pages.
|
|
887
962
|
*
|
|
963
|
+
* Since Astro v7.1, each entry can be a string or an object. The object allows changing the scope of the hash via the `kind` field. The `kind` field accepts:
|
|
964
|
+
* - `"element"`: it will store the hash in the `script-src-elem` directive
|
|
965
|
+
* - `"attribute"`: it will store the hash in the `script-src-attr` directive
|
|
966
|
+
* - `"default"`: it will store the hash in the `script-src` directive
|
|
967
|
+
*
|
|
968
|
+
* A `"default"` hash goes on `script-src`, or on `script-src-elem` instead once you use `kind: "element"`. It is never added to `script-src-attr`. Astro's generated hashes follow the same rule.
|
|
969
|
+
*
|
|
888
970
|
* ```js title="astro.config.mjs"
|
|
889
971
|
* import { defineConfig } from 'astro/config';
|
|
890
972
|
*
|
|
@@ -913,19 +995,56 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
913
995
|
* "
|
|
914
996
|
* >
|
|
915
997
|
* ```
|
|
998
|
+
*
|
|
999
|
+
* Scoping a hash to `"element"` stores it in `script-src-elem` instead. Astro's generated hashes move there too:
|
|
1000
|
+
*
|
|
1001
|
+
* ```js title="astro.config.mjs"
|
|
1002
|
+
* import { defineConfig } from 'astro/config';
|
|
1003
|
+
*
|
|
1004
|
+
* export default defineConfig({
|
|
1005
|
+
* security: {
|
|
1006
|
+
* csp: {
|
|
1007
|
+
* scriptDirective: {
|
|
1008
|
+
* hashes: [{ hash: "sha256-scriptHash", kind: "element" }]
|
|
1009
|
+
* }
|
|
1010
|
+
* }
|
|
1011
|
+
* }
|
|
1012
|
+
* });
|
|
1013
|
+
* ```
|
|
1014
|
+
*
|
|
1015
|
+
* After the build, the `<meta>` element will include the hash in the `script-src-elem` directive instead of `script-src`:
|
|
1016
|
+
*
|
|
1017
|
+
* ```html
|
|
1018
|
+
* <meta
|
|
1019
|
+
* http-equiv="content-security-policy"
|
|
1020
|
+
* content="
|
|
1021
|
+
* script-src 'self';
|
|
1022
|
+
* script-src-elem 'self' 'sha256-scriptHash' 'sha256-generatedByAstro';
|
|
1023
|
+
* "
|
|
1024
|
+
* >
|
|
1025
|
+
* ```
|
|
916
1026
|
*/
|
|
917
|
-
hashes?:
|
|
1027
|
+
hashes?: CspHashEntry[];
|
|
918
1028
|
/**
|
|
919
1029
|
* @docs
|
|
920
1030
|
* @name security.csp.scriptDirective.resources
|
|
921
1031
|
* @kind h6
|
|
922
|
-
* @type {
|
|
1032
|
+
* @type {CspResourceEntry[]}
|
|
923
1033
|
* @default `[]`
|
|
924
1034
|
* @version 6.0.0
|
|
925
1035
|
* @description
|
|
926
1036
|
*
|
|
927
1037
|
* A list of valid sources for the `script-src` directives to override Astro's default sources. This will not include `'self'` by default, and must be included in this list if you wish to keep it. These resources are added to all pages.
|
|
928
1038
|
*
|
|
1039
|
+
* Since Astro v7.1, each entry can be a string or an object. The object allows changing the scope of the source via the `kind` field. The `kind` field accepts:
|
|
1040
|
+
* - `"element"`: it will store the source in the `script-src-elem` directive
|
|
1041
|
+
* - `"attribute"`: it will store the source in the `script-src-attr` directive
|
|
1042
|
+
* - `"default"`: it will store the source in the `script-src` directive
|
|
1043
|
+
*
|
|
1044
|
+
* `"attribute"` sources must be one of `'none'`, `'unsafe-hashes'`, `'unsafe-inline'`, or `'report-sample'`, and `'unsafe-hashes'` cannot be used with `"element"`.
|
|
1045
|
+
*
|
|
1046
|
+
* Unlike a hash, a `"default"` source is never moved and stays on `script-src` only. This does not apply where you also scope `"element"` or `"attribute"` sources, since browsers do not fall back. Astro warns when this happens. Add it to the more specific directive as well, if necessary.
|
|
1047
|
+
*
|
|
929
1048
|
* ```js title="astro.config.mjs"
|
|
930
1049
|
* import { defineConfig } from 'astro/config';
|
|
931
1050
|
*
|
|
@@ -955,9 +1074,40 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
955
1074
|
* </head>
|
|
956
1075
|
* ```
|
|
957
1076
|
*
|
|
1077
|
+
* A `"default"` source is not copied into the more specific directives. Here, a `"default"` source and an `"element"` source render in different directives:
|
|
1078
|
+
*
|
|
1079
|
+
* ```js title="astro.config.mjs"
|
|
1080
|
+
* import { defineConfig } from 'astro/config';
|
|
1081
|
+
*
|
|
1082
|
+
* export default defineConfig({
|
|
1083
|
+
* security: {
|
|
1084
|
+
* csp: {
|
|
1085
|
+
* scriptDirective: {
|
|
1086
|
+
* resources: [
|
|
1087
|
+
* "https://cdn.example.com",
|
|
1088
|
+
* { resource: "https://elements.cdn.example.com", kind: "element" }
|
|
1089
|
+
* ]
|
|
1090
|
+
* }
|
|
1091
|
+
* }
|
|
1092
|
+
* }
|
|
1093
|
+
* });
|
|
1094
|
+
* ```
|
|
1095
|
+
*
|
|
1096
|
+
* After the build, the `<meta>` element keeps `https://cdn.example.com` on `script-src` only. This means that this value is not added to `script-src-elem` and does not apply to `<script>` elements (the generated hash, by contrast, does move there):
|
|
1097
|
+
*
|
|
1098
|
+
* ```html
|
|
1099
|
+
* <meta
|
|
1100
|
+
* http-equiv="content-security-policy"
|
|
1101
|
+
* content="
|
|
1102
|
+
* script-src https://cdn.example.com;
|
|
1103
|
+
* script-src-elem https://elements.cdn.example.com 'sha256-generatedByAstro';
|
|
1104
|
+
* "
|
|
1105
|
+
* >
|
|
1106
|
+
* ```
|
|
1107
|
+
*
|
|
958
1108
|
* When resources are inserted multiple times or from multiple sources (e.g. defined in your `csp` config and added using [the CSP runtime API](/en/reference/api-reference/#csp)), Astro will merge and deduplicate all resources to create your `<meta>` element.
|
|
959
1109
|
*/
|
|
960
|
-
resources?:
|
|
1110
|
+
resources?: CspResourceEntry[];
|
|
961
1111
|
/**
|
|
962
1112
|
* @docs
|
|
963
1113
|
* @name security.csp.scriptDirective.strictDynamic
|
|
@@ -982,6 +1132,8 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
982
1132
|
* }
|
|
983
1133
|
* });
|
|
984
1134
|
* ```
|
|
1135
|
+
*
|
|
1136
|
+
* This applies to `script-src`. When you also scope `script` resources or hashes to `script-src-elem` (using `kind: "element"`), `strict-dynamic` is inherited by `script-src-elem` so that dynamically injected `<script>` elements continue to work.
|
|
985
1137
|
*/
|
|
986
1138
|
strictDynamic?: boolean;
|
|
987
1139
|
};
|
|
@@ -1379,7 +1531,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
1379
1531
|
/**
|
|
1380
1532
|
* @docs
|
|
1381
1533
|
* @name logger.entrypoint
|
|
1382
|
-
* @type {string}
|
|
1534
|
+
* @type {string | URL}
|
|
1383
1535
|
* @version 7.0.0
|
|
1384
1536
|
* @description
|
|
1385
1537
|
*
|
|
@@ -2974,6 +3126,35 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
2974
3126
|
* See the [experimental SVG optimization docs](https://docs.astro.build/en/reference/experimental-flags/svg-optimization/) for more information.
|
|
2975
3127
|
*/
|
|
2976
3128
|
svgOptimizer?: SvgOptimizer;
|
|
3129
|
+
/**
|
|
3130
|
+
* @name experimental.collectionStorage
|
|
3131
|
+
* @type {'single-file' | 'chunked'}
|
|
3132
|
+
* @default `'single-file'`
|
|
3133
|
+
* @version 7.1.0
|
|
3134
|
+
* @description
|
|
3135
|
+
*
|
|
3136
|
+
* Controls how Astro persists the content layer data store.
|
|
3137
|
+
*
|
|
3138
|
+
* By default, the entire store is written to a single `data-store.json`
|
|
3139
|
+
* file. For very large content collections, this file can grow large
|
|
3140
|
+
* enough to hit platform file-size limits.
|
|
3141
|
+
*
|
|
3142
|
+
* When set to `'chunked'`, the store is split across many smaller,
|
|
3143
|
+
* content-addressed files so that no single file grows unbounded.
|
|
3144
|
+
*
|
|
3145
|
+
* ```js
|
|
3146
|
+
* import { defineConfig } from 'astro/config';
|
|
3147
|
+
*
|
|
3148
|
+
* export default defineConfig({
|
|
3149
|
+
* experimental: {
|
|
3150
|
+
* collectionStorage: 'chunked',
|
|
3151
|
+
* },
|
|
3152
|
+
* });
|
|
3153
|
+
* ```
|
|
3154
|
+
*
|
|
3155
|
+
* See the [experimental data store chunking documentation](https://docs.astro.build/en/reference/experimental-flags/collection-storage/) for more information.
|
|
3156
|
+
*/
|
|
3157
|
+
collectionStorage?: 'single-file' | 'chunked';
|
|
2977
3158
|
};
|
|
2978
3159
|
}
|
|
2979
3160
|
/**
|