astro 7.0.8 → 7.1.0
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 +37 -8
- 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 +52 -10
- 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/astro-island.js +1 -3
- package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
- package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt.js +1 -1
- 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
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { existsSync, promises as fs } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
2
3
|
import * as devalue from "devalue";
|
|
3
4
|
import { Traverse } from "neotraverse/modern";
|
|
4
5
|
import { imageSrcToImportId, importIdToSymbolName } from "../assets/utils/resolveImports.js";
|
|
5
6
|
import { AstroError, AstroErrorData } from "../core/errors/index.js";
|
|
6
|
-
import { IMAGE_IMPORT_PREFIX } from "./consts.js";
|
|
7
|
+
import { DATA_STORE_MANIFEST_FILE, IMAGE_IMPORT_PREFIX } from "./consts.js";
|
|
8
|
+
import {
|
|
9
|
+
ChunkedWriter,
|
|
10
|
+
FileWriter,
|
|
11
|
+
serializeDataStore
|
|
12
|
+
} from "./data-store-writer.js";
|
|
7
13
|
import { ImmutableDataStore } from "./data-store.js";
|
|
8
14
|
import { contentModuleToId } from "./utils.js";
|
|
9
15
|
const SAVE_DEBOUNCE_MS = 500;
|
|
10
16
|
const MAX_DEPTH = 10;
|
|
11
17
|
class MutableDataStore extends ImmutableDataStore {
|
|
12
|
-
#
|
|
18
|
+
#writer;
|
|
13
19
|
#assetsFile;
|
|
14
20
|
#modulesFile;
|
|
15
21
|
#saveTimeout;
|
|
@@ -201,7 +207,7 @@ ${lines.join(",\n")}]);
|
|
|
201
207
|
clearTimeout(this.#saveTimeout);
|
|
202
208
|
}
|
|
203
209
|
this.#saveTimeout = void 0;
|
|
204
|
-
if (this.#
|
|
210
|
+
if (this.#writer) {
|
|
205
211
|
await this.writeToDisk();
|
|
206
212
|
}
|
|
207
213
|
this.#maybeResolveSavePromise();
|
|
@@ -218,7 +224,7 @@ ${lines.join(",\n")}]);
|
|
|
218
224
|
}
|
|
219
225
|
this.#saveTimeout = setTimeout(async () => {
|
|
220
226
|
this.#saveTimeout = void 0;
|
|
221
|
-
if (this.#
|
|
227
|
+
if (this.#writer) {
|
|
222
228
|
await this.writeToDisk();
|
|
223
229
|
}
|
|
224
230
|
this.#maybeResolveSavePromise();
|
|
@@ -340,19 +346,13 @@ ${lines.join(",\n")}]);
|
|
|
340
346
|
return this.#savePromise;
|
|
341
347
|
}
|
|
342
348
|
toString() {
|
|
343
|
-
|
|
344
|
-
[...this._collections.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([key, collection]) => [
|
|
345
|
-
key,
|
|
346
|
-
new Map([...collection.entries()].sort(([a], [b]) => a.localeCompare(b)))
|
|
347
|
-
])
|
|
348
|
-
);
|
|
349
|
-
return devalue.stringify(sorted);
|
|
349
|
+
return serializeDataStore(this._collections);
|
|
350
350
|
}
|
|
351
351
|
async writeToDisk() {
|
|
352
352
|
if (!this.#dirty) {
|
|
353
353
|
return;
|
|
354
354
|
}
|
|
355
|
-
if (!this.#
|
|
355
|
+
if (!this.#writer) {
|
|
356
356
|
throw new AstroError(AstroErrorData.UnknownFilesystemError);
|
|
357
357
|
}
|
|
358
358
|
if (this.#writeInProgress) {
|
|
@@ -362,7 +362,7 @@ ${lines.join(",\n")}]);
|
|
|
362
362
|
try {
|
|
363
363
|
this.#dirty = false;
|
|
364
364
|
this.#writeInProgress = true;
|
|
365
|
-
await this.#
|
|
365
|
+
await this.#writer.write(this._collections);
|
|
366
366
|
} catch (err) {
|
|
367
367
|
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause: err });
|
|
368
368
|
} finally {
|
|
@@ -400,7 +400,7 @@ ${lines.join(",\n")}]);
|
|
|
400
400
|
if (existsSync(filePath)) {
|
|
401
401
|
const data = await fs.readFile(filePath, "utf-8");
|
|
402
402
|
const store2 = await MutableDataStore.fromString(data);
|
|
403
|
-
store2.#
|
|
403
|
+
store2.#writer = new FileWriter(filePath);
|
|
404
404
|
return store2;
|
|
405
405
|
} else {
|
|
406
406
|
await fs.mkdir(new URL("./", filePath), { recursive: true });
|
|
@@ -408,7 +408,44 @@ ${lines.join(",\n")}]);
|
|
|
408
408
|
} catch {
|
|
409
409
|
}
|
|
410
410
|
const store = new MutableDataStore();
|
|
411
|
-
store.#
|
|
411
|
+
store.#writer = new FileWriter(filePath);
|
|
412
|
+
return store;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Loads a MutableDataStore from a chunked store directory (experimental
|
|
416
|
+
* `collectionStorage: 'chunked'`), reading the manifest and its referenced parts.
|
|
417
|
+
* If the directory has no manifest yet (fresh build) it starts empty. If the
|
|
418
|
+
* manifest exists but can't be read (corrupt cache), it warns and starts
|
|
419
|
+
* empty so loaders rebuild it, rather than failing the sync.
|
|
420
|
+
*/
|
|
421
|
+
static async fromDir(dirPath) {
|
|
422
|
+
const manifestFile = new URL(`./${DATA_STORE_MANIFEST_FILE}`, dirPath);
|
|
423
|
+
if (existsSync(manifestFile)) {
|
|
424
|
+
try {
|
|
425
|
+
const manifestData = await fs.readFile(manifestFile, "utf-8");
|
|
426
|
+
const manifest = JSON.parse(manifestData);
|
|
427
|
+
const expanded = {};
|
|
428
|
+
for (const collectionName in manifest) {
|
|
429
|
+
expanded[collectionName] = await Promise.all(
|
|
430
|
+
manifest[collectionName].map(
|
|
431
|
+
(fileName) => fs.readFile(new URL(`./${fileName}`, dirPath), "utf-8")
|
|
432
|
+
)
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
const map = ImmutableDataStore.manifestToMap(expanded);
|
|
436
|
+
const store2 = await MutableDataStore.fromMap(map);
|
|
437
|
+
store2.#writer = new ChunkedWriter(dirPath);
|
|
438
|
+
return store2;
|
|
439
|
+
} catch (err) {
|
|
440
|
+
console.warn(
|
|
441
|
+
`[content] Could not read the chunked data store at ${fileURLToPath(dirPath)}, rebuilding from scratch.`,
|
|
442
|
+
err
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
447
|
+
const store = new MutableDataStore();
|
|
448
|
+
store.#writer = new ChunkedWriter(dirPath);
|
|
412
449
|
return store;
|
|
413
450
|
}
|
|
414
451
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AstroSettings } from '../types/astro.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get the path to the data store file.
|
|
4
|
+
* During development, this is in the `.astro` directory so that the Vite watcher can see it.
|
|
5
|
+
* In production, it's in the cache directory so that it's preserved between builds.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getDataStoreFile(settings: AstroSettings, isDev: boolean): URL;
|
|
8
|
+
/**
|
|
9
|
+
* Get the path to the data store directory, used when the store is split across
|
|
10
|
+
* multiple files (experimental `collectionStorage: 'chunked'`).
|
|
11
|
+
* During development, this is in the `.astro` directory so that the Vite watcher can see it.
|
|
12
|
+
* In production, it's in the cache directory so that it's preserved between builds.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getDataStoreDir(settings: AstroSettings, isDev: boolean): URL;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DATA_STORE_DIR, DATA_STORE_FILE } from "./consts.js";
|
|
2
|
+
function getDataStoreFile(settings, isDev) {
|
|
3
|
+
return new URL(DATA_STORE_FILE, isDev ? settings.dotAstroDir : settings.config.cacheDir);
|
|
4
|
+
}
|
|
5
|
+
function getDataStoreDir(settings, isDev) {
|
|
6
|
+
return new URL(DATA_STORE_DIR, isDev ? settings.dotAstroDir : settings.config.cacheDir);
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
getDataStoreDir,
|
|
10
|
+
getDataStoreFile
|
|
11
|
+
};
|
package/dist/content/runtime.js
CHANGED
|
@@ -73,10 +73,10 @@ function createGetCollection({
|
|
|
73
73
|
}
|
|
74
74
|
const hasFilter = typeof filter === "function";
|
|
75
75
|
const store = await globalDataStore.get();
|
|
76
|
-
if (store.hasCollection(collection)) {
|
|
76
|
+
if (await store.hasCollection(collection)) {
|
|
77
77
|
const { default: imageAssetMap } = await import("astro:asset-imports");
|
|
78
78
|
const result = [];
|
|
79
|
-
for (const rawEntry of store.values(collection)) {
|
|
79
|
+
for (const rawEntry of await store.values(collection)) {
|
|
80
80
|
const data = updateImageReferencesInData(rawEntry.data, rawEntry.filePath, imageAssetMap);
|
|
81
81
|
let entry = {
|
|
82
82
|
...rawEntry,
|
|
@@ -127,8 +127,8 @@ function createGetEntry({ liveCollections }) {
|
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
const store = await globalDataStore.get();
|
|
130
|
-
if (store.hasCollection(collection)) {
|
|
131
|
-
const entry = store.get(collection, lookupId);
|
|
130
|
+
if (await store.hasCollection(collection)) {
|
|
131
|
+
const entry = await store.get(collection, lookupId);
|
|
132
132
|
if (!entry) {
|
|
133
133
|
console.warn(`Entry ${collection} \u2192 ${lookupId} was not found.`);
|
|
134
134
|
return;
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ASSET_IMPORTS_VIRTUAL_ID,
|
|
14
14
|
CONTENT_MODULE_FLAG,
|
|
15
15
|
CONTENT_RENDER_FLAG,
|
|
16
|
+
DATA_STORE_MANIFEST_FILE,
|
|
16
17
|
DATA_STORE_VIRTUAL_ID,
|
|
17
18
|
MODULES_IMPORTS_FILE,
|
|
18
19
|
MODULES_MJS_ID,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
RESOLVED_VIRTUAL_MODULE_ID,
|
|
22
23
|
VIRTUAL_MODULE_ID
|
|
23
24
|
} from "./consts.js";
|
|
24
|
-
import { getDataStoreFile } from "./
|
|
25
|
+
import { getDataStoreDir, getDataStoreFile } from "./paths.js";
|
|
25
26
|
import { getContentPaths, isDeferredModule } from "./utils.js";
|
|
26
27
|
const LARGE_DATA_STORE_THRESHOLD = 5 * 1024 * 1024;
|
|
27
28
|
function invalidateAssetImports(viteServer, filePath) {
|
|
@@ -43,7 +44,7 @@ function invalidateAssetImports(viteServer, filePath) {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
|
-
function invalidateDataStore(viteServer) {
|
|
47
|
+
function invalidateDataStore(viteServer, { notifyClient = true } = {}) {
|
|
47
48
|
const environment = viteServer.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr];
|
|
48
49
|
const module = environment.moduleGraph.getModuleById(RESOLVED_DATA_STORE_VIRTUAL_ID);
|
|
49
50
|
if (module) {
|
|
@@ -59,15 +60,18 @@ function invalidateDataStore(viteServer) {
|
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
environment.hot.send("astro:content-changed", {});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
if (notifyClient) {
|
|
64
|
+
viteServer.environments.client.hot.send({
|
|
65
|
+
type: "full-reload",
|
|
66
|
+
path: "*"
|
|
67
|
+
});
|
|
68
|
+
}
|
|
66
69
|
}
|
|
67
70
|
function astroContentVirtualModPlugin({
|
|
68
71
|
settings,
|
|
69
72
|
fs
|
|
70
73
|
}) {
|
|
74
|
+
let dataStoreDir;
|
|
71
75
|
let dataStoreFile;
|
|
72
76
|
let devServer;
|
|
73
77
|
let liveConfig;
|
|
@@ -77,7 +81,12 @@ function astroContentVirtualModPlugin({
|
|
|
77
81
|
enforce: "pre",
|
|
78
82
|
config(_, env) {
|
|
79
83
|
isDev = env.command === "serve";
|
|
80
|
-
|
|
84
|
+
if (settings.config.experimental.collectionStorage === "chunked") {
|
|
85
|
+
dataStoreDir = getDataStoreDir(settings, env.command === "serve");
|
|
86
|
+
dataStoreFile = new URL(DATA_STORE_MANIFEST_FILE, dataStoreDir);
|
|
87
|
+
} else {
|
|
88
|
+
dataStoreFile = getDataStoreFile(settings, env.command === "serve");
|
|
89
|
+
}
|
|
81
90
|
const contentPaths = getContentPaths(
|
|
82
91
|
settings.config,
|
|
83
92
|
void 0,
|
|
@@ -92,7 +101,7 @@ function astroContentVirtualModPlugin({
|
|
|
92
101
|
const assetImportsPath = fileURLToPath(new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir));
|
|
93
102
|
devServer.watcher.add(fileURLToPath(dataStoreFile));
|
|
94
103
|
devServer.watcher.add(assetImportsPath);
|
|
95
|
-
invalidateDataStore(devServer);
|
|
104
|
+
invalidateDataStore(devServer, { notifyClient: false });
|
|
96
105
|
invalidateAssetImports(devServer, assetImportsPath);
|
|
97
106
|
}
|
|
98
107
|
},
|
|
@@ -170,6 +179,26 @@ function astroContentVirtualModPlugin({
|
|
|
170
179
|
return { code: "export default new Map()" };
|
|
171
180
|
}
|
|
172
181
|
const jsonData = await fs.promises.readFile(dataStoreFile, "utf-8");
|
|
182
|
+
if (settings.config.experimental.collectionStorage === "chunked") {
|
|
183
|
+
try {
|
|
184
|
+
const manifest = JSON.parse(jsonData);
|
|
185
|
+
const rawImport = (fileName) => {
|
|
186
|
+
const path = rootRelativePath(
|
|
187
|
+
settings.config.root,
|
|
188
|
+
new URL(`./${fileName}`, dataStoreDir)
|
|
189
|
+
);
|
|
190
|
+
return `(await import(${JSON.stringify(`${path}?raw`)}))`;
|
|
191
|
+
};
|
|
192
|
+
const entries = Object.entries(manifest).map(
|
|
193
|
+
([collection, parts]) => `${JSON.stringify(collection)}:[${parts.map(rawImport).join(",")}]`
|
|
194
|
+
);
|
|
195
|
+
const code = `export default{${entries.join(",")}}`;
|
|
196
|
+
return { code, map: { mappings: "" } };
|
|
197
|
+
} catch (err) {
|
|
198
|
+
const message = "Could not parse data store manifest JSON file";
|
|
199
|
+
this.error({ message, id, cause: err });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
173
202
|
try {
|
|
174
203
|
const parsed = JSON.parse(jsonData);
|
|
175
204
|
const useRuntimeJsonParse = isDev && Buffer.byteLength(jsonData) > LARGE_DATA_STORE_THRESHOLD;
|
|
@@ -2,6 +2,7 @@ import { Pipeline } from "../../base-pipeline.js";
|
|
|
2
2
|
import { ASTRO_VERSION } from "../../constants.js";
|
|
3
3
|
import { createModuleScriptElement, createStylesheetElementSet } from "../../render/ssr-element.js";
|
|
4
4
|
import { findRouteToRewrite } from "../../routing/rewrite.js";
|
|
5
|
+
import { stringifyForScript } from "../../../runtime/server/escape.js";
|
|
5
6
|
class NonRunnablePipeline extends Pipeline {
|
|
6
7
|
getName() {
|
|
7
8
|
return "NonRunnablePipeline";
|
|
@@ -73,7 +74,7 @@ class NonRunnablePipeline extends Pipeline {
|
|
|
73
74
|
debugInfo: this.manifest.devToolbar.debugInfoOutput ?? "",
|
|
74
75
|
placement: this.manifest.devToolbar.placement
|
|
75
76
|
};
|
|
76
|
-
const children = `window.__astro_dev_toolbar__ = ${
|
|
77
|
+
const children = `window.__astro_dev_toolbar__ = ${stringifyForScript(additionalMetadata)}`;
|
|
77
78
|
scripts.add({ props: {}, children });
|
|
78
79
|
}
|
|
79
80
|
const { devCSSMap } = await import("virtual:astro:dev-css-all");
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { AstroMiddlewareInstance } from '../../types/public/common.js';
|
|
|
4
4
|
import type { AstroConfig, CspAlgorithm, Locales, RemotePattern } from '../../types/public/config.js';
|
|
5
5
|
import type { RouteData, SSRComponentMetadata, SSRLoadedRenderer, SSRResult } from '../../types/public/internal.js';
|
|
6
6
|
import type { SinglePageBuiltModule } from '../build/types.js';
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
7
|
+
import type { AstroLoggerDestination, AstroLoggerLevel } from '../logger/core.js';
|
|
8
|
+
import type { CspDirective, CspHashEntry, CspResourceEntry } from '../csp/config.js';
|
|
9
9
|
import type { RoutingStrategies } from './common.js';
|
|
10
10
|
import type { CacheProviderFactory, SSRManifestCache } from '../cache/types.js';
|
|
11
11
|
import type { BaseSessionConfig, SessionDriverFactory } from '../session/types.js';
|
|
@@ -91,9 +91,9 @@ export type SSRManifest = {
|
|
|
91
91
|
i18n: SSRManifestI18n | undefined;
|
|
92
92
|
middleware?: () => Promise<AstroMiddlewareInstance> | AstroMiddlewareInstance;
|
|
93
93
|
logger?: () => Promise<{
|
|
94
|
-
default: AstroLoggerDestination
|
|
94
|
+
default: AstroLoggerDestination;
|
|
95
95
|
}> | {
|
|
96
|
-
default: AstroLoggerDestination
|
|
96
|
+
default: AstroLoggerDestination;
|
|
97
97
|
};
|
|
98
98
|
actions?: () => Promise<SSRActions> | SSRActions;
|
|
99
99
|
sessionDriver?: () => Promise<{
|
|
@@ -152,15 +152,49 @@ export type SSRManifestI18n = {
|
|
|
152
152
|
domainLookupTable: Record<string, string>;
|
|
153
153
|
domains: Record<string, string> | undefined;
|
|
154
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* The CSP section of the manifest. It mirrors the `security.csp` config: `directives` plus a
|
|
157
|
+
* `scriptDirective`/`styleDirective`, each holding `resources`/`hashes` entries that carry their
|
|
158
|
+
* `kind` (`default`/`element`/`attribute`). The `kind` is only interpreted at render time. Astro's
|
|
159
|
+
* generated hashes are appended to the relevant `hashes` array as `default`-kind entries.
|
|
160
|
+
*/
|
|
155
161
|
export type SSRManifestCSP = {
|
|
156
162
|
cspDestination: 'adapter' | 'meta' | 'header' | undefined;
|
|
157
163
|
algorithm: CspAlgorithm;
|
|
164
|
+
directives: CspDirective[];
|
|
165
|
+
/**
|
|
166
|
+
* @deprecated Use {@linkcode scriptDirective} instead. Holds the `default`-kind `script-src`
|
|
167
|
+
* hashes (the same values `scriptDirective.hashes` carries with `kind: "default"`).
|
|
168
|
+
*/
|
|
158
169
|
scriptHashes: string[];
|
|
170
|
+
/**
|
|
171
|
+
* @deprecated Use {@linkcode scriptDirective} instead. Holds the `default`-kind `script-src`
|
|
172
|
+
* resources.
|
|
173
|
+
*/
|
|
159
174
|
scriptResources: string[];
|
|
175
|
+
/**
|
|
176
|
+
* @deprecated Use {@linkcode scriptDirective}'s `strictDynamic` instead.
|
|
177
|
+
*/
|
|
160
178
|
isStrictDynamic: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* @deprecated Use {@linkcode styleDirective} instead. Holds the `default`-kind `style-src`
|
|
181
|
+
* hashes.
|
|
182
|
+
*/
|
|
161
183
|
styleHashes: string[];
|
|
184
|
+
/**
|
|
185
|
+
* @deprecated Use {@linkcode styleDirective} instead. Holds the `default`-kind `style-src`
|
|
186
|
+
* resources.
|
|
187
|
+
*/
|
|
162
188
|
styleResources: string[];
|
|
163
|
-
|
|
189
|
+
scriptDirective: {
|
|
190
|
+
resources: CspResourceEntry[];
|
|
191
|
+
hashes: CspHashEntry[];
|
|
192
|
+
strictDynamic: boolean;
|
|
193
|
+
};
|
|
194
|
+
styleDirective: {
|
|
195
|
+
resources: CspResourceEntry[];
|
|
196
|
+
hashes: CspHashEntry[];
|
|
197
|
+
};
|
|
164
198
|
};
|
|
165
199
|
export interface SSRManifestSession extends BaseSessionConfig {
|
|
166
200
|
driver: string;
|
|
@@ -6,7 +6,7 @@ import type { RuntimeMode } from '../types/public/config.js';
|
|
|
6
6
|
import type { RouteData, SSRActions, SSRLoadedRenderer, SSRManifest, SSRResult } from '../types/public/internal.js';
|
|
7
7
|
import type { ServerIslandMappings } from './app/types.js';
|
|
8
8
|
import type { SinglePageBuiltModule } from './build/types.js';
|
|
9
|
-
import
|
|
9
|
+
import { AstroLogger } from './logger/core.js';
|
|
10
10
|
import { RouteCache } from './render/route-cache.js';
|
|
11
11
|
import { type DefaultRouteParams } from './routing/default.js';
|
|
12
12
|
import type { CacheProvider, CacheProviderFactory } from './cache/types.js';
|
|
@@ -2,6 +2,7 @@ import { NOOP_ACTIONS_MOD } from "../actions/noop-actions.js";
|
|
|
2
2
|
import { createOriginCheckMiddleware } from "./app/origin-check.js";
|
|
3
3
|
import { ActionNotFoundError } from "./errors/errors-data.js";
|
|
4
4
|
import { AstroError } from "./errors/index.js";
|
|
5
|
+
import { AstroLogger } from "./logger/core.js";
|
|
5
6
|
import { NOOP_MIDDLEWARE_FN } from "./middleware/noop-middleware.js";
|
|
6
7
|
import { sequence } from "./middleware/sequence.js";
|
|
7
8
|
import { RedirectSinglePageBuiltModule } from "./redirects/index.js";
|
|
@@ -10,7 +11,7 @@ import { createDefaultRoutes } from "./routing/default.js";
|
|
|
10
11
|
import { ensure404Route } from "./routing/astro-designed-error-pages.js";
|
|
11
12
|
import { Router } from "./routing/router.js";
|
|
12
13
|
import { FORBIDDEN_PATH_KEYS } from "@astrojs/internal-helpers/object";
|
|
13
|
-
import {
|
|
14
|
+
import { loadLoggerDestination } from "./logger/load.js";
|
|
14
15
|
const PipelineFeatures = {
|
|
15
16
|
redirects: 1 << 0,
|
|
16
17
|
sessions: 1 << 1,
|
|
@@ -171,7 +172,10 @@ class Pipeline {
|
|
|
171
172
|
}
|
|
172
173
|
this.resolvedLogger = true;
|
|
173
174
|
if (this.manifest.loggerConfig) {
|
|
174
|
-
this.logger =
|
|
175
|
+
this.logger = new AstroLogger({
|
|
176
|
+
destination: await loadLoggerDestination(this.manifest.loggerConfig),
|
|
177
|
+
level: this.manifest.logLevel
|
|
178
|
+
});
|
|
175
179
|
}
|
|
176
180
|
return this.logger;
|
|
177
181
|
}
|
package/dist/core/build/index.js
CHANGED
|
@@ -24,13 +24,14 @@ import { ensureProcessNodeEnv } from "../util.js";
|
|
|
24
24
|
import { collectPagesData } from "./page-data.js";
|
|
25
25
|
import { viteBuild } from "./static-build.js";
|
|
26
26
|
import { getTimeStat } from "./util.js";
|
|
27
|
-
import { warnIfCspWithShiki } from "../messages/runtime.js";
|
|
27
|
+
import { warnIfCspResourceFallbackShadowing, warnIfCspWithShiki } from "../messages/runtime.js";
|
|
28
28
|
async function build(inlineConfig, options = {}) {
|
|
29
29
|
ensureProcessNodeEnv(options.devOutput ? "development" : "production");
|
|
30
30
|
const { userConfig, astroConfig } = await resolveConfig(inlineConfig, "build");
|
|
31
31
|
const logger = await loadOrCreateNodeLogger(astroConfig, inlineConfig ?? {});
|
|
32
32
|
telemetry.record(eventCliSession("build", userConfig));
|
|
33
33
|
warnIfCspWithShiki(astroConfig, logger);
|
|
34
|
+
warnIfCspResourceFallbackShadowing(astroConfig, logger);
|
|
34
35
|
const settings = await createSettings(
|
|
35
36
|
astroConfig,
|
|
36
37
|
inlineConfig.logLevel,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
trackScriptHashes,
|
|
21
21
|
trackStyleHashes
|
|
22
22
|
} from "../../csp/common.js";
|
|
23
|
+
import { partitionByKind } from "../../csp/runtime.js";
|
|
23
24
|
import { encodeKey } from "../../encryption.js";
|
|
24
25
|
import { fileExtension, joinPaths, prependForwardSlash } from "../../path.js";
|
|
25
26
|
import { DEFAULT_COMPONENTS } from "../../routing/default.js";
|
|
@@ -192,25 +193,39 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
192
193
|
}
|
|
193
194
|
let csp = void 0;
|
|
194
195
|
if (shouldTrackCspHashes(settings.config.security.csp)) {
|
|
195
|
-
const
|
|
196
|
+
const cspConfig = settings.config.security.csp;
|
|
197
|
+
const algorithm = getAlgorithm(cspConfig);
|
|
196
198
|
const scriptHashes = [
|
|
197
|
-
...getScriptHashes(
|
|
199
|
+
...getScriptHashes(cspConfig),
|
|
198
200
|
...await trackScriptHashes(internals, settings, algorithm)
|
|
199
201
|
];
|
|
200
202
|
const styleHashes = [
|
|
201
|
-
...getStyleHashes(
|
|
203
|
+
...getStyleHashes(cspConfig),
|
|
202
204
|
...settings.injectedCsp.styleHashes,
|
|
203
205
|
...await trackStyleHashes(internals, settings, algorithm)
|
|
204
206
|
];
|
|
207
|
+
const scriptDirective = {
|
|
208
|
+
resources: getScriptResources(cspConfig),
|
|
209
|
+
hashes: scriptHashes,
|
|
210
|
+
strictDynamic: getStrictDynamic(cspConfig)
|
|
211
|
+
};
|
|
212
|
+
const styleDirective = {
|
|
213
|
+
resources: getStyleResources(cspConfig),
|
|
214
|
+
hashes: styleHashes
|
|
215
|
+
};
|
|
216
|
+
const scriptDefault = partitionByKind(scriptDirective).default;
|
|
217
|
+
const styleDefault = partitionByKind(styleDirective).default;
|
|
205
218
|
csp = {
|
|
206
219
|
cspDestination: settings.adapter?.adapterFeatures?.staticHeaders ? "adapter" : void 0,
|
|
207
|
-
scriptHashes,
|
|
208
|
-
scriptResources: getScriptResources(settings.config.security.csp),
|
|
209
|
-
styleHashes,
|
|
210
|
-
styleResources: getStyleResources(settings.config.security.csp),
|
|
211
220
|
algorithm,
|
|
212
221
|
directives: getDirectives(settings),
|
|
213
|
-
|
|
222
|
+
scriptHashes: scriptDefault.hashes,
|
|
223
|
+
scriptResources: scriptDefault.resources,
|
|
224
|
+
isStrictDynamic: scriptDirective.strictDynamic,
|
|
225
|
+
styleHashes: styleDefault.hashes,
|
|
226
|
+
styleResources: styleDefault.resources,
|
|
227
|
+
scriptDirective,
|
|
228
|
+
styleDirective
|
|
214
229
|
};
|
|
215
230
|
}
|
|
216
231
|
let internalFetchHeaders = void 0;
|
|
@@ -80,6 +80,7 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
|
|
|
80
80
|
clientPrerender: false;
|
|
81
81
|
contentIntellisense: false;
|
|
82
82
|
chromeDevtoolsWorkspace: false;
|
|
83
|
+
collectionStorage: "single-file";
|
|
83
84
|
};
|
|
84
85
|
};
|
|
85
86
|
export declare const AstroConfigSchema: z.ZodObject<{
|
|
@@ -368,12 +369,40 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
368
369
|
}>>>;
|
|
369
370
|
directives: z.ZodOptional<z.ZodArray<z.ZodCustom<`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}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`, `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}` | `report-uri${string}` | `require-trusted-types-for${string}` | `sandbox${string}` | `trusted-types${string}` | `upgrade-insecure-requests${string}` | `worker-src${string}`>>>;
|
|
370
371
|
styleDirective: z.ZodOptional<z.ZodObject<{
|
|
371
|
-
resources: z.ZodOptional<z.ZodArray<z.ZodString
|
|
372
|
-
|
|
372
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
373
|
+
resource: z.ZodString;
|
|
374
|
+
kind: z.ZodEnum<{
|
|
375
|
+
default: "default";
|
|
376
|
+
attribute: "attribute";
|
|
377
|
+
element: "element";
|
|
378
|
+
}>;
|
|
379
|
+
}, z.core.$strip>]>>>;
|
|
380
|
+
hashes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>, z.ZodObject<{
|
|
381
|
+
hash: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
382
|
+
kind: z.ZodEnum<{
|
|
383
|
+
default: "default";
|
|
384
|
+
attribute: "attribute";
|
|
385
|
+
element: "element";
|
|
386
|
+
}>;
|
|
387
|
+
}, z.core.$strip>]>>>;
|
|
373
388
|
}, z.core.$strip>>;
|
|
374
389
|
scriptDirective: z.ZodOptional<z.ZodObject<{
|
|
375
|
-
resources: z.ZodOptional<z.ZodArray<z.ZodString
|
|
376
|
-
|
|
390
|
+
resources: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
391
|
+
resource: z.ZodString;
|
|
392
|
+
kind: z.ZodEnum<{
|
|
393
|
+
default: "default";
|
|
394
|
+
attribute: "attribute";
|
|
395
|
+
element: "element";
|
|
396
|
+
}>;
|
|
397
|
+
}, z.core.$strip>]>>>;
|
|
398
|
+
hashes: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>, z.ZodObject<{
|
|
399
|
+
hash: z.ZodCustom<`sha256-${string}` | `sha384-${string}` | `sha512-${string}`, `sha256-${string}` | `sha384-${string}` | `sha512-${string}`>;
|
|
400
|
+
kind: z.ZodEnum<{
|
|
401
|
+
default: "default";
|
|
402
|
+
attribute: "attribute";
|
|
403
|
+
element: "element";
|
|
404
|
+
}>;
|
|
405
|
+
}, z.core.$strip>]>>>;
|
|
377
406
|
strictDynamic: z.ZodOptional<z.ZodBoolean>;
|
|
378
407
|
}, z.core.$strip>>;
|
|
379
408
|
}, z.core.$strip>]>>>;
|
|
@@ -458,7 +487,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
458
487
|
}>>>;
|
|
459
488
|
fetchFile: z.ZodDefault<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
|
|
460
489
|
logger: z.ZodOptional<z.ZodObject<{
|
|
461
|
-
entrypoint: z.ZodString
|
|
490
|
+
entrypoint: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<URL, URL>]>;
|
|
462
491
|
config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
463
492
|
}, z.core.$strip>>;
|
|
464
493
|
fonts: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -524,6 +553,10 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
524
553
|
name: z.ZodString;
|
|
525
554
|
optimize: z.ZodCustom<(contents: string) => string | Promise<string>, (contents: string) => string | Promise<string>>;
|
|
526
555
|
}, z.core.$strip>>;
|
|
556
|
+
collectionStorage: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
557
|
+
"single-file": "single-file";
|
|
558
|
+
chunked: "chunked";
|
|
559
|
+
}>>>;
|
|
527
560
|
}, z.core.$strict>>;
|
|
528
561
|
legacy: z.ZodPrefault<z.ZodObject<{
|
|
529
562
|
collectionsBackwardsCompat: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
@@ -9,7 +9,12 @@ import { FontFamilySchema } from "../../../assets/fonts/config.js";
|
|
|
9
9
|
import { SvgOptimizerSchema } from "../../../assets/svg/config.js";
|
|
10
10
|
import { EnvSchema } from "../../../env/schema.js";
|
|
11
11
|
import { CacheSchema, RouteRulesSchema } from "../../cache/config.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
allowedDirectivesSchema,
|
|
14
|
+
cspAlgorithmSchema,
|
|
15
|
+
cspHashEntrySchema,
|
|
16
|
+
cspResourceEntrySchema
|
|
17
|
+
} from "../../csp/config.js";
|
|
13
18
|
import { SessionSchema } from "../../session/config.js";
|
|
14
19
|
const ASTRO_CONFIG_DEFAULTS = {
|
|
15
20
|
root: ".",
|
|
@@ -68,7 +73,8 @@ const ASTRO_CONFIG_DEFAULTS = {
|
|
|
68
73
|
experimental: {
|
|
69
74
|
clientPrerender: false,
|
|
70
75
|
contentIntellisense: false,
|
|
71
|
-
chromeDevtoolsWorkspace: false
|
|
76
|
+
chromeDevtoolsWorkspace: false,
|
|
77
|
+
collectionStorage: "single-file"
|
|
72
78
|
}
|
|
73
79
|
};
|
|
74
80
|
const highlighterTypesSchema = z.union([z.literal("shiki"), z.literal("prism")]).default(syntaxHighlightDefaults.type);
|
|
@@ -304,12 +310,12 @@ const AstroConfigSchema = z.object({
|
|
|
304
310
|
algorithm: cspAlgorithmSchema,
|
|
305
311
|
directives: z.array(allowedDirectivesSchema).optional(),
|
|
306
312
|
styleDirective: z.object({
|
|
307
|
-
resources: z.array(
|
|
308
|
-
hashes: z.array(
|
|
313
|
+
resources: z.array(cspResourceEntrySchema).optional(),
|
|
314
|
+
hashes: z.array(cspHashEntrySchema).optional()
|
|
309
315
|
}).optional(),
|
|
310
316
|
scriptDirective: z.object({
|
|
311
|
-
resources: z.array(
|
|
312
|
-
hashes: z.array(
|
|
317
|
+
resources: z.array(cspResourceEntrySchema).optional(),
|
|
318
|
+
hashes: z.array(cspHashEntrySchema).optional(),
|
|
313
319
|
strictDynamic: z.boolean().optional()
|
|
314
320
|
}).optional()
|
|
315
321
|
})
|
|
@@ -323,7 +329,7 @@ const AstroConfigSchema = z.object({
|
|
|
323
329
|
prerenderConflictBehavior: z.enum(["error", "warn", "ignore"]).optional().default(ASTRO_CONFIG_DEFAULTS.prerenderConflictBehavior),
|
|
324
330
|
fetchFile: z.string().nullable().optional().default(ASTRO_CONFIG_DEFAULTS.fetchFile),
|
|
325
331
|
logger: z.object({
|
|
326
|
-
entrypoint: z.string(),
|
|
332
|
+
entrypoint: z.union([z.string(), z.instanceof(URL)]),
|
|
327
333
|
config: z.record(z.string(), z.any()).optional()
|
|
328
334
|
}).optional(),
|
|
329
335
|
fonts: z.array(FontFamilySchema).optional(),
|
|
@@ -333,7 +339,8 @@ const AstroConfigSchema = z.object({
|
|
|
333
339
|
clientPrerender: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.clientPrerender),
|
|
334
340
|
contentIntellisense: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.contentIntellisense),
|
|
335
341
|
chromeDevtoolsWorkspace: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.chromeDevtoolsWorkspace),
|
|
336
|
-
svgOptimizer: SvgOptimizerSchema.optional()
|
|
342
|
+
svgOptimizer: SvgOptimizerSchema.optional(),
|
|
343
|
+
collectionStorage: z.enum(["single-file", "chunked"]).optional().default(ASTRO_CONFIG_DEFAULTS.experimental.collectionStorage)
|
|
337
344
|
}).prefault({}),
|
|
338
345
|
legacy: z.object({
|
|
339
346
|
collectionsBackwardsCompat: z.boolean().optional().default(false)
|