astro 5.0.8 → 5.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/client.d.ts +10 -0
- package/dist/actions/plugins.js +6 -6
- package/dist/assets/build/generate.js +52 -20
- package/dist/assets/build/remote.d.ts +22 -0
- package/dist/assets/build/remote.js +37 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/content/content-layer.js +22 -6
- package/dist/content/utils.d.ts +1 -0
- package/dist/content/utils.js +23 -1
- package/dist/core/app/index.js +9 -0
- package/dist/core/app/types.d.ts +2 -1
- package/dist/core/build/plugins/plugin-manifest.js +8 -2
- package/dist/core/build/static-build.js +2 -3
- package/dist/core/config/schema.d.ts +312 -0
- package/dist/core/config/schema.js +21 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/errors-data.d.ts +26 -0
- package/dist/core/errors/errors-data.js +14 -0
- package/dist/core/messages.js +2 -2
- package/dist/core/render-context.d.ts +2 -0
- package/dist/core/render-context.js +8 -4
- package/dist/core/session.d.ts +48 -0
- package/dist/core/session.js +385 -0
- package/dist/i18n/middleware.js +4 -4
- package/dist/types/public/config.d.ts +83 -3
- package/dist/types/public/context.d.ts +5 -0
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/dist/vite-plugin-astro-server/route.js +3 -0
- package/package.json +2 -1
- package/templates/actions.mjs +24 -12
- package/types/actions.d.ts +4 -0
package/client.d.ts
CHANGED
|
@@ -535,3 +535,13 @@ declare module '*?inline' {
|
|
|
535
535
|
const src: string;
|
|
536
536
|
export default src;
|
|
537
537
|
}
|
|
538
|
+
|
|
539
|
+
declare module '*?url&inline' {
|
|
540
|
+
const src: string;
|
|
541
|
+
export default src;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
declare module '*?url&no-inline' {
|
|
545
|
+
const src: string;
|
|
546
|
+
export default src;
|
|
547
|
+
}
|
package/dist/actions/plugins.js
CHANGED
|
@@ -70,13 +70,13 @@ export * from 'astro/actions/runtime/virtual/server.js';`;
|
|
|
70
70
|
} else {
|
|
71
71
|
code += `
|
|
72
72
|
export * from 'astro/actions/runtime/virtual/client.js';`;
|
|
73
|
-
code = code.replace(
|
|
74
|
-
"'/** @TRAILING_SLASH@ **/'",
|
|
75
|
-
JSON.stringify(
|
|
76
|
-
shouldAppendForwardSlash(settings.config.trailingSlash, settings.config.build.format)
|
|
77
|
-
)
|
|
78
|
-
);
|
|
79
73
|
}
|
|
74
|
+
code = code.replace(
|
|
75
|
+
"'/** @TRAILING_SLASH@ **/'",
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
shouldAppendForwardSlash(settings.config.trailingSlash, settings.config.build.format)
|
|
78
|
+
)
|
|
79
|
+
);
|
|
80
80
|
return code;
|
|
81
81
|
}
|
|
82
82
|
};
|
|
@@ -8,7 +8,7 @@ import { AstroErrorData } from "../../core/errors/index.js";
|
|
|
8
8
|
import { isRemotePath, removeLeadingForwardSlash } from "../../core/path.js";
|
|
9
9
|
import { getConfiguredImageService } from "../internal.js";
|
|
10
10
|
import { isESMImportedImage } from "../utils/imageKind.js";
|
|
11
|
-
import { loadRemoteImage } from "./remote.js";
|
|
11
|
+
import { loadRemoteImage, revalidateRemoteImage } from "./remote.js";
|
|
12
12
|
async function prepareAssetsGenerationEnv(pipeline, totalCount) {
|
|
13
13
|
const { config, logger, settings } = pipeline;
|
|
14
14
|
let useCache = true;
|
|
@@ -72,7 +72,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
72
72
|
const timeEnd = performance.now();
|
|
73
73
|
const timeChange = getTimeStat(timeStart, timeEnd);
|
|
74
74
|
const timeIncrease = `(+${timeChange})`;
|
|
75
|
-
const statsText = generationData.cached ? `(reused cache entry)` : `(before: ${generationData.weight.before}kB, after: ${generationData.weight.after}kB)`;
|
|
75
|
+
const statsText = generationData.cached !== "miss" ? generationData.cached === "hit" ? `(reused cache entry)` : `(revalidated cache entry)` : `(before: ${generationData.weight.before}kB, after: ${generationData.weight.after}kB)`;
|
|
76
76
|
const count = `(${env.count.current}/${env.count.total})`;
|
|
77
77
|
env.logger.info(
|
|
78
78
|
null,
|
|
@@ -91,7 +91,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
91
91
|
if (isLocalImage) {
|
|
92
92
|
await fs.promises.copyFile(cachedFileURL, finalFileURL, fs.constants.COPYFILE_FICLONE);
|
|
93
93
|
return {
|
|
94
|
-
cached:
|
|
94
|
+
cached: "hit"
|
|
95
95
|
};
|
|
96
96
|
} else {
|
|
97
97
|
const JSONData = JSON.parse(readFileSync(cachedFileURL, "utf-8"));
|
|
@@ -104,11 +104,33 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
104
104
|
if (JSONData.expires > Date.now()) {
|
|
105
105
|
await fs.promises.writeFile(finalFileURL, Buffer.from(JSONData.data, "base64"));
|
|
106
106
|
return {
|
|
107
|
-
cached:
|
|
107
|
+
cached: "hit"
|
|
108
108
|
};
|
|
109
|
-
} else {
|
|
110
|
-
await fs.promises.unlink(cachedFileURL);
|
|
111
109
|
}
|
|
110
|
+
if (JSONData.etag || JSONData.lastModified) {
|
|
111
|
+
try {
|
|
112
|
+
const revalidatedData = await revalidateRemoteImage(options.src, {
|
|
113
|
+
etag: JSONData.etag,
|
|
114
|
+
lastModified: JSONData.lastModified
|
|
115
|
+
});
|
|
116
|
+
if (revalidatedData.data.length) {
|
|
117
|
+
originalImage = revalidatedData;
|
|
118
|
+
} else {
|
|
119
|
+
revalidatedData.data = Buffer.from(JSONData.data, "base64");
|
|
120
|
+
await writeRemoteCacheFile(cachedFileURL, revalidatedData, env);
|
|
121
|
+
await fs.promises.writeFile(finalFileURL, revalidatedData.data);
|
|
122
|
+
return { cached: "revalidated" };
|
|
123
|
+
}
|
|
124
|
+
} catch (e) {
|
|
125
|
+
env.logger.warn(
|
|
126
|
+
null,
|
|
127
|
+
`An error was encountered while revalidating a cached remote asset. Proceeding with stale cache. ${e}`
|
|
128
|
+
);
|
|
129
|
+
await fs.promises.writeFile(finalFileURL, Buffer.from(JSONData.data, "base64"));
|
|
130
|
+
return { cached: "hit" };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
await fs.promises.unlink(cachedFileURL);
|
|
112
134
|
}
|
|
113
135
|
} catch (e) {
|
|
114
136
|
if (e.code !== "ENOENT") {
|
|
@@ -121,7 +143,9 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
121
143
|
}
|
|
122
144
|
let resultData = {
|
|
123
145
|
data: void 0,
|
|
124
|
-
expires: originalImage.expires
|
|
146
|
+
expires: originalImage.expires,
|
|
147
|
+
etag: originalImage.etag,
|
|
148
|
+
lastModified: originalImage.lastModified
|
|
125
149
|
};
|
|
126
150
|
const imageService = await getConfiguredImageService();
|
|
127
151
|
try {
|
|
@@ -145,13 +169,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
145
169
|
if (isLocalImage) {
|
|
146
170
|
await fs.promises.writeFile(cachedFileURL, resultData.data);
|
|
147
171
|
} else {
|
|
148
|
-
await
|
|
149
|
-
cachedFileURL,
|
|
150
|
-
JSON.stringify({
|
|
151
|
-
data: Buffer.from(resultData.data).toString("base64"),
|
|
152
|
-
expires: resultData.expires
|
|
153
|
-
})
|
|
154
|
-
);
|
|
172
|
+
await writeRemoteCacheFile(cachedFileURL, resultData, env);
|
|
155
173
|
}
|
|
156
174
|
}
|
|
157
175
|
} catch (e) {
|
|
@@ -163,7 +181,7 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
163
181
|
await fs.promises.writeFile(finalFileURL, resultData.data);
|
|
164
182
|
}
|
|
165
183
|
return {
|
|
166
|
-
cached:
|
|
184
|
+
cached: "miss",
|
|
167
185
|
weight: {
|
|
168
186
|
// Divide by 1024 to get size in kilobytes
|
|
169
187
|
before: Math.trunc(originalImage.data.byteLength / 1024),
|
|
@@ -172,6 +190,24 @@ async function generateImagesForPath(originalFilePath, transformsAndPath, env, q
|
|
|
172
190
|
};
|
|
173
191
|
}
|
|
174
192
|
}
|
|
193
|
+
async function writeRemoteCacheFile(cachedFileURL, resultData, env) {
|
|
194
|
+
try {
|
|
195
|
+
return await fs.promises.writeFile(
|
|
196
|
+
cachedFileURL,
|
|
197
|
+
JSON.stringify({
|
|
198
|
+
data: Buffer.from(resultData.data).toString("base64"),
|
|
199
|
+
expires: resultData.expires,
|
|
200
|
+
etag: resultData.etag,
|
|
201
|
+
lastModified: resultData.lastModified
|
|
202
|
+
})
|
|
203
|
+
);
|
|
204
|
+
} catch (e) {
|
|
205
|
+
env.logger.warn(
|
|
206
|
+
null,
|
|
207
|
+
`An error was encountered while writing the cache file for a remote asset. Proceeding without caching this asset. Error: ${e}`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
175
211
|
function getStaticImageList() {
|
|
176
212
|
if (!globalThis?.astroAsset?.staticImages) {
|
|
177
213
|
return /* @__PURE__ */ new Map();
|
|
@@ -180,11 +216,7 @@ function getStaticImageList() {
|
|
|
180
216
|
}
|
|
181
217
|
async function loadImage(path, env) {
|
|
182
218
|
if (isRemotePath(path)) {
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
data: remoteImage.data,
|
|
186
|
-
expires: remoteImage.expires
|
|
187
|
-
};
|
|
219
|
+
return await loadRemoteImage(path);
|
|
188
220
|
}
|
|
189
221
|
return {
|
|
190
222
|
data: await fs.promises.readFile(getFullImagePath(path, env)),
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
export type RemoteCacheEntry = {
|
|
2
2
|
data: string;
|
|
3
3
|
expires: number;
|
|
4
|
+
etag?: string;
|
|
5
|
+
lastModified?: string;
|
|
4
6
|
};
|
|
5
7
|
export declare function loadRemoteImage(src: string): Promise<{
|
|
6
8
|
data: Buffer;
|
|
7
9
|
expires: number;
|
|
10
|
+
etag: string | undefined;
|
|
11
|
+
lastModified: string | undefined;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Revalidate a cached remote asset using its entity-tag or modified date.
|
|
15
|
+
* Uses the [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) and [If-Modified-Since](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Modified-Since)
|
|
16
|
+
* headers to check with the remote server if the cached version of a remote asset is still up to date.
|
|
17
|
+
* The remote server may respond that the cached asset is still up-to-date if the entity-tag or modification time matches (304 Not Modified), or respond with an updated asset (200 OK)
|
|
18
|
+
* @param src - url to remote asset
|
|
19
|
+
* @param revalidationData - an object containing the stored Entity-Tag of the cached asset and/or the Last Modified time
|
|
20
|
+
* @returns An ImageData object containing the asset data, a new expiry time, and the asset's etag. The data buffer will be empty if the asset was not modified.
|
|
21
|
+
*/
|
|
22
|
+
export declare function revalidateRemoteImage(src: string, revalidationData: {
|
|
23
|
+
etag?: string;
|
|
24
|
+
lastModified?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
data: Buffer;
|
|
27
|
+
expires: number;
|
|
28
|
+
etag: string | undefined;
|
|
29
|
+
lastModified: string | undefined;
|
|
8
30
|
}>;
|
|
@@ -11,7 +11,41 @@ async function loadRemoteImage(src) {
|
|
|
11
11
|
const expires = policy.storable() ? policy.timeToLive() : 0;
|
|
12
12
|
return {
|
|
13
13
|
data: Buffer.from(await res.arrayBuffer()),
|
|
14
|
-
expires: Date.now() + expires
|
|
14
|
+
expires: Date.now() + expires,
|
|
15
|
+
etag: res.headers.get("Etag") ?? void 0,
|
|
16
|
+
lastModified: res.headers.get("Last-Modified") ?? void 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function revalidateRemoteImage(src, revalidationData) {
|
|
20
|
+
const headers = {
|
|
21
|
+
...revalidationData.etag && { "If-None-Match": revalidationData.etag },
|
|
22
|
+
...revalidationData.lastModified && { "If-Modified-Since": revalidationData.lastModified }
|
|
23
|
+
};
|
|
24
|
+
const req = new Request(src, { headers });
|
|
25
|
+
const res = await fetch(req);
|
|
26
|
+
if (!res.ok && res.status !== 304) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Failed to revalidate cached remote image ${src}. The request did not return a 200 OK / 304 NOT MODIFIED response. (received ${res.status} ${res.statusText})`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
const data = Buffer.from(await res.arrayBuffer());
|
|
32
|
+
if (res.ok && !data.length) {
|
|
33
|
+
return await loadRemoteImage(src);
|
|
34
|
+
}
|
|
35
|
+
const policy = new CachePolicy(
|
|
36
|
+
webToCachePolicyRequest(req),
|
|
37
|
+
webToCachePolicyResponse(
|
|
38
|
+
res.ok ? res : new Response(null, { status: 200, headers: res.headers })
|
|
39
|
+
)
|
|
40
|
+
// 304 responses themselves are not cachable, so just pretend to get the refreshed TTL
|
|
41
|
+
);
|
|
42
|
+
const expires = policy.storable() ? policy.timeToLive() : 0;
|
|
43
|
+
return {
|
|
44
|
+
data,
|
|
45
|
+
expires: Date.now() + expires,
|
|
46
|
+
// While servers should respond with the same headers as a 200 response, if they don't we should reuse the stored value
|
|
47
|
+
etag: res.headers.get("Etag") ?? (res.ok ? void 0 : revalidationData.etag),
|
|
48
|
+
lastModified: res.headers.get("Last-Modified") ?? (res.ok ? void 0 : revalidationData.lastModified)
|
|
15
49
|
};
|
|
16
50
|
}
|
|
17
51
|
function webToCachePolicyRequest({ url, method, headers: _headers }) {
|
|
@@ -38,5 +72,6 @@ function webToCachePolicyResponse({ status, headers: _headers }) {
|
|
|
38
72
|
};
|
|
39
73
|
}
|
|
40
74
|
export {
|
|
41
|
-
loadRemoteImage
|
|
75
|
+
loadRemoteImage,
|
|
76
|
+
revalidateRemoteImage
|
|
42
77
|
};
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { UserConfig as ViteUserConfig, UserConfigFn as ViteUserConfigFn } from 'vite';
|
|
2
|
-
import type { AstroInlineConfig, AstroUserConfig, Locales } from '../types/public/config.js';
|
|
2
|
+
import type { AstroInlineConfig, AstroUserConfig, Locales, SessionDriverName } from '../types/public/config.js';
|
|
3
3
|
/**
|
|
4
4
|
* See the full Astro Configuration API Documentation
|
|
5
5
|
* https://astro.build/config
|
|
6
6
|
*/
|
|
7
|
-
export declare function defineConfig<const TLocales extends Locales = never>(config: AstroUserConfig<TLocales>): AstroUserConfig<TLocales>;
|
|
7
|
+
export declare function defineConfig<const TLocales extends Locales = never, const TDriver extends SessionDriverName = never>(config: AstroUserConfig<TLocales, TDriver>): AstroUserConfig<TLocales, TDriver>;
|
|
8
8
|
/**
|
|
9
9
|
* Use Astro to generate a fully resolved Vite config
|
|
10
10
|
*/
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
getEntryConfigByExtMap,
|
|
14
14
|
getEntryDataAndImages,
|
|
15
|
-
globalContentConfigObserver
|
|
15
|
+
globalContentConfigObserver,
|
|
16
|
+
safeStringify
|
|
16
17
|
} from "./utils.js";
|
|
17
18
|
class ContentLayer {
|
|
18
19
|
#logger;
|
|
@@ -105,16 +106,28 @@ class ContentLayer {
|
|
|
105
106
|
return;
|
|
106
107
|
}
|
|
107
108
|
logger.info("Syncing content");
|
|
109
|
+
const {
|
|
110
|
+
vite: _vite,
|
|
111
|
+
integrations: _integrations,
|
|
112
|
+
adapter: _adapter,
|
|
113
|
+
...hashableConfig
|
|
114
|
+
} = this.#settings.config;
|
|
115
|
+
const astroConfigDigest = safeStringify(hashableConfig);
|
|
108
116
|
const { digest: currentConfigDigest } = contentConfig.config;
|
|
109
117
|
this.#lastConfigDigest = currentConfigDigest;
|
|
110
118
|
let shouldClear = false;
|
|
111
|
-
const previousConfigDigest = await this.#store.metaStore().get("config-digest");
|
|
119
|
+
const previousConfigDigest = await this.#store.metaStore().get("content-config-digest");
|
|
120
|
+
const previousAstroConfigDigest = await this.#store.metaStore().get("astro-config-digest");
|
|
112
121
|
const previousAstroVersion = await this.#store.metaStore().get("astro-version");
|
|
122
|
+
if (previousAstroConfigDigest && previousAstroConfigDigest !== astroConfigDigest) {
|
|
123
|
+
logger.info("Astro config changed");
|
|
124
|
+
shouldClear = true;
|
|
125
|
+
}
|
|
113
126
|
if (currentConfigDigest && previousConfigDigest !== currentConfigDigest) {
|
|
114
127
|
logger.info("Content config changed");
|
|
115
128
|
shouldClear = true;
|
|
116
129
|
}
|
|
117
|
-
if (previousAstroVersion !== "5.0
|
|
130
|
+
if (previousAstroVersion !== "5.1.0") {
|
|
118
131
|
logger.info("Astro version changed");
|
|
119
132
|
shouldClear = true;
|
|
120
133
|
}
|
|
@@ -122,11 +135,14 @@ class ContentLayer {
|
|
|
122
135
|
logger.info("Clearing content store");
|
|
123
136
|
this.#store.clearAll();
|
|
124
137
|
}
|
|
125
|
-
if ("5.0
|
|
126
|
-
await this.#store.metaStore().set("astro-version", "5.0
|
|
138
|
+
if ("5.1.0") {
|
|
139
|
+
await this.#store.metaStore().set("astro-version", "5.1.0");
|
|
127
140
|
}
|
|
128
141
|
if (currentConfigDigest) {
|
|
129
|
-
await this.#store.metaStore().set("config-digest", currentConfigDigest);
|
|
142
|
+
await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
143
|
+
}
|
|
144
|
+
if (astroConfigDigest) {
|
|
145
|
+
await this.#store.metaStore().set("astro-config-digest", astroConfigDigest);
|
|
130
146
|
}
|
|
131
147
|
await Promise.all(
|
|
132
148
|
Object.entries(contentConfig.config.collections).map(async ([name, collection]) => {
|
package/dist/content/utils.d.ts
CHANGED
|
@@ -583,4 +583,5 @@ export declare function posixifyPath(filePath: string): string;
|
|
|
583
583
|
*/
|
|
584
584
|
export declare function posixRelative(from: string, to: string): string;
|
|
585
585
|
export declare function contentModuleToId(fileName: string): string;
|
|
586
|
+
export declare function safeStringify(value: unknown): string;
|
|
586
587
|
export {};
|
package/dist/content/utils.js
CHANGED
|
@@ -589,6 +589,27 @@ function contentModuleToId(fileName) {
|
|
|
589
589
|
params.set(CONTENT_MODULE_FLAG, "true");
|
|
590
590
|
return `${DEFERRED_MODULE}?${params.toString()}`;
|
|
591
591
|
}
|
|
592
|
+
function safeStringifyReplacer(seen) {
|
|
593
|
+
return function(_key, value) {
|
|
594
|
+
if (!(value !== null && typeof value === "object")) {
|
|
595
|
+
return value;
|
|
596
|
+
}
|
|
597
|
+
if (seen.has(value)) {
|
|
598
|
+
return "[Circular]";
|
|
599
|
+
}
|
|
600
|
+
seen.add(value);
|
|
601
|
+
const newValue = Array.isArray(value) ? [] : {};
|
|
602
|
+
for (const [key2, value2] of Object.entries(value)) {
|
|
603
|
+
newValue[key2] = safeStringifyReplacer(seen)(key2, value2);
|
|
604
|
+
}
|
|
605
|
+
seen.delete(value);
|
|
606
|
+
return newValue;
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function safeStringify(value) {
|
|
610
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
611
|
+
return JSON.stringify(value, safeStringifyReplacer(seen));
|
|
612
|
+
}
|
|
592
613
|
export {
|
|
593
614
|
autogenerateCollections,
|
|
594
615
|
contentModuleToId,
|
|
@@ -617,5 +638,6 @@ export {
|
|
|
617
638
|
posixifyPath,
|
|
618
639
|
reloadContentConfigObserver,
|
|
619
640
|
reverseSymlink,
|
|
620
|
-
safeParseFrontmatter
|
|
641
|
+
safeParseFrontmatter,
|
|
642
|
+
safeStringify
|
|
621
643
|
};
|
package/dist/core/app/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { createAssetLink } from "../render/ssr-element.js";
|
|
|
21
21
|
import { ensure404Route } from "../routing/astro-designed-error-pages.js";
|
|
22
22
|
import { createDefaultRoutes } from "../routing/default.js";
|
|
23
23
|
import { matchRoute } from "../routing/match.js";
|
|
24
|
+
import { PERSIST_SYMBOL } from "../session.js";
|
|
24
25
|
import { AppPipeline } from "./pipeline.js";
|
|
25
26
|
import { deserializeManifest } from "./common.js";
|
|
26
27
|
class App {
|
|
@@ -188,6 +189,7 @@ class App {
|
|
|
188
189
|
const pathname = this.#getPathnameFromRequest(request);
|
|
189
190
|
const defaultStatus = this.#getDefaultStatusCode(routeData, pathname);
|
|
190
191
|
let response;
|
|
192
|
+
let session;
|
|
191
193
|
try {
|
|
192
194
|
const mod = await this.#pipeline.getModuleForRoute(routeData);
|
|
193
195
|
const renderContext = await RenderContext.create({
|
|
@@ -199,10 +201,13 @@ class App {
|
|
|
199
201
|
status: defaultStatus,
|
|
200
202
|
clientAddress
|
|
201
203
|
});
|
|
204
|
+
session = renderContext.session;
|
|
202
205
|
response = await renderContext.render(await mod.page());
|
|
203
206
|
} catch (err) {
|
|
204
207
|
this.#logger.error(null, err.stack || err.message || String(err));
|
|
205
208
|
return this.#renderError(request, { locals, status: 500, error: err, clientAddress });
|
|
209
|
+
} finally {
|
|
210
|
+
session?.[PERSIST_SYMBOL]();
|
|
206
211
|
}
|
|
207
212
|
if (REROUTABLE_STATUS_CODES.includes(response.status) && response.headers.get(REROUTE_DIRECTIVE_HEADER) !== "no") {
|
|
208
213
|
return this.#renderError(request, {
|
|
@@ -270,6 +275,7 @@ class App {
|
|
|
270
275
|
}
|
|
271
276
|
}
|
|
272
277
|
const mod = await this.#pipeline.getModuleForRoute(errorRouteData);
|
|
278
|
+
let session;
|
|
273
279
|
try {
|
|
274
280
|
const renderContext = await RenderContext.create({
|
|
275
281
|
locals,
|
|
@@ -282,6 +288,7 @@ class App {
|
|
|
282
288
|
props: { error },
|
|
283
289
|
clientAddress
|
|
284
290
|
});
|
|
291
|
+
session = renderContext.session;
|
|
285
292
|
const response2 = await renderContext.render(await mod.page());
|
|
286
293
|
return this.#mergeResponses(response2, originalResponse);
|
|
287
294
|
} catch {
|
|
@@ -294,6 +301,8 @@ class App {
|
|
|
294
301
|
clientAddress
|
|
295
302
|
});
|
|
296
303
|
}
|
|
304
|
+
} finally {
|
|
305
|
+
session?.[PERSIST_SYMBOL]();
|
|
297
306
|
}
|
|
298
307
|
}
|
|
299
308
|
const response = this.#mergeResponses(new Response(null, { status }), originalResponse);
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RoutingStrategies } from '../../i18n/utils.js';
|
|
2
2
|
import type { ComponentInstance, SerializedRouteData } from '../../types/astro.js';
|
|
3
3
|
import type { AstroMiddlewareInstance } from '../../types/public/common.js';
|
|
4
|
-
import type { Locales } from '../../types/public/config.js';
|
|
4
|
+
import type { Locales, ResolvedSessionConfig } 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
7
|
export type ComponentPath = string;
|
|
@@ -59,6 +59,7 @@ export type SSRManifest = {
|
|
|
59
59
|
i18n: SSRManifestI18n | undefined;
|
|
60
60
|
middleware?: () => Promise<AstroMiddlewareInstance> | AstroMiddlewareInstance;
|
|
61
61
|
checkOrigin: boolean;
|
|
62
|
+
sessionConfig?: ResolvedSessionConfig<any>;
|
|
62
63
|
};
|
|
63
64
|
export type SSRManifestI18n = {
|
|
64
65
|
fallback: Record<string, string> | undefined;
|
|
@@ -9,6 +9,7 @@ import { encodeKey } from "../../encryption.js";
|
|
|
9
9
|
import { fileExtension, joinPaths, prependForwardSlash } from "../../path.js";
|
|
10
10
|
import { DEFAULT_COMPONENTS } from "../../routing/default.js";
|
|
11
11
|
import { serializeRouteData } from "../../routing/index.js";
|
|
12
|
+
import { resolveSessionDriver } from "../../session.js";
|
|
12
13
|
import { addRollupInput } from "../add-rollup-input.js";
|
|
13
14
|
import { getOutFile, getOutFolder } from "../common.js";
|
|
14
15
|
import { cssOrder, mergeInlineCss } from "../internal.js";
|
|
@@ -17,7 +18,7 @@ const manifestReplace = "@@ASTRO_MANIFEST_REPLACE@@";
|
|
|
17
18
|
const replaceExp = new RegExp(`['"]${manifestReplace}['"]`, "g");
|
|
18
19
|
const SSR_MANIFEST_VIRTUAL_MODULE_ID = "@astrojs-manifest";
|
|
19
20
|
const RESOLVED_SSR_MANIFEST_VIRTUAL_MODULE_ID = "\0" + SSR_MANIFEST_VIRTUAL_MODULE_ID;
|
|
20
|
-
function vitePluginManifest(
|
|
21
|
+
function vitePluginManifest(options, internals) {
|
|
21
22
|
return {
|
|
22
23
|
name: "@astro/plugin-build-manifest",
|
|
23
24
|
enforce: "post",
|
|
@@ -40,8 +41,12 @@ function vitePluginManifest(_options, internals) {
|
|
|
40
41
|
`import { deserializeManifest as _deserializeManifest } from 'astro/app'`,
|
|
41
42
|
`import { _privateSetManifestDontUseThis } from 'astro:ssr-manifest'`
|
|
42
43
|
];
|
|
44
|
+
const resolvedDriver = await resolveSessionDriver(
|
|
45
|
+
options.settings.config.experimental?.session?.driver
|
|
46
|
+
);
|
|
43
47
|
const contents = [
|
|
44
48
|
`const manifest = _deserializeManifest('${manifestReplace}');`,
|
|
49
|
+
`if (manifest.sessionConfig) manifest.sessionConfig.driverModule = ${resolvedDriver ? `() => import(${JSON.stringify(resolvedDriver)})` : "null"};`,
|
|
45
50
|
`_privateSetManifestDontUseThis(manifest);`
|
|
46
51
|
];
|
|
47
52
|
const exports = [`export { manifest }`];
|
|
@@ -220,7 +225,8 @@ function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
220
225
|
buildFormat: settings.config.build.format,
|
|
221
226
|
checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
|
|
222
227
|
serverIslandNameMap: Array.from(settings.serverIslandNameMap),
|
|
223
|
-
key: encodedKey
|
|
228
|
+
key: encodedKey,
|
|
229
|
+
sessionConfig: settings.config.experimental.session
|
|
224
230
|
};
|
|
225
231
|
}
|
|
226
232
|
export {
|
|
@@ -218,14 +218,14 @@ ${bgGreen(black(" building client (vite) "))}`);
|
|
|
218
218
|
envPrefix: viteConfig.envPrefix ?? "PUBLIC_",
|
|
219
219
|
base: settings.config.base
|
|
220
220
|
};
|
|
221
|
-
await runHookBuildSetup({
|
|
221
|
+
const updatedViteBuildConfig = await runHookBuildSetup({
|
|
222
222
|
config: settings.config,
|
|
223
223
|
pages: internals.pagesByKeys,
|
|
224
224
|
vite: viteBuildConfig,
|
|
225
225
|
target: "client",
|
|
226
226
|
logger: opts.logger
|
|
227
227
|
});
|
|
228
|
-
const buildResult = await vite.build(
|
|
228
|
+
const buildResult = await vite.build(updatedViteBuildConfig);
|
|
229
229
|
return buildResult;
|
|
230
230
|
}
|
|
231
231
|
async function runPostBuildHooks(container, ssrOutputs, clientOutputs) {
|
|
@@ -316,7 +316,6 @@ async function ssrMoveAssets(opts) {
|
|
|
316
316
|
const files = await glob(`**/*`, {
|
|
317
317
|
cwd: fileURLToPath(serverAssets)
|
|
318
318
|
});
|
|
319
|
-
console.log("FILES2", files);
|
|
320
319
|
if (files.length > 0) {
|
|
321
320
|
await Promise.all(
|
|
322
321
|
files.map(async function moveAsset(filename) {
|