astro 6.0.0-beta.16 → 6.0.0-beta.17
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/actions/runtime/server.js +7 -7
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +2 -0
- package/dist/content/content-layer.d.ts +5 -9
- package/dist/content/content-layer.js +22 -30
- package/dist/content/instance.d.ts +17 -0
- package/dist/content/instance.js +20 -0
- package/dist/core/app/types.d.ts +8 -0
- package/dist/core/base-pipeline.js +2 -1
- package/dist/core/build/plugins/plugin-manifest.js +6 -1
- package/dist/core/config/schemas/base.d.ts +2 -0
- package/dist/core/config/schemas/base.js +3 -1
- package/dist/core/config/schemas/relative.d.ts +3 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +3 -2
- package/dist/core/dev/restart.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/sync/index.js +2 -1
- package/dist/integrations/adapter-utils.d.ts +19 -0
- package/dist/integrations/adapter-utils.js +12 -0
- package/dist/integrations/hooks.js +1 -1
- package/dist/manifest/serialized.js +4 -0
- package/dist/types/public/config.d.ts +24 -0
- package/dist/types/public/integrations.d.ts +13 -3
- package/dist/vite-plugin-astro-server/plugin.js +4 -0
- package/package.json +4 -4
|
@@ -99,9 +99,10 @@ function getActionContext(context) {
|
|
|
99
99
|
}
|
|
100
100
|
throw error;
|
|
101
101
|
}
|
|
102
|
+
const bodySizeLimit = pipeline.manifest.actionBodySizeLimit;
|
|
102
103
|
let input;
|
|
103
104
|
try {
|
|
104
|
-
input = await parseRequestBody(context.request);
|
|
105
|
+
input = await parseRequestBody(context.request, bodySizeLimit);
|
|
105
106
|
} catch (e) {
|
|
106
107
|
if (e instanceof ActionError) {
|
|
107
108
|
return { data: void 0, error: e };
|
|
@@ -149,22 +150,21 @@ function getCallerInfo(ctx) {
|
|
|
149
150
|
}
|
|
150
151
|
return void 0;
|
|
151
152
|
}
|
|
152
|
-
|
|
153
|
-
async function parseRequestBody(request) {
|
|
153
|
+
async function parseRequestBody(request, bodySizeLimit) {
|
|
154
154
|
const contentType = request.headers.get("content-type");
|
|
155
155
|
const contentLengthHeader = request.headers.get("content-length");
|
|
156
156
|
const contentLength = contentLengthHeader ? Number.parseInt(contentLengthHeader, 10) : void 0;
|
|
157
157
|
const hasContentLength = typeof contentLength === "number" && Number.isFinite(contentLength);
|
|
158
158
|
if (!contentType) return void 0;
|
|
159
|
-
if (hasContentLength && contentLength >
|
|
159
|
+
if (hasContentLength && contentLength > bodySizeLimit) {
|
|
160
160
|
throw new ActionError({
|
|
161
161
|
code: "CONTENT_TOO_LARGE",
|
|
162
|
-
message: `Request body exceeds ${
|
|
162
|
+
message: `Request body exceeds ${bodySizeLimit} bytes`
|
|
163
163
|
});
|
|
164
164
|
}
|
|
165
165
|
if (hasContentType(contentType, formContentTypes)) {
|
|
166
166
|
if (!hasContentLength) {
|
|
167
|
-
const body = await readRequestBodyWithLimit(request.clone(),
|
|
167
|
+
const body = await readRequestBodyWithLimit(request.clone(), bodySizeLimit);
|
|
168
168
|
const formRequest = new Request(request.url, {
|
|
169
169
|
method: request.method,
|
|
170
170
|
headers: request.headers,
|
|
@@ -177,7 +177,7 @@ async function parseRequestBody(request) {
|
|
|
177
177
|
if (hasContentType(contentType, ["application/json"])) {
|
|
178
178
|
if (contentLength === 0) return void 0;
|
|
179
179
|
if (!hasContentLength) {
|
|
180
|
-
const body = await readRequestBodyWithLimit(request.clone(),
|
|
180
|
+
const body = await readRequestBodyWithLimit(request.clone(), bodySizeLimit);
|
|
181
181
|
if (body.byteLength === 0) return void 0;
|
|
182
182
|
return JSON.parse(new TextDecoder().decode(body));
|
|
183
183
|
}
|
package/dist/container/index.js
CHANGED
|
@@ -33,6 +33,7 @@ function createManifest(manifest, renderers, middleware) {
|
|
|
33
33
|
compressHTML: manifest?.compressHTML ?? ASTRO_CONFIG_DEFAULTS.compressHTML,
|
|
34
34
|
assetsDir: manifest?.assetsDir ?? ASTRO_CONFIG_DEFAULTS.build.assets,
|
|
35
35
|
serverLike: manifest?.serverLike ?? true,
|
|
36
|
+
middlewareMode: manifest?.middlewareMode ?? "classic",
|
|
36
37
|
assets: manifest?.assets ?? /* @__PURE__ */ new Set(),
|
|
37
38
|
assetsPrefix: manifest?.assetsPrefix ?? void 0,
|
|
38
39
|
entryModules: manifest?.entryModules ?? {},
|
|
@@ -47,6 +48,7 @@ function createManifest(manifest, renderers, middleware) {
|
|
|
47
48
|
i18n: manifest?.i18n,
|
|
48
49
|
checkOrigin: false,
|
|
49
50
|
allowedDomains: manifest?.allowedDomains ?? [],
|
|
51
|
+
actionBodySizeLimit: 1024 * 1024,
|
|
50
52
|
middleware: manifest?.middleware ?? middlewareInstance,
|
|
51
53
|
key: createKey(),
|
|
52
54
|
csp: manifest?.csp,
|
|
@@ -3,15 +3,17 @@ import type { Logger } from '../core/logger/core.js';
|
|
|
3
3
|
import type { AstroSettings } from '../types/astro.js';
|
|
4
4
|
import type { RefreshContentOptions } from '../types/public/content.js';
|
|
5
5
|
import type { MutableDataStore } from './mutable-data-store.js';
|
|
6
|
-
|
|
6
|
+
import { type ContentObservable } from './utils.js';
|
|
7
|
+
export interface ContentLayerOptions {
|
|
7
8
|
store: MutableDataStore;
|
|
8
9
|
settings: AstroSettings;
|
|
9
10
|
logger: Logger;
|
|
10
11
|
watcher?: FSWatcher;
|
|
12
|
+
contentConfigObserver?: ContentObservable;
|
|
11
13
|
}
|
|
12
|
-
declare class ContentLayer {
|
|
14
|
+
export declare class ContentLayer {
|
|
13
15
|
#private;
|
|
14
|
-
constructor({ settings, logger, store, watcher }: ContentLayerOptions);
|
|
16
|
+
constructor({ settings, logger, store, watcher, contentConfigObserver, }: ContentLayerOptions);
|
|
15
17
|
/**
|
|
16
18
|
* Whether the content layer is currently loading content
|
|
17
19
|
*/
|
|
@@ -37,9 +39,3 @@ declare class ContentLayer {
|
|
|
37
39
|
* In production, it's in the cache directory so that it's preserved between builds.
|
|
38
40
|
*/
|
|
39
41
|
export declare function getDataStoreFile(settings: AstroSettings, isDev: boolean): URL;
|
|
40
|
-
export declare const globalContentLayer: {
|
|
41
|
-
init: (options: ContentLayerOptions) => ContentLayer;
|
|
42
|
-
get: () => ContentLayer | null;
|
|
43
|
-
dispose: () => void;
|
|
44
|
-
};
|
|
45
|
-
export {};
|
|
@@ -30,12 +30,20 @@ class ContentLayer {
|
|
|
30
30
|
#unsubscribe;
|
|
31
31
|
#markdownProcessor;
|
|
32
32
|
#generateDigest;
|
|
33
|
+
#contentConfigObserver;
|
|
33
34
|
#queue;
|
|
34
|
-
constructor({
|
|
35
|
+
constructor({
|
|
36
|
+
settings,
|
|
37
|
+
logger,
|
|
38
|
+
store,
|
|
39
|
+
watcher,
|
|
40
|
+
contentConfigObserver = globalContentConfigObserver
|
|
41
|
+
}) {
|
|
35
42
|
watcher?.setMaxListeners(50);
|
|
36
43
|
this.#logger = logger;
|
|
37
44
|
this.#store = store;
|
|
38
45
|
this.#settings = settings;
|
|
46
|
+
this.#contentConfigObserver = contentConfigObserver;
|
|
39
47
|
if (watcher) {
|
|
40
48
|
this.#watcher = createWatcherWrapper(watcher);
|
|
41
49
|
}
|
|
@@ -52,7 +60,7 @@ class ContentLayer {
|
|
|
52
60
|
*/
|
|
53
61
|
watchContentConfig() {
|
|
54
62
|
this.#unsubscribe?.();
|
|
55
|
-
this.#unsubscribe =
|
|
63
|
+
this.#unsubscribe = this.#contentConfigObserver.subscribe(async (ctx) => {
|
|
56
64
|
if (ctx.status === "loaded" && ctx.config.digest !== this.#lastConfigDigest) {
|
|
57
65
|
this.sync();
|
|
58
66
|
}
|
|
@@ -122,12 +130,12 @@ class ContentLayer {
|
|
|
122
130
|
return this.#queue.add(() => this.#doSync(options));
|
|
123
131
|
}
|
|
124
132
|
async #doSync(options) {
|
|
125
|
-
let contentConfig =
|
|
133
|
+
let contentConfig = this.#contentConfigObserver.get();
|
|
126
134
|
const logger = this.#logger.forkIntegrationLogger("content");
|
|
127
135
|
if (contentConfig?.status === "loading") {
|
|
128
136
|
contentConfig = await Promise.race([
|
|
129
137
|
new Promise((resolve) => {
|
|
130
|
-
const unsub =
|
|
138
|
+
const unsub = this.#contentConfigObserver.subscribe((ctx) => {
|
|
131
139
|
unsub();
|
|
132
140
|
resolve(ctx);
|
|
133
141
|
});
|
|
@@ -170,9 +178,9 @@ ${contentConfig.error.message}`
|
|
|
170
178
|
const { digest: currentConfigDigest } = contentConfig.config;
|
|
171
179
|
this.#lastConfigDigest = currentConfigDigest;
|
|
172
180
|
let shouldClear = false;
|
|
173
|
-
const previousConfigDigest =
|
|
174
|
-
const previousAstroConfigDigest =
|
|
175
|
-
const previousAstroVersion =
|
|
181
|
+
const previousConfigDigest = this.#store.metaStore().get("content-config-digest");
|
|
182
|
+
const previousAstroConfigDigest = this.#store.metaStore().get("astro-config-digest");
|
|
183
|
+
const previousAstroVersion = this.#store.metaStore().get("astro-version");
|
|
176
184
|
if (previousAstroConfigDigest && previousAstroConfigDigest !== astroConfigDigest) {
|
|
177
185
|
logger.info("Astro config changed");
|
|
178
186
|
shouldClear = true;
|
|
@@ -181,7 +189,7 @@ ${contentConfig.error.message}`
|
|
|
181
189
|
logger.info("Content config changed");
|
|
182
190
|
shouldClear = true;
|
|
183
191
|
}
|
|
184
|
-
if (previousAstroVersion && previousAstroVersion !== "6.0.0-beta.
|
|
192
|
+
if (previousAstroVersion && previousAstroVersion !== "6.0.0-beta.17") {
|
|
185
193
|
logger.info("Astro version changed");
|
|
186
194
|
shouldClear = true;
|
|
187
195
|
}
|
|
@@ -189,14 +197,14 @@ ${contentConfig.error.message}`
|
|
|
189
197
|
logger.info("Clearing content store");
|
|
190
198
|
this.#store.clearAll();
|
|
191
199
|
}
|
|
192
|
-
if ("6.0.0-beta.
|
|
193
|
-
|
|
200
|
+
if ("6.0.0-beta.17") {
|
|
201
|
+
this.#store.metaStore().set("astro-version", "6.0.0-beta.17");
|
|
194
202
|
}
|
|
195
203
|
if (currentConfigDigest) {
|
|
196
|
-
|
|
204
|
+
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
197
205
|
}
|
|
198
206
|
if (astroConfigDigest) {
|
|
199
|
-
|
|
207
|
+
this.#store.metaStore().set("astro-config-digest", astroConfigDigest);
|
|
200
208
|
}
|
|
201
209
|
if (!options?.loaders?.length) {
|
|
202
210
|
this.#watcher?.removeAllTrackedListeners();
|
|
@@ -354,23 +362,7 @@ ${JSON.stringify({ ...raw, id: void 0 }, null, 2)}`
|
|
|
354
362
|
function getDataStoreFile(settings, isDev) {
|
|
355
363
|
return new URL(DATA_STORE_FILE, isDev ? settings.dotAstroDir : settings.config.cacheDir);
|
|
356
364
|
}
|
|
357
|
-
function contentLayerSingleton() {
|
|
358
|
-
let instance = null;
|
|
359
|
-
return {
|
|
360
|
-
init: (options) => {
|
|
361
|
-
instance?.dispose();
|
|
362
|
-
instance = new ContentLayer(options);
|
|
363
|
-
return instance;
|
|
364
|
-
},
|
|
365
|
-
get: () => instance,
|
|
366
|
-
dispose: () => {
|
|
367
|
-
instance?.dispose();
|
|
368
|
-
instance = null;
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
const globalContentLayer = contentLayerSingleton();
|
|
373
365
|
export {
|
|
374
|
-
|
|
375
|
-
|
|
366
|
+
ContentLayer,
|
|
367
|
+
getDataStoreFile
|
|
376
368
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FSWatcher } from 'vite';
|
|
2
|
+
import { ContentLayer } from './content-layer.js';
|
|
3
|
+
import type { Logger } from '../core/logger/core.js';
|
|
4
|
+
import type { AstroSettings } from '../types/astro.js';
|
|
5
|
+
import type { MutableDataStore } from './mutable-data-store.js';
|
|
6
|
+
interface ContentLayerOptions {
|
|
7
|
+
store: MutableDataStore;
|
|
8
|
+
settings: AstroSettings;
|
|
9
|
+
logger: Logger;
|
|
10
|
+
watcher?: FSWatcher;
|
|
11
|
+
}
|
|
12
|
+
export declare const globalContentLayer: {
|
|
13
|
+
init: (options: ContentLayerOptions) => ContentLayer;
|
|
14
|
+
get: () => ContentLayer | null;
|
|
15
|
+
dispose: () => void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ContentLayer } from "./content-layer.js";
|
|
2
|
+
function contentLayerSingleton() {
|
|
3
|
+
let instance = null;
|
|
4
|
+
return {
|
|
5
|
+
init: (options) => {
|
|
6
|
+
instance?.dispose();
|
|
7
|
+
instance = new ContentLayer(options);
|
|
8
|
+
return instance;
|
|
9
|
+
},
|
|
10
|
+
get: () => instance,
|
|
11
|
+
dispose: () => {
|
|
12
|
+
instance?.dispose();
|
|
13
|
+
instance = null;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
const globalContentLayer = contentLayerSingleton();
|
|
18
|
+
export {
|
|
19
|
+
globalContentLayer
|
|
20
|
+
};
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import type { LoggerLevel } from '../logger/core.js';
|
|
|
9
9
|
import type { RoutingStrategies } from './common.js';
|
|
10
10
|
import type { BaseSessionConfig, SessionDriverFactory } from '../session/types.js';
|
|
11
11
|
import type { DevToolbarPlacement } from '../../types/public/toolbar.js';
|
|
12
|
+
import type { MiddlewareMode } from '../../types/public/integrations.js';
|
|
12
13
|
import type { BaseApp } from './base.js';
|
|
13
14
|
type ComponentPath = string;
|
|
14
15
|
export type StylesheetAsset = {
|
|
@@ -74,6 +75,12 @@ export type SSRManifest = {
|
|
|
74
75
|
* the creation of `dist/client` and `dist/server` folders.
|
|
75
76
|
*/
|
|
76
77
|
serverLike: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* The middleware mode determines when and how middleware executes.
|
|
80
|
+
* - 'classic' (default): Build-time for prerendered pages, request-time for SSR pages
|
|
81
|
+
* - 'edge': Middleware deployed as separate edge function
|
|
82
|
+
*/
|
|
83
|
+
middlewareMode: MiddlewareMode;
|
|
77
84
|
/**
|
|
78
85
|
* Map of directive name (e.g. `load`) to the directive script code
|
|
79
86
|
*/
|
|
@@ -94,6 +101,7 @@ export type SSRManifest = {
|
|
|
94
101
|
}>;
|
|
95
102
|
checkOrigin: boolean;
|
|
96
103
|
allowedDomains?: Partial<RemotePattern>[];
|
|
104
|
+
actionBodySizeLimit: number;
|
|
97
105
|
sessionConfig?: SSRManifestSession;
|
|
98
106
|
cacheDir: URL;
|
|
99
107
|
srcDir: URL;
|
|
@@ -60,7 +60,8 @@ class Pipeline {
|
|
|
60
60
|
async getMiddleware() {
|
|
61
61
|
if (this.resolvedMiddleware) {
|
|
62
62
|
return this.resolvedMiddleware;
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
|
+
if (this.middleware) {
|
|
64
65
|
const middlewareInstance = await this.middleware();
|
|
65
66
|
const onRequest = middlewareInstance.onRequest ?? NOOP_MIDDLEWARE_FN;
|
|
66
67
|
const internalMiddlewares = [onRequest];
|
|
@@ -2,6 +2,7 @@ import { fileURLToPath } from "node:url";
|
|
|
2
2
|
import { glob } from "tinyglobby";
|
|
3
3
|
import { getAssetsPrefix } from "../../../assets/utils/getAssetsPrefix.js";
|
|
4
4
|
import { normalizeTheLocale } from "../../../i18n/index.js";
|
|
5
|
+
import { resolveMiddlewareMode } from "../../../integrations/adapter-utils.js";
|
|
5
6
|
import { runHookBuildSsr } from "../../../integrations/hooks.js";
|
|
6
7
|
import { SERIALIZED_MANIFEST_RESOLVED_ID } from "../../../manifest/serialized.js";
|
|
7
8
|
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from "../../../vite-plugin-scripts/index.js";
|
|
@@ -37,7 +38,8 @@ async function manifestBuildPostHook(options, internals, {
|
|
|
37
38
|
(c) => !c.prerender && c.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)
|
|
38
39
|
);
|
|
39
40
|
if (ssrManifestChunk) {
|
|
40
|
-
const
|
|
41
|
+
const middlewareMode = resolveMiddlewareMode(options.settings.adapter?.adapterFeatures);
|
|
42
|
+
const shouldPassMiddlewareEntryPoint = middlewareMode === "edge";
|
|
41
43
|
await runHookBuildSsr({
|
|
42
44
|
config: options.settings.config,
|
|
43
45
|
manifest,
|
|
@@ -196,6 +198,7 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
196
198
|
internalFetchHeaders = headers;
|
|
197
199
|
}
|
|
198
200
|
}
|
|
201
|
+
const middlewareMode = resolveMiddlewareMode(opts.settings.adapter?.adapterFeatures);
|
|
199
202
|
return {
|
|
200
203
|
rootDir: opts.settings.config.root.toString(),
|
|
201
204
|
cacheDir: opts.settings.config.cacheDir.toString(),
|
|
@@ -208,6 +211,7 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
208
211
|
assetsDir: opts.settings.config.build.assets,
|
|
209
212
|
routes,
|
|
210
213
|
serverLike: opts.settings.buildOutput === "server",
|
|
214
|
+
middlewareMode,
|
|
211
215
|
site: settings.config.site,
|
|
212
216
|
base: settings.config.base,
|
|
213
217
|
userAssetsBase: settings.config?.vite?.base,
|
|
@@ -228,6 +232,7 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
228
232
|
i18n: i18nManifest,
|
|
229
233
|
buildFormat: settings.config.build.format,
|
|
230
234
|
checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
|
|
235
|
+
actionBodySizeLimit: settings.config.security?.actionBodySizeLimit && settings.buildOutput === "server" ? settings.config.security.actionBodySizeLimit : 1024 * 1024,
|
|
231
236
|
allowedDomains: settings.config.security?.allowedDomains,
|
|
232
237
|
key: encodedKey,
|
|
233
238
|
sessionConfig: sessionConfigToManifest(settings.config.session),
|
|
@@ -65,6 +65,7 @@ export declare const ASTRO_CONFIG_DEFAULTS: {
|
|
|
65
65
|
checkOrigin: true;
|
|
66
66
|
allowedDomains: never[];
|
|
67
67
|
csp: false;
|
|
68
|
+
actionBodySizeLimit: number;
|
|
68
69
|
};
|
|
69
70
|
env: {
|
|
70
71
|
schema: {};
|
|
@@ -349,6 +350,7 @@ export declare const AstroConfigSchema: z.ZodObject<{
|
|
|
349
350
|
protocol: z.ZodOptional<z.ZodString>;
|
|
350
351
|
port: z.ZodOptional<z.ZodString>;
|
|
351
352
|
}, z.core.$strip>>>>;
|
|
353
|
+
actionBodySizeLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
352
354
|
csp: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodDefault<z.ZodOptional<z.ZodBoolean>>, z.ZodObject<{
|
|
353
355
|
algorithm: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
354
356
|
"SHA-256": "SHA-256";
|
|
@@ -48,7 +48,8 @@ const ASTRO_CONFIG_DEFAULTS = {
|
|
|
48
48
|
security: {
|
|
49
49
|
checkOrigin: true,
|
|
50
50
|
allowedDomains: [],
|
|
51
|
-
csp: false
|
|
51
|
+
csp: false,
|
|
52
|
+
actionBodySizeLimit: 1024 * 1024
|
|
52
53
|
},
|
|
53
54
|
env: {
|
|
54
55
|
schema: {},
|
|
@@ -253,6 +254,7 @@ const AstroConfigSchema = z.object({
|
|
|
253
254
|
port: z.string().optional()
|
|
254
255
|
})
|
|
255
256
|
).optional().default(ASTRO_CONFIG_DEFAULTS.security.allowedDomains),
|
|
257
|
+
actionBodySizeLimit: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.security.actionBodySizeLimit),
|
|
256
258
|
csp: z.union([
|
|
257
259
|
z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.security.csp),
|
|
258
260
|
z.object({
|
|
@@ -237,6 +237,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
237
237
|
protocol: z.ZodOptional<z.ZodString>;
|
|
238
238
|
port: z.ZodOptional<z.ZodString>;
|
|
239
239
|
}, z.core.$strip>>>>;
|
|
240
|
+
actionBodySizeLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
240
241
|
csp: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodDefault<z.ZodOptional<z.ZodBoolean>>, z.ZodObject<{
|
|
241
242
|
algorithm: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
242
243
|
"SHA-256": "SHA-256";
|
|
@@ -491,6 +492,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
491
492
|
protocol?: string | undefined;
|
|
492
493
|
port?: string | undefined;
|
|
493
494
|
}[];
|
|
495
|
+
actionBodySizeLimit: number;
|
|
494
496
|
csp: boolean | {
|
|
495
497
|
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
|
|
496
498
|
directives?: (`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}`)[] | undefined;
|
|
@@ -719,6 +721,7 @@ export declare function createRelativeSchema(cmd: string, fileProtocolRoot: stri
|
|
|
719
721
|
protocol?: string | undefined;
|
|
720
722
|
port?: string | undefined;
|
|
721
723
|
}[];
|
|
724
|
+
actionBodySizeLimit: number;
|
|
722
725
|
csp: boolean | {
|
|
723
726
|
algorithm: "SHA-256" | "SHA-384" | "SHA-512";
|
|
724
727
|
directives?: (`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}`)[] | undefined;
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -2,7 +2,8 @@ import fs from "node:fs";
|
|
|
2
2
|
import { performance } from "node:perf_hooks";
|
|
3
3
|
import colors from "piccolore";
|
|
4
4
|
import { gt, major, minor, patch } from "semver";
|
|
5
|
-
import { getDataStoreFile
|
|
5
|
+
import { getDataStoreFile } from "../../content/content-layer.js";
|
|
6
|
+
import { globalContentLayer } from "../../content/instance.js";
|
|
6
7
|
import { attachContentServerListeners } from "../../content/index.js";
|
|
7
8
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
8
9
|
import { globalContentConfigObserver } from "../../content/utils.js";
|
|
@@ -25,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
25
26
|
await telemetry.record([]);
|
|
26
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
27
28
|
const logger = restart.container.logger;
|
|
28
|
-
const currentVersion = "6.0.0-beta.
|
|
29
|
+
const currentVersion = "6.0.0-beta.17";
|
|
29
30
|
const isPrerelease = currentVersion.includes("-");
|
|
30
31
|
if (!isPrerelease) {
|
|
31
32
|
try {
|
package/dist/core/dev/restart.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import * as vite from "vite";
|
|
3
|
-
import { globalContentLayer } from "../../content/
|
|
3
|
+
import { globalContentLayer } from "../../content/instance.js";
|
|
4
4
|
import { attachContentServerListeners } from "../../content/server-listeners.js";
|
|
5
5
|
import { eventCliSession, telemetry } from "../../events/index.js";
|
|
6
6
|
import { SETTINGS_FILE } from "../../preferences/constants.js";
|
package/dist/core/sync/index.js
CHANGED
|
@@ -6,7 +6,8 @@ import colors from "piccolore";
|
|
|
6
6
|
import { createServer } from "vite";
|
|
7
7
|
import { syncFonts } from "../../assets/fonts/sync.js";
|
|
8
8
|
import { CONTENT_TYPES_FILE } from "../../content/consts.js";
|
|
9
|
-
import { getDataStoreFile
|
|
9
|
+
import { getDataStoreFile } from "../../content/content-layer.js";
|
|
10
|
+
import { globalContentLayer } from "../../content/instance.js";
|
|
10
11
|
import { createContentTypesGenerator } from "../../content/index.js";
|
|
11
12
|
import { MutableDataStore } from "../../content/mutable-data-store.js";
|
|
12
13
|
import { getContentPaths, globalContentConfigObserver } from "../../content/utils.js";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AstroAdapterFeatures, MiddlewareMode } from '../types/public/integrations.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the middleware mode from adapter features.
|
|
4
|
+
* Handles backward compatibility with the deprecated `edgeMiddleware` flag.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* // New way
|
|
9
|
+
* resolveMiddlewareMode({ middlewareMode: 'always' }) // 'always'
|
|
10
|
+
*
|
|
11
|
+
* // Backward compatibility
|
|
12
|
+
* resolveMiddlewareMode({ edgeMiddleware: true }) // 'edge'
|
|
13
|
+
* resolveMiddlewareMode({ edgeMiddleware: false }) // 'classic'
|
|
14
|
+
*
|
|
15
|
+
* // Default
|
|
16
|
+
* resolveMiddlewareMode({}) // 'classic'
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveMiddlewareMode(features?: AstroAdapterFeatures): MiddlewareMode;
|
|
@@ -5,7 +5,7 @@ import { mergeConfig as mergeViteConfig } from "vite";
|
|
|
5
5
|
import astroIntegrationActionsRouteHandler from "../actions/integration.js";
|
|
6
6
|
import { isActionsFilePresent } from "../actions/utils.js";
|
|
7
7
|
import { CONTENT_LAYER_TYPE } from "../content/consts.js";
|
|
8
|
-
import { globalContentLayer } from "../content/
|
|
8
|
+
import { globalContentLayer } from "../content/instance.js";
|
|
9
9
|
import { globalContentConfigObserver } from "../content/utils.js";
|
|
10
10
|
import { buildClientDirectiveEntrypoint } from "../core/client-directive/index.js";
|
|
11
11
|
import { mergeConfig } from "../core/config/merge.js";
|
|
@@ -21,6 +21,7 @@ import { ASTRO_RENDERERS_MODULE_ID } from "../vite-plugin-renderers/index.js";
|
|
|
21
21
|
import { ASTRO_ROUTES_MODULE_ID } from "../vite-plugin-routes/index.js";
|
|
22
22
|
import { sessionConfigToManifest } from "../core/session/utils.js";
|
|
23
23
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
|
|
24
|
+
import { resolveMiddlewareMode } from "../integrations/adapter-utils.js";
|
|
24
25
|
const SERIALIZED_MANIFEST_ID = "virtual:astro:manifest";
|
|
25
26
|
const SERIALIZED_MANIFEST_RESOLVED_ID = "\0" + SERIALIZED_MANIFEST_ID;
|
|
26
27
|
function serializedManifestPlugin({
|
|
@@ -133,6 +134,7 @@ async function createSerializedManifest(settings) {
|
|
|
133
134
|
buildFormat: settings.config.build.format,
|
|
134
135
|
compressHTML: settings.config.compressHTML,
|
|
135
136
|
serverLike: settings.buildOutput === "server",
|
|
137
|
+
middlewareMode: resolveMiddlewareMode(settings.adapter?.adapterFeatures),
|
|
136
138
|
assets: [],
|
|
137
139
|
entryModules: {},
|
|
138
140
|
routes: [],
|
|
@@ -147,6 +149,8 @@ async function createSerializedManifest(settings) {
|
|
|
147
149
|
inlinedScripts: [],
|
|
148
150
|
i18n: i18nManifest,
|
|
149
151
|
checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
|
|
152
|
+
actionBodySizeLimit: settings.config.security?.actionBodySizeLimit ? settings.config.security.actionBodySizeLimit : 1024 * 1024,
|
|
153
|
+
// 1mb default
|
|
150
154
|
key: await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey()),
|
|
151
155
|
sessionConfig: sessionConfigToManifest(settings.config.session),
|
|
152
156
|
csp,
|
|
@@ -600,6 +600,30 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
600
600
|
* When not configured, `X-Forwarded-Host` headers are not trusted and will be ignored.
|
|
601
601
|
*/
|
|
602
602
|
allowedDomains?: Partial<RemotePattern>[];
|
|
603
|
+
/**
|
|
604
|
+
* @docs
|
|
605
|
+
* @name security.actionBodySizeLimit
|
|
606
|
+
* @kind h4
|
|
607
|
+
* @type {number}
|
|
608
|
+
* @default `1048576` (1 MB)
|
|
609
|
+
* @version 5.18.0
|
|
610
|
+
* @description
|
|
611
|
+
*
|
|
612
|
+
* Sets the maximum size in bytes allowed for action request bodies.
|
|
613
|
+
*
|
|
614
|
+
* By default, action request bodies are limited to 1 MB (1048576 bytes) to prevent abuse.
|
|
615
|
+
* You can increase this limit if your actions need to accept larger payloads, for example when handling file uploads.
|
|
616
|
+
*
|
|
617
|
+
* ```js
|
|
618
|
+
* // astro.config.mjs
|
|
619
|
+
* export default defineConfig({
|
|
620
|
+
* security: {
|
|
621
|
+
* actionBodySizeLimit: 10 * 1024 * 1024 // 10 MB
|
|
622
|
+
* }
|
|
623
|
+
* })
|
|
624
|
+
* ```
|
|
625
|
+
*/
|
|
626
|
+
actionBodySizeLimit?: number;
|
|
603
627
|
/**
|
|
604
628
|
* @docs
|
|
605
629
|
* @name security.csp
|
|
@@ -65,12 +65,22 @@ export type AdapterSupportWithMessage = {
|
|
|
65
65
|
suppress?: 'all' | 'default';
|
|
66
66
|
};
|
|
67
67
|
export type AdapterSupport = AdapterSupportsKind | AdapterSupportWithMessage;
|
|
68
|
+
export type MiddlewareMode = 'classic' | 'edge';
|
|
68
69
|
export interface AstroAdapterFeatures {
|
|
69
70
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
71
|
+
* Creates an edge function that will communicate with the Astro middleware
|
|
72
|
+
*
|
|
73
|
+
* @deprecated Use `middlewareMode: 'edge'` instead
|
|
74
|
+
*/
|
|
75
|
+
edgeMiddleware?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Determines when and how middleware executes:
|
|
78
|
+
* - `'classic'` (default): Middleware runs for prerendered pages at build time, and for SSR pages at request time. Does not run for prerendered pages at request time.
|
|
79
|
+
* - `'edge'`: Middleware is deployed as a separate edge function. Middleware code will not be bundled and imported by all pages during the build.
|
|
80
|
+
*
|
|
81
|
+
* @default 'classic'
|
|
72
82
|
*/
|
|
73
|
-
|
|
83
|
+
middlewareMode?: MiddlewareMode;
|
|
74
84
|
/**
|
|
75
85
|
* Allows you to force a specific output shape for the build. This can be useful for adapters that only work with
|
|
76
86
|
* a specific output type. For example, your adapter might expect a static website so it can create host-specific
|
|
@@ -19,6 +19,7 @@ import { getViteErrorPayload } from "../core/errors/dev/index.js";
|
|
|
19
19
|
import { AstroError, AstroErrorData } from "../core/errors/index.js";
|
|
20
20
|
import { NOOP_MIDDLEWARE_FN } from "../core/middleware/noop-middleware.js";
|
|
21
21
|
import { createViteLoader } from "../core/module-loader/index.js";
|
|
22
|
+
import { resolveMiddlewareMode } from "../integrations/adapter-utils.js";
|
|
22
23
|
import { SERIALIZED_MANIFEST_ID } from "../manifest/serialized.js";
|
|
23
24
|
import { ASTRO_DEV_SERVER_APP_ID } from "../vite-plugin-app/index.js";
|
|
24
25
|
import { baseMiddleware } from "./base.js";
|
|
@@ -137,6 +138,7 @@ async function createDevelopmentManifest(settings) {
|
|
|
137
138
|
compressHTML: settings.config.compressHTML,
|
|
138
139
|
assetsDir: settings.config.build.assets,
|
|
139
140
|
serverLike: settings.buildOutput === "server",
|
|
141
|
+
middlewareMode: resolveMiddlewareMode(settings.adapter?.adapterFeatures),
|
|
140
142
|
assets: /* @__PURE__ */ new Set(),
|
|
141
143
|
entryModules: {},
|
|
142
144
|
routes: [],
|
|
@@ -151,6 +153,8 @@ async function createDevelopmentManifest(settings) {
|
|
|
151
153
|
inlinedScripts: /* @__PURE__ */ new Map(),
|
|
152
154
|
i18n: i18nManifest,
|
|
153
155
|
checkOrigin: (settings.config.security?.checkOrigin && settings.buildOutput === "server") ?? false,
|
|
156
|
+
actionBodySizeLimit: settings.config.security?.actionBodySizeLimit ? settings.config.security.actionBodySizeLimit : 1024 * 1024,
|
|
157
|
+
// 1mb default
|
|
154
158
|
key: hasEnvironmentKey() ? getEnvironmentKey() : createKey(),
|
|
155
159
|
middleware() {
|
|
156
160
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "6.0.0-beta.
|
|
3
|
+
"version": "6.0.0-beta.17",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -151,9 +151,9 @@
|
|
|
151
151
|
"xxhash-wasm": "^1.1.0",
|
|
152
152
|
"yargs-parser": "^22.0.0",
|
|
153
153
|
"zod": "^4.3.6",
|
|
154
|
-
"@astrojs/
|
|
155
|
-
"@astrojs/
|
|
156
|
-
"@astrojs/
|
|
154
|
+
"@astrojs/internal-helpers": "0.8.0-beta.1",
|
|
155
|
+
"@astrojs/markdown-remark": "7.0.0-beta.8",
|
|
156
|
+
"@astrojs/telemetry": "3.3.0"
|
|
157
157
|
},
|
|
158
158
|
"optionalDependencies": {
|
|
159
159
|
"sharp": "^0.34.0"
|