astro 7.2.9 → 7.3.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/build/generate.d.ts +1 -1
- package/dist/assets/build/generate.js +3 -1
- package/dist/assets/endpoint/dev.js +6 -5
- package/dist/assets/endpoint/generic.js +5 -4
- package/dist/assets/endpoint/node.js +3 -3
- package/dist/assets/endpoint/shared.d.ts +3 -1
- package/dist/assets/endpoint/shared.js +9 -3
- package/dist/assets/fonts/config.d.ts +2 -2
- package/dist/assets/internal.d.ts +2 -1
- package/dist/assets/internal.js +11 -10
- package/dist/assets/services/service.d.ts +8 -7
- package/dist/assets/services/sharp.js +5 -5
- package/dist/assets/vite-plugin-assets.js +22 -5
- package/dist/cli/add/index.js +3 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/cli/preferences/index.js +32 -30
- package/dist/cli/preview/index.js +44 -1
- package/dist/cli/telemetry/index.d.ts +2 -1
- package/dist/cli/telemetry/index.js +2 -2
- package/dist/content/content-layer.js +3 -3
- package/dist/content/data-store-writer.d.ts +18 -5
- package/dist/content/data-store-writer.js +11 -3
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +5 -1
- package/dist/content/mutable-data-store.d.ts +13 -1
- package/dist/content/mutable-data-store.js +35 -5
- package/dist/content/runtime.d.ts +8 -3
- package/dist/content/runtime.js +43 -32
- package/dist/content/types-generator.js +2 -1
- package/dist/content/utils.d.ts +5 -35
- package/dist/content/utils.js +71 -65
- package/dist/content/vite-plugin-content-imports.js +2 -1
- package/dist/content/vite-plugin-content-virtual-mod.d.ts +11 -1
- package/dist/content/vite-plugin-content-virtual-mod.js +36 -3
- package/dist/core/app/entrypoints/index.d.ts +4 -2
- package/dist/core/app/entrypoints/index.js +13 -11
- package/dist/core/app/entrypoints/virtual/dev.js +2 -2
- package/dist/core/app/prerender.d.ts +32 -0
- package/dist/core/app/prerender.js +22 -0
- package/dist/core/build/default-prerenderer.js +5 -2
- package/dist/core/build/generate.d.ts +3 -1
- package/dist/core/build/generate.js +40 -62
- package/dist/core/build/plugins/plugin-manifest.js +1 -1
- package/dist/core/cache/handler.js +12 -1
- package/dist/core/cache/memory-provider.js +35 -8
- package/dist/core/cache/runtime/cache.js +3 -0
- package/dist/core/cache/types.d.ts +2 -0
- package/dist/core/config/schemas/base.d.ts +5 -5
- package/dist/core/config/schemas/relative.d.ts +7 -7
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.d.ts +2 -1
- package/dist/core/cookies/cookies.js +5 -4
- package/dist/core/dev/dev.js +5 -3
- package/dist/core/fetch/fetch-state.d.ts +1 -1
- package/dist/core/fetch/fetch-state.js +4 -23
- package/dist/core/logger/core.d.ts +2 -0
- package/dist/core/logger/core.js +14 -0
- package/dist/core/logger/vite-plugin.d.ts +13 -2
- package/dist/core/logger/vite-plugin.js +8 -7
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/middleware/index.js +14 -1
- package/dist/core/render-scope/collect.d.ts +24 -0
- package/dist/core/render-scope/collect.js +27 -0
- package/dist/core/render-scope/node-scope.d.ts +10 -0
- package/dist/core/render-scope/node-scope.js +8 -0
- package/dist/core/render-scope/record.d.ts +14 -0
- package/dist/core/render-scope/record.js +12 -0
- package/dist/core/render-scope/scope.d.ts +38 -0
- package/dist/core/render-scope/scope.js +28 -0
- package/dist/core/rewrites/handler.js +1 -1
- package/dist/core/routing/create-manifest.js +5 -1
- package/dist/core/server-islands/endpoint.js +4 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +2 -2
- package/dist/core/sync/index.js +1 -1
- package/dist/core/util.d.ts +0 -9
- package/dist/core/util.js +0 -34
- package/dist/core/viteUtils.d.ts +1 -13
- package/dist/core/viteUtils.js +3 -33
- package/dist/types/public/integrations.d.ts +20 -13
- package/dist/vite-plugin-app/createAstroServerApp.js +1 -1
- package/dist/vite-plugin-routes/index.js +22 -8
- package/package.json +6 -6
- package/templates/content/module.mjs +13 -5
- package/dist/core/build/incremental-content-collector.d.ts +0 -10
- package/dist/core/build/incremental-content-collector.js +0 -33
- package/dist/core/build/incremental-image-collector.d.ts +0 -11
- package/dist/core/build/incremental-image-collector.js +0 -32
|
@@ -89,7 +89,17 @@ function getPathFromCacheKey(key, queryConfig) {
|
|
|
89
89
|
const url = new URL(urlPart);
|
|
90
90
|
return `${url.pathname}${buildQueryString(url, queryConfig)}`;
|
|
91
91
|
}
|
|
92
|
-
const IGNORED_VARY_HEADERS = /* @__PURE__ */ new Set(["
|
|
92
|
+
const IGNORED_VARY_HEADERS = /* @__PURE__ */ new Set(["set-cookie"]);
|
|
93
|
+
function getUncacheableVaryHeader(response) {
|
|
94
|
+
const vary = response.headers.get("Vary");
|
|
95
|
+
if (!vary) return void 0;
|
|
96
|
+
for (const header of vary.split(",")) {
|
|
97
|
+
const normalized = header.trim().toLowerCase();
|
|
98
|
+
if (normalized === "cookie") return "Cookie";
|
|
99
|
+
if (normalized === "*") return "*";
|
|
100
|
+
}
|
|
101
|
+
return void 0;
|
|
102
|
+
}
|
|
93
103
|
function parseVaryHeader(response) {
|
|
94
104
|
const vary = response.headers.get("Vary");
|
|
95
105
|
if (!vary || vary.trim() === "*") return void 0;
|
|
@@ -118,9 +128,14 @@ function hasSetCookieHeader(response) {
|
|
|
118
128
|
if (response.headers.has("set-cookie")) return true;
|
|
119
129
|
return hasAtLeastOneCookie(getCookiesFromResponse(response));
|
|
120
130
|
}
|
|
121
|
-
function warnSkippedSetCookie(url) {
|
|
122
|
-
|
|
123
|
-
`
|
|
131
|
+
function warnSkippedSetCookie(logger, url) {
|
|
132
|
+
logger.warn(
|
|
133
|
+
`Skipping cache for ${url.pathname}${url.search} because response includes Set-Cookie.`
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
function warnSkippedVary(logger, url, header) {
|
|
137
|
+
logger.warn(
|
|
138
|
+
`Skipping cache for ${url.pathname}${url.search} because response includes Vary: ${header}.`
|
|
124
139
|
);
|
|
125
140
|
}
|
|
126
141
|
class LRUMap {
|
|
@@ -232,7 +247,13 @@ const memoryProvider = ((config) => {
|
|
|
232
247
|
const { maxAge: newMaxAge, swr: newSwr } = parseCdnCacheControl(cdnCC2);
|
|
233
248
|
if (newMaxAge > 0) {
|
|
234
249
|
if (hasSetCookieHeader(freshResponse)) {
|
|
235
|
-
warnSkippedSetCookie(requestUrl);
|
|
250
|
+
warnSkippedSetCookie(context.logger, requestUrl);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const uncacheableVary = getUncacheableVaryHeader(freshResponse);
|
|
254
|
+
if (uncacheableVary) {
|
|
255
|
+
cache.delete(key);
|
|
256
|
+
warnSkippedVary(context.logger, requestUrl, uncacheableVary);
|
|
236
257
|
return;
|
|
237
258
|
}
|
|
238
259
|
const newTags = parseCacheTags(freshResponse.headers.get("Cache-Tag"));
|
|
@@ -249,8 +270,8 @@ const memoryProvider = ((config) => {
|
|
|
249
270
|
cache.set(key, newEntry);
|
|
250
271
|
}
|
|
251
272
|
}).catch((error) => {
|
|
252
|
-
|
|
253
|
-
`
|
|
273
|
+
context.logger.warn(
|
|
274
|
+
`Background revalidation failed for ${requestUrl.pathname}${requestUrl.search}: ${String(
|
|
254
275
|
error
|
|
255
276
|
)}`
|
|
256
277
|
);
|
|
@@ -266,7 +287,13 @@ const memoryProvider = ((config) => {
|
|
|
266
287
|
const { maxAge, swr } = parseCdnCacheControl(cdnCC);
|
|
267
288
|
if (maxAge > 0) {
|
|
268
289
|
if (hasSetCookieHeader(response)) {
|
|
269
|
-
warnSkippedSetCookie(requestUrl);
|
|
290
|
+
warnSkippedSetCookie(context.logger, requestUrl);
|
|
291
|
+
return response;
|
|
292
|
+
}
|
|
293
|
+
const uncacheableVary = getUncacheableVaryHeader(response);
|
|
294
|
+
if (uncacheableVary) {
|
|
295
|
+
cache.delete(key);
|
|
296
|
+
warnSkippedVary(context.logger, requestUrl, uncacheableVary);
|
|
270
297
|
return response;
|
|
271
298
|
}
|
|
272
299
|
const tags = parseCacheTags(response.headers.get("Cache-Tag"));
|
|
@@ -75,6 +75,9 @@ class AstroCache {
|
|
|
75
75
|
for (const [key, value] of headers) {
|
|
76
76
|
response.headers.set(key, value);
|
|
77
77
|
}
|
|
78
|
+
if (!response.headers.has("Cache-Control") && !response.headers.has("Expires") && (response.headers.has("Last-Modified") || response.headers.has("ETag"))) {
|
|
79
|
+
response.headers.set("Cache-Control", "no-cache");
|
|
80
|
+
}
|
|
78
81
|
}
|
|
79
82
|
/** @internal */
|
|
80
83
|
get [IS_ACTIVE]() {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { MiddlewareNext } from '../../types/public/common.js';
|
|
2
|
+
import type { AstroRuntimeLogger } from '../../types/public/context.js';
|
|
2
3
|
import type { WaitUntilHook } from '../wait-until.js';
|
|
3
4
|
export interface CacheOptions {
|
|
4
5
|
maxAge?: number;
|
|
@@ -27,6 +28,7 @@ export interface CacheProvider {
|
|
|
27
28
|
request: Request;
|
|
28
29
|
url: URL;
|
|
29
30
|
waitUntil?: WaitUntilHook;
|
|
31
|
+
logger: AstroRuntimeLogger;
|
|
30
32
|
}, next: MiddlewareNext): Promise<Response>;
|
|
31
33
|
invalidate(options: InvalidateOptions): Promise<void>;
|
|
32
34
|
}
|
|
@@ -34,10 +34,10 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
34
34
|
name: z.ZodString;
|
|
35
35
|
hooks: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
|
|
36
36
|
}, z.core.$strip>>;
|
|
37
|
-
integrations: z.ZodDefault<z.ZodOptional<z.
|
|
37
|
+
integrations: z.ZodDefault<z.ZodOptional<z.ZodPreprocess<z.ZodArray<z.ZodObject<{
|
|
38
38
|
name: z.ZodString;
|
|
39
39
|
hooks: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
|
|
40
|
-
}, z.core.$strip
|
|
40
|
+
}, z.core.$strip>>, unknown>>>;
|
|
41
41
|
build: z.ZodPrefault<z.ZodObject<{
|
|
42
42
|
format: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"file">, z.ZodLiteral<"directory">, z.ZodLiteral<"preserve">]>>>;
|
|
43
43
|
client: z.ZodPipe<z.ZodDefault<z.ZodOptional<z.ZodString>>, z.ZodTransform<URL, string>>;
|
|
@@ -55,13 +55,13 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
55
55
|
}>>>;
|
|
56
56
|
concurrency: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
57
57
|
}, z.core.$strip>>;
|
|
58
|
-
server: z.ZodPrefault<z.
|
|
58
|
+
server: z.ZodPrefault<z.ZodPreprocess<z.ZodObject<{
|
|
59
59
|
open: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean]>>>;
|
|
60
60
|
host: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean]>>>;
|
|
61
61
|
port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
62
62
|
headers: z.ZodOptional<z.ZodCustom<OutgoingHttpHeaders, OutgoingHttpHeaders>>;
|
|
63
63
|
allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodLiteral<true>]>>>;
|
|
64
|
-
}, z.core.$strip
|
|
64
|
+
}, z.core.$strip>, unknown>>;
|
|
65
65
|
redirects: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
66
66
|
status: z.ZodUnion<readonly [z.ZodLiteral<300>, z.ZodLiteral<301>, z.ZodLiteral<302>, z.ZodLiteral<303>, z.ZodLiteral<304>, z.ZodLiteral<307>, z.ZodLiteral<308>]>;
|
|
67
67
|
destination: z.ZodString;
|
|
@@ -456,8 +456,8 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
456
456
|
fallbacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
457
457
|
optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
|
|
458
458
|
display: z.ZodOptional<z.ZodEnum<{
|
|
459
|
-
auto: "auto";
|
|
460
459
|
optional: "optional";
|
|
460
|
+
auto: "auto";
|
|
461
461
|
fallback: "fallback";
|
|
462
462
|
block: "block";
|
|
463
463
|
swap: "swap";
|
|
@@ -10,10 +10,10 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
10
10
|
name: z.ZodString;
|
|
11
11
|
hooks: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
|
|
12
12
|
}, z.core.$strip>>;
|
|
13
|
-
integrations: z.ZodDefault<z.ZodOptional<z.
|
|
13
|
+
integrations: z.ZodDefault<z.ZodOptional<z.ZodPreprocess<z.ZodArray<z.ZodObject<{
|
|
14
14
|
name: z.ZodString;
|
|
15
15
|
hooks: z.ZodDefault<z.ZodObject<{}, z.core.$loose>>;
|
|
16
|
-
}, z.core.$strip
|
|
16
|
+
}, z.core.$strip>>, unknown>>>;
|
|
17
17
|
redirects: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
18
18
|
status: z.ZodUnion<readonly [z.ZodLiteral<300>, z.ZodLiteral<301>, z.ZodLiteral<302>, z.ZodLiteral<303>, z.ZodLiteral<304>, z.ZodLiteral<307>, z.ZodLiteral<308>]>;
|
|
19
19
|
destination: z.ZodString;
|
|
@@ -408,8 +408,8 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
408
408
|
fallbacks: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
409
409
|
optimizedFallbacks: z.ZodOptional<z.ZodBoolean>;
|
|
410
410
|
display: z.ZodOptional<z.ZodEnum<{
|
|
411
|
-
auto: "auto";
|
|
412
411
|
optional: "optional";
|
|
412
|
+
auto: "auto";
|
|
413
413
|
fallback: "fallback";
|
|
414
414
|
block: "block";
|
|
415
415
|
swap: "swap";
|
|
@@ -472,13 +472,13 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
472
472
|
}>>>;
|
|
473
473
|
concurrency: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
474
474
|
}, z.core.$strip>>>;
|
|
475
|
-
server: z.ZodPrefault<z.
|
|
475
|
+
server: z.ZodPrefault<z.ZodPreprocess<z.ZodObject<{
|
|
476
476
|
open: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean]>>>;
|
|
477
477
|
host: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean]>>>;
|
|
478
478
|
port: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
479
479
|
headers: z.ZodOptional<z.ZodCustom<OutgoingHttpHeaders, OutgoingHttpHeaders>>;
|
|
480
480
|
allowedHosts: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodArray<z.ZodString>, z.ZodLiteral<true>]>>>;
|
|
481
|
-
}, z.core.$strip
|
|
481
|
+
}, z.core.$strip>, unknown>>;
|
|
482
482
|
}, z.core.$strip>, z.ZodTransform<{
|
|
483
483
|
base: string;
|
|
484
484
|
trailingSlash: "never" | "ignore" | "always";
|
|
@@ -727,7 +727,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
727
727
|
formats?: ["woff2" | "woff" | "otf" | "ttf" | "eot", ...("woff2" | "woff" | "otf" | "ttf" | "eot")[]] | undefined;
|
|
728
728
|
fallbacks?: string[] | undefined;
|
|
729
729
|
optimizedFallbacks?: boolean | undefined;
|
|
730
|
-
display?: "
|
|
730
|
+
display?: "optional" | "auto" | "fallback" | "block" | "swap" | undefined;
|
|
731
731
|
stretch?: string | undefined;
|
|
732
732
|
featureSettings?: string | undefined;
|
|
733
733
|
variationSettings?: string | undefined;
|
|
@@ -994,7 +994,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
994
994
|
formats?: ["woff2" | "woff" | "otf" | "ttf" | "eot", ...("woff2" | "woff" | "otf" | "ttf" | "eot")[]] | undefined;
|
|
995
995
|
fallbacks?: string[] | undefined;
|
|
996
996
|
optimizedFallbacks?: boolean | undefined;
|
|
997
|
-
display?: "
|
|
997
|
+
display?: "optional" | "auto" | "fallback" | "block" | "swap" | undefined;
|
|
998
998
|
stretch?: string | undefined;
|
|
999
999
|
featureSettings?: string | undefined;
|
|
1000
1000
|
variationSettings?: string | undefined;
|
package/dist/core/constants.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SerializeOptions } from 'cookie';
|
|
2
|
+
import type { AstroLogger } from '../logger/core.js';
|
|
2
3
|
export type AstroCookieSetOptions = Pick<SerializeOptions, 'domain' | 'path' | 'expires' | 'maxAge' | 'httpOnly' | 'sameSite' | 'secure' | 'encode' | 'partitioned'>;
|
|
3
4
|
export interface AstroCookieGetOptions {
|
|
4
5
|
decode?: (value: string) => string;
|
|
@@ -25,7 +26,7 @@ declare class AstroCookie implements AstroCookieInterface {
|
|
|
25
26
|
}
|
|
26
27
|
declare class AstroCookies implements AstroCookiesInterface {
|
|
27
28
|
#private;
|
|
28
|
-
constructor(request: Request);
|
|
29
|
+
constructor(request: Request, logger: Pick<AstroLogger, 'warn'>);
|
|
29
30
|
/**
|
|
30
31
|
* Astro.cookies.delete(key) is used to delete a cookie. Using this method will result
|
|
31
32
|
* in a Set-Cookie header added to the response.
|
|
@@ -29,11 +29,13 @@ class AstroCookies {
|
|
|
29
29
|
#requestValues;
|
|
30
30
|
#outgoing;
|
|
31
31
|
#consumed;
|
|
32
|
-
|
|
32
|
+
#logger;
|
|
33
|
+
constructor(request, logger) {
|
|
33
34
|
this.#request = request;
|
|
34
35
|
this.#requestValues = null;
|
|
35
36
|
this.#outgoing = null;
|
|
36
37
|
this.#consumed = false;
|
|
38
|
+
this.#logger = logger;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Astro.cookies.delete(key) is used to delete a cookie. Using this method will result
|
|
@@ -112,11 +114,10 @@ class AstroCookies {
|
|
|
112
114
|
*/
|
|
113
115
|
set(key, value, options) {
|
|
114
116
|
if (this.#consumed) {
|
|
115
|
-
|
|
117
|
+
this.#logger.warn(
|
|
118
|
+
"SKIP_FORMAT",
|
|
116
119
|
"Astro.cookies.set() was called after the cookies had already been sent to the browser.\nThis may have happened if this method was called in an imported component.\nPlease make sure that Astro.cookies.set() is only called in the frontmatter of the main page."
|
|
117
120
|
);
|
|
118
|
-
warning.name = "Warning";
|
|
119
|
-
console.warn(warning);
|
|
120
121
|
}
|
|
121
122
|
let serializedValue;
|
|
122
123
|
if (typeof value === "string") {
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -4,7 +4,7 @@ import colors from "piccolore";
|
|
|
4
4
|
import { gt, major, minor, patch } from "semver";
|
|
5
5
|
import { getDataStoreChunkSize, getDataStoreDir, getDataStoreFile } from "../../content/paths.js";
|
|
6
6
|
import { globalContentLayer } from "../../content/instance.js";
|
|
7
|
-
import { attachContentServerListeners } from "../../content/index.js";
|
|
7
|
+
import { attachContentServerListeners, attachDataStoreInvalidation } from "../../content/index.js";
|
|
8
8
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
9
9
|
import { globalContentConfigObserver } from "../../content/utils.js";
|
|
10
10
|
import { telemetry } from "../../events/index.js";
|
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "7.
|
|
29
|
+
const currentVersion = "7.3.0";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -59,7 +59,7 @@ async function dev(inlineConfig) {
|
|
|
59
59
|
const chunkSize = getDataStoreChunkSize(restart.container.settings);
|
|
60
60
|
if (chunkSize !== void 0) {
|
|
61
61
|
const dataStoreDir = getDataStoreDir(restart.container.settings, true);
|
|
62
|
-
store = await MutableDataStore.fromDir(dataStoreDir, chunkSize);
|
|
62
|
+
store = await MutableDataStore.fromDir(dataStoreDir, chunkSize, logger);
|
|
63
63
|
} else {
|
|
64
64
|
const dataStoreFile = getDataStoreFile(restart.container.settings, true);
|
|
65
65
|
store = await MutableDataStore.fromFile(dataStoreFile);
|
|
@@ -69,6 +69,8 @@ async function dev(inlineConfig) {
|
|
|
69
69
|
}
|
|
70
70
|
if (!store) {
|
|
71
71
|
logger.error("content", "Failed to create data store");
|
|
72
|
+
} else {
|
|
73
|
+
attachDataStoreInvalidation(store, restart.container.viteServer, restart.container.settings);
|
|
72
74
|
}
|
|
73
75
|
await attachContentServerListeners(restart.container);
|
|
74
76
|
const config = globalContentConfigObserver.get();
|
|
@@ -7,7 +7,7 @@ import { AstroCookies } from '../cookies/index.js';
|
|
|
7
7
|
import type { RenderErrorOptions, ResolvedRenderOptions } from '../app/base.js';
|
|
8
8
|
import type { SSRManifest } from '../app/types.js';
|
|
9
9
|
import { type RequestLogPayload } from '../environment/index.js';
|
|
10
|
-
import type
|
|
10
|
+
import { type AstroLogger } from '../logger/core.js';
|
|
11
11
|
/**
|
|
12
12
|
* Per-render facade inputs passed by `BaseApp.render`'s fast path to the
|
|
13
13
|
* internal `FetchState` constructor and stored as plain state fields.
|
|
@@ -35,6 +35,7 @@ import { getRenderOptions } from "../app/render-options.js";
|
|
|
35
35
|
import { getFirstForwardedValue, validateForwardedHeaders } from "../app/validate-headers.js";
|
|
36
36
|
import { getEnvironment } from "../environment/index.js";
|
|
37
37
|
import { getLogger } from "../logger/manifest-logger.js";
|
|
38
|
+
import { astroToRuntimeLogger } from "../logger/core.js";
|
|
38
39
|
import { getSite } from "../manifest/derived.js";
|
|
39
40
|
import { getRouteCache } from "../render/route-cache.js";
|
|
40
41
|
import { getRouteTable, matchAllRoutes, matchRoute } from "../routing/route-table.js";
|
|
@@ -232,7 +233,7 @@ class FetchState {
|
|
|
232
233
|
this.clientAddress = options?.clientAddress;
|
|
233
234
|
this.locals = options?.locals ?? {};
|
|
234
235
|
this.url = url;
|
|
235
|
-
this.cookies = new AstroCookies(request);
|
|
236
|
+
this.cookies = new AstroCookies(request, this.logger);
|
|
236
237
|
if (manifest.allowedDomains && manifest.allowedDomains.length > 0 && !this.routeData?.prerender) {
|
|
237
238
|
this.#applyForwardedHeaders();
|
|
238
239
|
}
|
|
@@ -441,17 +442,7 @@ class FetchState {
|
|
|
441
442
|
return state.getCsp();
|
|
442
443
|
},
|
|
443
444
|
get logger() {
|
|
444
|
-
return
|
|
445
|
-
info(msg) {
|
|
446
|
-
logger.info(null, msg);
|
|
447
|
-
},
|
|
448
|
-
warn(msg) {
|
|
449
|
-
logger.warn(null, msg);
|
|
450
|
-
},
|
|
451
|
-
error(msg) {
|
|
452
|
-
logger.error(null, msg);
|
|
453
|
-
}
|
|
454
|
-
};
|
|
445
|
+
return astroToRuntimeLogger(logger);
|
|
455
446
|
}
|
|
456
447
|
};
|
|
457
448
|
this.defineProviderGetters(partial);
|
|
@@ -906,17 +897,7 @@ class FetchState {
|
|
|
906
897
|
return state.getCsp();
|
|
907
898
|
},
|
|
908
899
|
get logger() {
|
|
909
|
-
return
|
|
910
|
-
info(msg) {
|
|
911
|
-
state.logger.info(null, msg);
|
|
912
|
-
},
|
|
913
|
-
warn(msg) {
|
|
914
|
-
state.logger.warn(null, msg);
|
|
915
|
-
},
|
|
916
|
-
error(msg) {
|
|
917
|
-
state.logger.error(null, msg);
|
|
918
|
-
}
|
|
919
|
-
};
|
|
900
|
+
return astroToRuntimeLogger(state.logger);
|
|
920
901
|
}
|
|
921
902
|
};
|
|
922
903
|
this.defineProviderGetters(ctx);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AstroRuntimeLogger } from '../../types/public/context.js';
|
|
1
2
|
export interface AstroLoggerDestination {
|
|
2
3
|
/**
|
|
3
4
|
* It receives a message and writes it into a destination
|
|
@@ -109,4 +110,5 @@ export declare class AstroIntegrationLogger {
|
|
|
109
110
|
*/
|
|
110
111
|
close(): void;
|
|
111
112
|
}
|
|
113
|
+
export declare function astroToRuntimeLogger(logger: AstroLogger): AstroRuntimeLogger;
|
|
112
114
|
export {};
|
package/dist/core/logger/core.js
CHANGED
|
@@ -186,9 +186,23 @@ class AstroIntegrationLogger {
|
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
function astroToRuntimeLogger(logger) {
|
|
190
|
+
return {
|
|
191
|
+
info(msg) {
|
|
192
|
+
logger.info(null, msg);
|
|
193
|
+
},
|
|
194
|
+
warn(msg) {
|
|
195
|
+
logger.warn(null, msg);
|
|
196
|
+
},
|
|
197
|
+
error(msg) {
|
|
198
|
+
logger.error(null, msg);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
189
202
|
export {
|
|
190
203
|
AstroIntegrationLogger,
|
|
191
204
|
AstroLogger,
|
|
205
|
+
astroToRuntimeLogger,
|
|
192
206
|
dateTimeFormat,
|
|
193
207
|
debug,
|
|
194
208
|
getEventPrefix,
|
|
@@ -24,7 +24,18 @@ export declare function emitDestination(config: NormalizedLoggerConfig, resolveE
|
|
|
24
24
|
* destinations continue numbering where their parent left off.
|
|
25
25
|
*/
|
|
26
26
|
nameOffset?: number): Promise<EmittedDestination>;
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Emits `virtual:astro:logger`: the configured destination as the default export
|
|
29
|
+
* (`null` when the user configured none) plus the resolved log level.
|
|
30
|
+
*
|
|
31
|
+
* The module is always registered, even without a `logger` config, so that code
|
|
32
|
+
* generated ahead of the user's config — `astro:content`, which is built from a
|
|
33
|
+
* static template — can import it unconditionally. It deliberately imports
|
|
34
|
+
* nothing but the user's destination entrypoint: unlike `virtual:astro:manifest`
|
|
35
|
+
* it is a leaf, so reaching a logger through it cannot pull renderers and pages
|
|
36
|
+
* into an importer's module graph.
|
|
37
|
+
*/
|
|
38
|
+
export declare function vitePluginLogger({ settings }: {
|
|
28
39
|
settings: AstroSettings;
|
|
29
|
-
}): VitePlugin
|
|
40
|
+
}): VitePlugin;
|
|
30
41
|
export {};
|
|
@@ -35,13 +35,8 @@ async function emitDestination(config, resolveEntrypoint, nameOffset = 0) {
|
|
|
35
35
|
}
|
|
36
36
|
return { expression: `${name}(${JSON.stringify(config.config) ?? "undefined"})`, imports };
|
|
37
37
|
}
|
|
38
|
-
function vitePluginLogger({
|
|
39
|
-
settings
|
|
40
|
-
}) {
|
|
38
|
+
function vitePluginLogger({ settings }) {
|
|
41
39
|
const loggerConfig = settings.config.logger;
|
|
42
|
-
if (!loggerConfig) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
40
|
return {
|
|
46
41
|
name: VIRTUAL_LOGGER_ID,
|
|
47
42
|
enforce: "pre",
|
|
@@ -58,6 +53,12 @@ function vitePluginLogger({
|
|
|
58
53
|
id: new RegExp(`^${RESOLVED_VIRTUAL_LOGGER_ID}$`)
|
|
59
54
|
},
|
|
60
55
|
async handler() {
|
|
56
|
+
const level = `export const level = ${JSON.stringify(settings.logLevel)};
|
|
57
|
+
`;
|
|
58
|
+
if (!loggerConfig) {
|
|
59
|
+
return { code: `${level}export default null;
|
|
60
|
+
` };
|
|
61
|
+
}
|
|
61
62
|
const importerPath = fileURLToPath(new URL("package.json", settings.config.root));
|
|
62
63
|
const { expression, imports } = await emitDestination(
|
|
63
64
|
normalizeLoggerConfig(loggerConfig, settings.config.root),
|
|
@@ -65,7 +66,7 @@ function vitePluginLogger({
|
|
|
65
66
|
);
|
|
66
67
|
return {
|
|
67
68
|
code: `${imports.join("\n")}
|
|
68
|
-
export default ${expression};
|
|
69
|
+
${level}export default ${expression};
|
|
69
70
|
`
|
|
70
71
|
};
|
|
71
72
|
}
|
|
@@ -8,8 +8,21 @@ import { DisabledAstroCache } from "../cache/runtime/noop.js";
|
|
|
8
8
|
import { ASTRO_GENERATOR } from "../constants.js";
|
|
9
9
|
import { AstroCookies } from "../cookies/index.js";
|
|
10
10
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
11
|
+
import { getLogger } from "../logger/manifest-logger.js";
|
|
12
|
+
import { tryGetAmbientManifest } from "../manifest/ambient.js";
|
|
11
13
|
import { getOriginPathname } from "../routing/rewrite.js";
|
|
12
14
|
import { sequence } from "./sequence.js";
|
|
15
|
+
function getMiddlewareLogger() {
|
|
16
|
+
const manifest = tryGetAmbientManifest();
|
|
17
|
+
if (manifest) {
|
|
18
|
+
return getLogger(manifest);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
warn(_label, message) {
|
|
22
|
+
console.warn(message);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
13
26
|
function createContext({
|
|
14
27
|
request,
|
|
15
28
|
params = {},
|
|
@@ -27,7 +40,7 @@ function createContext({
|
|
|
27
40
|
return Promise.resolve(new Response(null));
|
|
28
41
|
};
|
|
29
42
|
const context = {
|
|
30
|
-
cookies: new AstroCookies(request),
|
|
43
|
+
cookies: new AstroCookies(request, getMiddlewareLogger()),
|
|
31
44
|
request,
|
|
32
45
|
params,
|
|
33
46
|
site: void 0,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SerializedStaticImage } from '../../assets/types.js';
|
|
2
|
+
import type { AstroLogger } from '../logger/core.js';
|
|
3
|
+
export interface CollectedPrerenderMetadata {
|
|
4
|
+
contentEntryKeys: string[];
|
|
5
|
+
staticImages: SerializedStaticImage[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Runs `fn` inside a fresh per-render collectors store and returns its value
|
|
9
|
+
* together with a snapshot of everything recorded while it ran.
|
|
10
|
+
*
|
|
11
|
+
* When no render scope is installed, collection degrades to *not collecting*:
|
|
12
|
+
* warn once per process, run `fn` bare, and return `metadata: undefined`
|
|
13
|
+
* ("not tracked") — never wrong attribution.
|
|
14
|
+
*
|
|
15
|
+
* Invariant: `fn` must not resolve until all recordable work is done — in
|
|
16
|
+
* practice, until the response body is fully buffered inside `fn`. The
|
|
17
|
+
* snapshot is taken by copy when `fn` resolves, so a late-arriving record (a
|
|
18
|
+
* floating promise carrying the async context past buffering) mutates only the
|
|
19
|
+
* abandoned store, never the returned metadata.
|
|
20
|
+
*/
|
|
21
|
+
export declare function collectPrerenderMetadata<T>(fn: () => Promise<T>, logger: AstroLogger): Promise<{
|
|
22
|
+
value: T;
|
|
23
|
+
metadata: CollectedPrerenderMetadata | undefined;
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getInstalledRenderScope } from "./scope.js";
|
|
2
|
+
let warnedNoScope = false;
|
|
3
|
+
async function collectPrerenderMetadata(fn, logger) {
|
|
4
|
+
const scope = getInstalledRenderScope();
|
|
5
|
+
if (!scope) {
|
|
6
|
+
if (!warnedNoScope) {
|
|
7
|
+
warnedNoScope = true;
|
|
8
|
+
logger.warn(
|
|
9
|
+
"build",
|
|
10
|
+
"A prerenderer requested metadata collection but no render scope is installed; install one with `installRenderScope` from `astro/app` \u2014 incremental metadata will not be collected for prerendered paths."
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return { value: await fn(), metadata: void 0 };
|
|
14
|
+
}
|
|
15
|
+
const store = { contentEntries: /* @__PURE__ */ new Set(), staticImages: [] };
|
|
16
|
+
const value = await scope.run(store, fn);
|
|
17
|
+
return {
|
|
18
|
+
value,
|
|
19
|
+
metadata: {
|
|
20
|
+
contentEntryKeys: [...store.contentEntries],
|
|
21
|
+
staticImages: [...store.staticImages]
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
collectPrerenderMetadata
|
|
27
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RenderCollectorScope } from './scope.js';
|
|
2
|
+
/**
|
|
3
|
+
* Installs (first-wins) an AsyncLocalStorage-backed render scope and returns
|
|
4
|
+
* the installed scope.
|
|
5
|
+
*
|
|
6
|
+
* This module is the ONE static `node:async_hooks` import in core and must be
|
|
7
|
+
* imported ONLY by `core/build/default-prerenderer.ts` — orchestrator-only
|
|
8
|
+
* code that is never bundled into prerender, server, or adapter output.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ensureAsyncRenderScope(): RenderCollectorScope;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SerializedStaticImage } from '../../assets/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Records that a content entry was rendered, keyed by its root-relative
|
|
4
|
+
* `filePath`. No-op when no scope is installed (dev, production SSR,
|
|
5
|
+
* non-incremental builds) or no render is in scope (`getStaticPaths`, module
|
|
6
|
+
* top-level).
|
|
7
|
+
*/
|
|
8
|
+
export declare function recordContentEntryRender(filePath: string | undefined): void;
|
|
9
|
+
/**
|
|
10
|
+
* Records a resolved image transform, dedup hits included, preserving
|
|
11
|
+
* duplicates (array push, not a set — replay depends on every record
|
|
12
|
+
* arriving).
|
|
13
|
+
*/
|
|
14
|
+
export declare function recordStaticImage(image: SerializedStaticImage): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getInstalledRenderScope } from "./scope.js";
|
|
2
|
+
function recordContentEntryRender(filePath) {
|
|
3
|
+
if (!filePath) return;
|
|
4
|
+
getInstalledRenderScope()?.getStore()?.contentEntries?.add(filePath);
|
|
5
|
+
}
|
|
6
|
+
function recordStaticImage(image) {
|
|
7
|
+
getInstalledRenderScope()?.getStore()?.staticImages?.push(image);
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
recordContentEntryRender,
|
|
11
|
+
recordStaticImage
|
|
12
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SerializedStaticImage } from '../../assets/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The per-render store. One instance is created per collecting render and is
|
|
4
|
+
* reachable only through the installed {@link RenderCollectorScope} while that
|
|
5
|
+
* render's async execution is in scope. Fields are optional so record helpers
|
|
6
|
+
* tolerate stores created by a different astro module instance (or version)
|
|
7
|
+
* that only knows a subset of collectors.
|
|
8
|
+
*/
|
|
9
|
+
export interface RenderCollectors {
|
|
10
|
+
/** Root-relative `filePath`s of the content entries rendered. */
|
|
11
|
+
contentEntries?: Set<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Every image transform resolved, dedup hits included; array push,
|
|
14
|
+
* duplicates preserved.
|
|
15
|
+
*/
|
|
16
|
+
staticImages?: SerializedStaticImage[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Structurally satisfied by `AsyncLocalStorage<RenderCollectors>` — deliberate:
|
|
20
|
+
* installing an ALS instance directly IS the only shipped implementation.
|
|
21
|
+
*/
|
|
22
|
+
export interface RenderCollectorScope {
|
|
23
|
+
run<T>(store: RenderCollectors, fn: () => T): T;
|
|
24
|
+
getStore(): RenderCollectors | undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Installs a render scope on the process-wide channel and returns the installed
|
|
28
|
+
* scope. First-wins: when a scope is already installed (possibly by another
|
|
29
|
+
* module instance), the existing scope is returned and the argument discarded,
|
|
30
|
+
* so callers that both awaited an import converge on one scope.
|
|
31
|
+
*/
|
|
32
|
+
export declare function installRenderScope(scope: RenderCollectorScope): RenderCollectorScope;
|
|
33
|
+
/** The installed render scope, or `undefined` when none was installed. */
|
|
34
|
+
export declare function getInstalledRenderScope(): RenderCollectorScope | undefined;
|
|
35
|
+
/** Test-only: remove the installed scope so unit tests can reset the channel. */
|
|
36
|
+
export declare function uninstallRenderScope(): void;
|
|
37
|
+
/** The current render's collectors store, or `undefined` when not collecting. */
|
|
38
|
+
export declare function getRenderCollectors(): RenderCollectors | undefined;
|