astro 4.5.17 → 4.6.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/@types/astro.d.ts +96 -3
- package/dist/core/app/index.js +8 -0
- package/dist/core/app/middlewares.d.ts +7 -0
- package/dist/core/app/middlewares.js +26 -0
- package/dist/core/app/types.d.ts +2 -1
- package/dist/core/base-pipeline.js +6 -3
- package/dist/core/build/generate.js +3 -2
- package/dist/core/build/plugins/plugin-manifest.js +3 -2
- package/dist/core/config/schema.d.ts +168 -65
- package/dist/core/config/schema.js +20 -13
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.d.ts +3 -11
- package/dist/core/cookies/cookies.js +9 -7
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/dev/utils.js +1 -1
- package/dist/core/errors/errors-data.d.ts +23 -0
- package/dist/core/errors/errors-data.js +13 -1
- package/dist/core/errors/overlay.js +2 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/middleware/vite-plugin.js +8 -0
- package/dist/core/render/index.d.ts +1 -1
- package/dist/core/render/index.js +1 -1
- package/dist/core/render/{result.js → slots.js} +4 -2
- package/dist/core/routing/manifest/create.js +1 -1
- package/dist/i18n/index.d.ts +18 -1
- package/dist/i18n/index.js +107 -0
- package/dist/i18n/middleware.d.ts +1 -1
- package/dist/i18n/middleware.js +40 -81
- package/dist/i18n/utils.d.ts +2 -2
- package/dist/i18n/utils.js +20 -21
- package/dist/runtime/client/dev-toolbar/apps/astro.js +6 -1
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/a11y.js +6 -1
- package/dist/runtime/client/dev-toolbar/apps/settings.js +38 -1
- package/dist/runtime/client/dev-toolbar/apps/utils/window.d.ts +2 -1
- package/dist/runtime/client/dev-toolbar/apps/utils/window.js +18 -2
- package/dist/runtime/client/dev-toolbar/apps/xray.js +6 -1
- package/dist/runtime/client/dev-toolbar/entrypoint.js +3 -1
- package/dist/runtime/client/dev-toolbar/settings.d.ts +4 -1
- package/dist/runtime/client/dev-toolbar/settings.js +2 -1
- package/dist/runtime/client/dev-toolbar/toolbar.d.ts +2 -0
- package/dist/runtime/client/dev-toolbar/toolbar.js +25 -3
- package/dist/runtime/client/dev-toolbar/ui-library/index.d.ts +1 -0
- package/dist/runtime/client/dev-toolbar/ui-library/index.js +2 -0
- package/dist/runtime/client/dev-toolbar/ui-library/select.d.ts +15 -0
- package/dist/runtime/client/dev-toolbar/ui-library/select.js +100 -0
- package/dist/runtime/client/dev-toolbar/ui-library/window.d.ts +9 -0
- package/dist/runtime/client/dev-toolbar/ui-library/window.js +53 -3
- package/dist/runtime/server/render/astro/render-template.d.ts +1 -1
- package/dist/runtime/server/render/util.js +5 -4
- package/dist/virtual-modules/i18n.d.ts +102 -0
- package/dist/virtual-modules/i18n.js +86 -6
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/dist/vite-plugin-astro-server/route.js +2 -2
- package/package.json +6 -5
- /package/dist/core/render/{result.d.ts → slots.d.ts} +0 -0
package/dist/@types/astro.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type { AstroIntegrationLogger, Logger, LoggerLevel } from '../core/logger
|
|
|
17
17
|
import type { AstroPreferences } from '../preferences/index.js';
|
|
18
18
|
import type { AstroDevToolbar, DevToolbarCanvas } from '../runtime/client/dev-toolbar/toolbar.js';
|
|
19
19
|
import type { Icon } from '../runtime/client/dev-toolbar/ui-library/icons.js';
|
|
20
|
-
import type { DevToolbarBadge, DevToolbarButton, DevToolbarCard, DevToolbarHighlight, DevToolbarIcon, DevToolbarToggle, DevToolbarTooltip, DevToolbarWindow } from '../runtime/client/dev-toolbar/ui-library/index.js';
|
|
20
|
+
import type { DevToolbarBadge, DevToolbarButton, DevToolbarCard, DevToolbarHighlight, DevToolbarIcon, DevToolbarSelect, DevToolbarToggle, DevToolbarTooltip, DevToolbarWindow } from '../runtime/client/dev-toolbar/ui-library/index.js';
|
|
21
21
|
import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server/index.js';
|
|
22
22
|
import type { TransitionBeforePreparationEvent, TransitionBeforeSwapEvent } from '../transitions/events.js';
|
|
23
23
|
import type { DeepPartial, OmitIndexSignature, Simplify } from '../type-utils.js';
|
|
@@ -1375,6 +1375,7 @@ export interface AstroUserConfig {
|
|
|
1375
1375
|
* @description
|
|
1376
1376
|
*
|
|
1377
1377
|
* Controls the routing strategy to determine your site URLs. Set this based on your folder/URL path configuration for your default language.
|
|
1378
|
+
*
|
|
1378
1379
|
*/
|
|
1379
1380
|
routing?: {
|
|
1380
1381
|
/**
|
|
@@ -1393,6 +1394,18 @@ export interface AstroUserConfig {
|
|
|
1393
1394
|
* When `true`, all URLs will display a language prefix.
|
|
1394
1395
|
* URLs will be of the form `example.com/[locale]/content/` for every route, including the default language.
|
|
1395
1396
|
* Localized folders are used for every language, including the default.
|
|
1397
|
+
*
|
|
1398
|
+
* ```js
|
|
1399
|
+
* export default defineConfig({
|
|
1400
|
+
* i18n: {
|
|
1401
|
+
* defaultLocale: "en",
|
|
1402
|
+
* locales: ["en", "fr", "pt-br", "es"],
|
|
1403
|
+
* routing: {
|
|
1404
|
+
* prefixDefaultLocale: true,
|
|
1405
|
+
* }
|
|
1406
|
+
* }
|
|
1407
|
+
* })
|
|
1408
|
+
* ```
|
|
1396
1409
|
*/
|
|
1397
1410
|
prefixDefaultLocale?: boolean;
|
|
1398
1411
|
/**
|
|
@@ -1433,7 +1446,32 @@ export interface AstroUserConfig {
|
|
|
1433
1446
|
* - `"pathname": The strategy is applied to the pathname of the URLs
|
|
1434
1447
|
*/
|
|
1435
1448
|
strategy?: 'pathname';
|
|
1436
|
-
}
|
|
1449
|
+
} |
|
|
1450
|
+
/**
|
|
1451
|
+
*
|
|
1452
|
+
* @docs
|
|
1453
|
+
* @name i18n.routing.manual
|
|
1454
|
+
* @kind h4
|
|
1455
|
+
* @type {string}
|
|
1456
|
+
* @version 4.6.0
|
|
1457
|
+
* @description
|
|
1458
|
+
* When this option is enabled, Astro will **disable** its i18n middleware so that you can implement your own custom logic. No other `routing` options (e.g. `prefixDefaultLocale`) may be configured with `routing: "manual"`.
|
|
1459
|
+
*
|
|
1460
|
+
* You will be responsible for writing your own routing logic, or executing Astro's i18n middleware manually alongside your own.
|
|
1461
|
+
*
|
|
1462
|
+
* ```js
|
|
1463
|
+
* export default defineConfig({
|
|
1464
|
+
* i18n: {
|
|
1465
|
+
* defaultLocale: "en",
|
|
1466
|
+
* locales: ["en", "fr", "pt-br", "es"],
|
|
1467
|
+
* routing: {
|
|
1468
|
+
* prefixDefaultLocale: true,
|
|
1469
|
+
* }
|
|
1470
|
+
* }
|
|
1471
|
+
* })
|
|
1472
|
+
* ```
|
|
1473
|
+
*/
|
|
1474
|
+
'manual';
|
|
1437
1475
|
/**
|
|
1438
1476
|
* @name i18n.domains
|
|
1439
1477
|
* @type {Record<string, string> }
|
|
@@ -1468,7 +1506,7 @@ export interface AstroUserConfig {
|
|
|
1468
1506
|
* })
|
|
1469
1507
|
* ```
|
|
1470
1508
|
*
|
|
1471
|
-
* Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/
|
|
1509
|
+
* Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/reference/api-reference/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
|
|
1472
1510
|
*
|
|
1473
1511
|
* See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains) for more details, including the limitations of this feature.
|
|
1474
1512
|
*/
|
|
@@ -1692,6 +1730,60 @@ export interface AstroUserConfig {
|
|
|
1692
1730
|
* See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains-experimental) for more details, including the limitations of this experimental feature.
|
|
1693
1731
|
*/
|
|
1694
1732
|
i18nDomains?: boolean;
|
|
1733
|
+
/**
|
|
1734
|
+
* @docs
|
|
1735
|
+
* @name experimental.security
|
|
1736
|
+
* @type {boolean}
|
|
1737
|
+
* @default `false`
|
|
1738
|
+
* @version 4.6.0
|
|
1739
|
+
* @description
|
|
1740
|
+
*
|
|
1741
|
+
* Enables CSRF protection for Astro websites.
|
|
1742
|
+
*
|
|
1743
|
+
* The CSRF protection works only for pages rendered on demand (SSR) using `server` or `hybrid` mode. The pages must opt out of prerendering in `hybrid` mode.
|
|
1744
|
+
*
|
|
1745
|
+
* ```js
|
|
1746
|
+
* // astro.config.mjs
|
|
1747
|
+
* export default defineConfig({
|
|
1748
|
+
* output: "server",
|
|
1749
|
+
* experimental: {
|
|
1750
|
+
* security: {
|
|
1751
|
+
* csrfProtection: {
|
|
1752
|
+
* origin: true
|
|
1753
|
+
* }
|
|
1754
|
+
* }
|
|
1755
|
+
* }
|
|
1756
|
+
* })
|
|
1757
|
+
* ```
|
|
1758
|
+
*/
|
|
1759
|
+
security?: {
|
|
1760
|
+
/**
|
|
1761
|
+
* @name security.csrfProtection
|
|
1762
|
+
* @type {object}
|
|
1763
|
+
* @default '{}'
|
|
1764
|
+
* @version 4.6.0
|
|
1765
|
+
* @description
|
|
1766
|
+
*
|
|
1767
|
+
* Allows you to enable security measures to prevent CSRF attacks: https://owasp.org/www-community/attacks/csrf
|
|
1768
|
+
*/
|
|
1769
|
+
csrfProtection?: {
|
|
1770
|
+
/**
|
|
1771
|
+
* @name security.csrfProtection.origin
|
|
1772
|
+
* @type {boolean}
|
|
1773
|
+
* @default 'false'
|
|
1774
|
+
* @version 4.6.0
|
|
1775
|
+
* @description
|
|
1776
|
+
*
|
|
1777
|
+
* When enabled, performs a check that the "origin" header, automatically passed by all modern browsers, matches the URL sent by each `Request`.
|
|
1778
|
+
*
|
|
1779
|
+
* The "origin" check is executed only for pages rendered on demand, and only for the requests `POST, `PATCH`, `DELETE` and `PUT` with
|
|
1780
|
+
* the following `content-type` header: 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain'.
|
|
1781
|
+
*
|
|
1782
|
+
* If the "origin" header doesn't match the `pathname` of the request, Astro will return a 403 status code and will not render the page.
|
|
1783
|
+
*/
|
|
1784
|
+
origin?: boolean;
|
|
1785
|
+
};
|
|
1786
|
+
};
|
|
1695
1787
|
};
|
|
1696
1788
|
}
|
|
1697
1789
|
/**
|
|
@@ -2628,6 +2720,7 @@ declare global {
|
|
|
2628
2720
|
'astro-dev-toolbar-button': DevToolbarButton;
|
|
2629
2721
|
'astro-dev-toolbar-icon': DevToolbarIcon;
|
|
2630
2722
|
'astro-dev-toolbar-card': DevToolbarCard;
|
|
2723
|
+
'astro-dev-toolbar-select': DevToolbarSelect;
|
|
2631
2724
|
'astro-dev-overlay': AstroDevToolbar;
|
|
2632
2725
|
'astro-dev-overlay-window': DevToolbarWindow;
|
|
2633
2726
|
'astro-dev-overlay-plugin-canvas': DevToolbarCanvas;
|
package/dist/core/app/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { getSetCookiesFromResponse } from "../cookies/index.js";
|
|
|
11
11
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
12
12
|
import { consoleLogDestination } from "../logger/console.js";
|
|
13
13
|
import { AstroIntegrationLogger, Logger } from "../logger/core.js";
|
|
14
|
+
import { sequence } from "../middleware/index.js";
|
|
14
15
|
import {
|
|
15
16
|
appendForwardSlash,
|
|
16
17
|
collapseDuplicateSlashes,
|
|
@@ -23,6 +24,7 @@ import { RenderContext } from "../render-context.js";
|
|
|
23
24
|
import { createAssetLink } from "../render/ssr-element.js";
|
|
24
25
|
import { ensure404Route } from "../routing/astro-designed-error-pages.js";
|
|
25
26
|
import { matchRoute } from "../routing/match.js";
|
|
27
|
+
import { createOriginCheckMiddleware } from "./middlewares.js";
|
|
26
28
|
import { AppPipeline } from "./pipeline.js";
|
|
27
29
|
import { deserializeManifest } from "./common.js";
|
|
28
30
|
class App {
|
|
@@ -58,6 +60,12 @@ class App {
|
|
|
58
60
|
* @private
|
|
59
61
|
*/
|
|
60
62
|
#createPipeline(streaming = false) {
|
|
63
|
+
if (this.#manifest.checkOrigin) {
|
|
64
|
+
this.#manifest.middleware = sequence(
|
|
65
|
+
createOriginCheckMiddleware(),
|
|
66
|
+
this.#manifest.middleware
|
|
67
|
+
);
|
|
68
|
+
}
|
|
61
69
|
return AppPipeline.create({
|
|
62
70
|
logger: this.#logger,
|
|
63
71
|
manifest: this.#manifest,
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineMiddleware } from "../middleware/index.js";
|
|
2
|
+
const FORM_CONTENT_TYPES = [
|
|
3
|
+
"application/x-www-form-urlencoded",
|
|
4
|
+
"multipart/form-data",
|
|
5
|
+
"text/plain"
|
|
6
|
+
];
|
|
7
|
+
function createOriginCheckMiddleware() {
|
|
8
|
+
return defineMiddleware((context, next) => {
|
|
9
|
+
const { request, url } = context;
|
|
10
|
+
const contentType = request.headers.get("content-type");
|
|
11
|
+
if (contentType) {
|
|
12
|
+
if (FORM_CONTENT_TYPES.includes(contentType.toLowerCase())) {
|
|
13
|
+
const forbidden = (request.method === "POST" || request.method === "PUT" || request.method === "PATCH" || request.method === "DELETE") && request.headers.get("origin") !== url.origin;
|
|
14
|
+
if (forbidden) {
|
|
15
|
+
return new Response(`Cross-site ${request.method} form submissions are forbidden`, {
|
|
16
|
+
status: 403
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return next();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
createOriginCheckMiddleware
|
|
26
|
+
};
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -51,9 +51,10 @@ export type SSRManifest = {
|
|
|
51
51
|
pageMap?: Map<ComponentPath, ImportComponentInstance>;
|
|
52
52
|
i18n: SSRManifestI18n | undefined;
|
|
53
53
|
middleware: MiddlewareHandler;
|
|
54
|
+
checkOrigin: boolean;
|
|
54
55
|
};
|
|
55
56
|
export type SSRManifestI18n = {
|
|
56
|
-
fallback
|
|
57
|
+
fallback: Record<string, string> | undefined;
|
|
57
58
|
strategy: RoutingStrategies;
|
|
58
59
|
locales: Locales;
|
|
59
60
|
defaultLocale: string;
|
|
@@ -17,9 +17,12 @@ class Pipeline {
|
|
|
17
17
|
this.middleware = middleware;
|
|
18
18
|
this.routeCache = routeCache;
|
|
19
19
|
this.site = site;
|
|
20
|
-
this.internalMiddleware = [
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
this.internalMiddleware = [];
|
|
21
|
+
if (i18n?.strategy !== "manual") {
|
|
22
|
+
this.internalMiddleware.push(
|
|
23
|
+
createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
23
26
|
}
|
|
24
27
|
internalMiddleware;
|
|
25
28
|
}
|
|
@@ -411,7 +411,7 @@ function createBuildManifest(settings, internals, renderers, middleware) {
|
|
|
411
411
|
if (settings.config.i18n) {
|
|
412
412
|
i18nManifest = {
|
|
413
413
|
fallback: settings.config.i18n.fallback,
|
|
414
|
-
strategy: toRoutingStrategy(settings.config.i18n),
|
|
414
|
+
strategy: toRoutingStrategy(settings.config.i18n.routing, settings.config.i18n.domains),
|
|
415
415
|
defaultLocale: settings.config.i18n.defaultLocale,
|
|
416
416
|
locales: settings.config.i18n.locales,
|
|
417
417
|
domainLookupTable: {}
|
|
@@ -433,7 +433,8 @@ function createBuildManifest(settings, internals, renderers, middleware) {
|
|
|
433
433
|
componentMetadata: internals.componentMetadata,
|
|
434
434
|
i18n: i18nManifest,
|
|
435
435
|
buildFormat: settings.config.build.format,
|
|
436
|
-
middleware
|
|
436
|
+
middleware,
|
|
437
|
+
checkOrigin: settings.config.experimental.security?.csrfProtection?.origin ?? false
|
|
437
438
|
};
|
|
438
439
|
}
|
|
439
440
|
export {
|
|
@@ -192,7 +192,7 @@ function buildManifest(opts, internals, staticFiles) {
|
|
|
192
192
|
if (settings.config.i18n) {
|
|
193
193
|
i18nManifest = {
|
|
194
194
|
fallback: settings.config.i18n.fallback,
|
|
195
|
-
strategy: toRoutingStrategy(settings.config.i18n),
|
|
195
|
+
strategy: toRoutingStrategy(settings.config.i18n.routing, settings.config.i18n.domains),
|
|
196
196
|
locales: settings.config.i18n.locales,
|
|
197
197
|
defaultLocale: settings.config.i18n.defaultLocale,
|
|
198
198
|
domainLookupTable
|
|
@@ -213,7 +213,8 @@ function buildManifest(opts, internals, staticFiles) {
|
|
|
213
213
|
inlinedScripts: Array.from(internals.inlinedScripts),
|
|
214
214
|
assets: staticFiles.map(prefixAssetPath),
|
|
215
215
|
i18n: i18nManifest,
|
|
216
|
-
buildFormat: settings.config.build.format
|
|
216
|
+
buildFormat: settings.config.build.format,
|
|
217
|
+
checkOrigin: settings.config.experimental.security?.csrfProtection?.origin ?? false
|
|
217
218
|
};
|
|
218
219
|
}
|
|
219
220
|
export {
|