astro 4.2.8 → 4.3.1
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/astro-jsx.d.ts +1 -0
- package/astro.js +1 -1
- package/dist/@types/astro.d.ts +93 -10
- package/dist/content/types-generator.js +2 -1
- package/dist/core/app/index.js +55 -2
- package/dist/core/app/node.d.ts +1 -1
- package/dist/core/app/node.js +18 -18
- package/dist/core/app/types.d.ts +2 -1
- package/dist/core/build/buildPipeline.js +3 -1
- package/dist/core/build/common.d.ts +3 -3
- package/dist/core/build/common.js +20 -2
- package/dist/core/build/generate.js +12 -3
- package/dist/core/build/plugins/plugin-manifest.js +12 -3
- package/dist/core/build/plugins/plugin-ssr.js +8 -1
- package/dist/core/build/util.js +1 -0
- package/dist/core/config/schema.d.ts +305 -36
- package/dist/core/config/schema.js +95 -18
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/dev/restart.js +11 -3
- package/dist/core/errors/errors-data.d.ts +20 -10
- package/dist/core/errors/errors-data.js +8 -2
- package/dist/core/errors/errors.js +1 -1
- package/dist/core/logger/vite.js +7 -1
- package/dist/core/messages.d.ts +5 -0
- package/dist/core/messages.js +6 -2
- package/dist/core/render/context.js +1 -1
- package/dist/core/routing/manifest/serialization.js +2 -1
- package/dist/core/routing/match.js +1 -1
- package/dist/core/sync/index.js +12 -1
- package/dist/i18n/index.d.ts +9 -7
- package/dist/i18n/index.js +61 -12
- package/dist/i18n/middleware.js +82 -24
- package/dist/i18n/vite-plugin-i18n.d.ts +1 -0
- package/dist/i18n/vite-plugin-i18n.js +9 -2
- package/dist/integrations/astroFeaturesValidation.d.ts +2 -2
- package/dist/integrations/astroFeaturesValidation.js +20 -2
- package/dist/integrations/index.d.ts +0 -1
- package/dist/integrations/index.js +2 -8
- package/dist/virtual-modules/i18n.js +12 -3
- package/dist/vite-plugin-astro-server/base.js +7 -2
- package/dist/vite-plugin-astro-server/plugin.js +2 -1
- package/dist/vite-plugin-astro-server/route.js +3 -2
- package/dist/vite-plugin-markdown/images.js +5 -2
- package/package.json +3 -3
- package/types.d.ts +4 -1
package/astro-jsx.d.ts
CHANGED
package/astro.js
CHANGED
|
@@ -20,8 +20,8 @@ async function main() {
|
|
|
20
20
|
const version = process.versions.node;
|
|
21
21
|
// Fast-path for higher Node.js versions
|
|
22
22
|
if ((parseInt(version) || 0) <= skipSemverCheckIfAbove) {
|
|
23
|
+
const semver = await import('semver');
|
|
23
24
|
try {
|
|
24
|
-
const semver = await import('semver');
|
|
25
25
|
if (!semver.satisfies(version, engines)) {
|
|
26
26
|
await errorNodeUnsupported();
|
|
27
27
|
return;
|
package/dist/@types/astro.d.ts
CHANGED
|
@@ -137,7 +137,7 @@ export interface AstroGlobal<Props extends Record<string, any> = Record<string,
|
|
|
137
137
|
* const { name } = Astro.props
|
|
138
138
|
* ```
|
|
139
139
|
*
|
|
140
|
-
* [Astro reference](https://docs.astro.build/en/
|
|
140
|
+
* [Astro reference](https://docs.astro.build/en/basics/astro-components/#component-props)
|
|
141
141
|
*/
|
|
142
142
|
props: AstroSharedContext<Props, Params>['props'];
|
|
143
143
|
/** Information about the current request. This is a standard [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object
|
|
@@ -685,12 +685,13 @@ export interface AstroUserConfig {
|
|
|
685
685
|
/**
|
|
686
686
|
* @docs
|
|
687
687
|
* @name build.format
|
|
688
|
-
* @typeraw {('file' | 'directory')}
|
|
688
|
+
* @typeraw {('file' | 'directory' | 'preserve')}
|
|
689
689
|
* @default `'directory'`
|
|
690
690
|
* @description
|
|
691
691
|
* Control the output file format of each page. This value may be set by an adapter for you.
|
|
692
|
-
* -
|
|
693
|
-
* -
|
|
692
|
+
* - `'file'`: Astro will generate an HTML file named for each page route. (e.g. `src/pages/about.astro` and `src/pages/about/index.astro` both build the file `/about.html`)
|
|
693
|
+
* - `'directory'`: Astro will generate a directory with a nested `index.html` file for each page. (e.g. `src/pages/about.astro` and `src/pages/about/index.astro` both build the file `/about/index.html`)
|
|
694
|
+
* - `'preserve'`: Astro will generate HTML files exactly as they appear in your source folder. (e.g. `src/pages/about.astro` builds `/about.html` and `src/pages/about/index.astro` builds the file `/about/index.html`)
|
|
694
695
|
*
|
|
695
696
|
* ```js
|
|
696
697
|
* {
|
|
@@ -714,7 +715,7 @@ export interface AstroUserConfig {
|
|
|
714
715
|
* - `directory` - Set `trailingSlash: 'always'`
|
|
715
716
|
* - `file` - Set `trailingSlash: 'never'`
|
|
716
717
|
*/
|
|
717
|
-
format?: 'file' | 'directory';
|
|
718
|
+
format?: 'file' | 'directory' | 'preserve';
|
|
718
719
|
/**
|
|
719
720
|
* @docs
|
|
720
721
|
* @name build.client
|
|
@@ -1412,6 +1413,45 @@ export interface AstroUserConfig {
|
|
|
1412
1413
|
* - `"pathanme": The strategy is applied to the pathname of the URLs
|
|
1413
1414
|
*/
|
|
1414
1415
|
strategy: 'pathname';
|
|
1416
|
+
/**
|
|
1417
|
+
* @name i18n.domains
|
|
1418
|
+
* @type {Record<string, string> }
|
|
1419
|
+
* @default '{}'
|
|
1420
|
+
* @version 4.3.0
|
|
1421
|
+
* @description
|
|
1422
|
+
*
|
|
1423
|
+
* Configures the URL pattern of one or more supported languages to use a custom domain (or sub-domain).
|
|
1424
|
+
*
|
|
1425
|
+
* When a locale is mapped to a domain, a `/[locale]/` path prefix will not be used.
|
|
1426
|
+
* However, localized folders within `src/pages/` are still required, including for your configured `defaultLocale`.
|
|
1427
|
+
*
|
|
1428
|
+
* Any other locale not configured will default to a localized path-based URL according to your `prefixDefaultLocale` strategy (e.g. `https://example.com/[locale]/blog`).
|
|
1429
|
+
*
|
|
1430
|
+
* ```js
|
|
1431
|
+
* //astro.config.mjs
|
|
1432
|
+
* export default defineConfig({
|
|
1433
|
+
* site: "https://example.com",
|
|
1434
|
+
* output: "server", // required, with no prerendered pages
|
|
1435
|
+
* adapter: node({
|
|
1436
|
+
* mode: 'standalone',
|
|
1437
|
+
* }),
|
|
1438
|
+
* i18n: {
|
|
1439
|
+
* defaultLocale: "en",
|
|
1440
|
+
* locales: ["en", "fr", "pt-br", "es"],
|
|
1441
|
+
* prefixDefaultLocale: false,
|
|
1442
|
+
* domains: {
|
|
1443
|
+
* fr: "https://fr.example.com",
|
|
1444
|
+
* es: "https://example.es"
|
|
1445
|
+
* }
|
|
1446
|
+
* },
|
|
1447
|
+
* })
|
|
1448
|
+
* ```
|
|
1449
|
+
*
|
|
1450
|
+
* Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
|
|
1451
|
+
*
|
|
1452
|
+
* See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains) for more details, including the limitations of this feature.
|
|
1453
|
+
*/
|
|
1454
|
+
domains?: Record<string, string>;
|
|
1415
1455
|
};
|
|
1416
1456
|
};
|
|
1417
1457
|
/** ⚠️ WARNING: SUBJECT TO CHANGE */
|
|
@@ -1517,7 +1557,7 @@ export interface AstroUserConfig {
|
|
|
1517
1557
|
* @version 4.2.0
|
|
1518
1558
|
* @description
|
|
1519
1559
|
*
|
|
1520
|
-
* Prioritizes redirects and injected routes equally alongside file-based project routes, following the same [route priority order rules](https://docs.astro.build/en/
|
|
1560
|
+
* Prioritizes redirects and injected routes equally alongside file-based project routes, following the same [route priority order rules](https://docs.astro.build/en/guides/routing/#route-priority-order) for all routes.
|
|
1521
1561
|
*
|
|
1522
1562
|
* This allows more control over routing in your project by not automatically prioritizing certain types of routes, and standardizes the route priority ordering for all routes.
|
|
1523
1563
|
*
|
|
@@ -1538,6 +1578,48 @@ export interface AstroUserConfig {
|
|
|
1538
1578
|
* In the event of route collisions, where two routes of equal route priority attempt to build the same URL, Astro will log a warning identifying the conflicting routes.
|
|
1539
1579
|
*/
|
|
1540
1580
|
globalRoutePriority?: boolean;
|
|
1581
|
+
/**
|
|
1582
|
+
* @docs
|
|
1583
|
+
* @name experimental.i18nDomains
|
|
1584
|
+
* @type {boolean}
|
|
1585
|
+
* @default `false`
|
|
1586
|
+
* @version 4.3.0
|
|
1587
|
+
* @description
|
|
1588
|
+
*
|
|
1589
|
+
* Enables domain support for the [experimental `domains` routing strategy](https://docs.astro.build/en/guides/internationalization/#domains-experimental) which allows you to configure the URL pattern of one or more supported languages to use a custom domain (or sub-domain).
|
|
1590
|
+
*
|
|
1591
|
+
* When a locale is mapped to a domain, a `/[locale]/` path prefix will not be used. However, localized folders within `src/pages/` are still required, including for your configured `defaultLocale`.
|
|
1592
|
+
*
|
|
1593
|
+
* Any other locale not configured will default to a localized path-based URL according to your `prefixDefaultLocale` strategy (e.g. `https://example.com/[locale]/blog`).
|
|
1594
|
+
*
|
|
1595
|
+
* ```js
|
|
1596
|
+
* //astro.config.mjs
|
|
1597
|
+
* export default defineConfig({
|
|
1598
|
+
* site: "https://example.com",
|
|
1599
|
+
* output: "server", // required, with no prerendered pages
|
|
1600
|
+
* adapter: node({
|
|
1601
|
+
* mode: 'standalone',
|
|
1602
|
+
* }),
|
|
1603
|
+
* i18n: {
|
|
1604
|
+
* defaultLocale: "en",
|
|
1605
|
+
* locales: ["en", "fr", "pt-br", "es"],
|
|
1606
|
+
* prefixDefaultLocale: false,
|
|
1607
|
+
* domains: {
|
|
1608
|
+
* fr: "https://fr.example.com",
|
|
1609
|
+
* es: "https://example.es",
|
|
1610
|
+
* },
|
|
1611
|
+
* },
|
|
1612
|
+
* experimental: {
|
|
1613
|
+
* i18nDomains: true,
|
|
1614
|
+
* },
|
|
1615
|
+
* });
|
|
1616
|
+
* ```
|
|
1617
|
+
*
|
|
1618
|
+
* Both page routes built and URLs returned by the `astro:i18n` helper functions [`getAbsoluteLocaleUrl()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurl) and [`getAbsoluteLocaleUrlList()`](https://docs.astro.build/en/guides/internationalization/#getabsolutelocaleurllist) will use the options set in `i18n.domains`.
|
|
1619
|
+
*
|
|
1620
|
+
* See the [Internationalization Guide](https://docs.astro.build/en/guides/internationalization/#domains-experimental) for more details, including the limitations of this experimental feature.
|
|
1621
|
+
*/
|
|
1622
|
+
i18nDomains?: boolean;
|
|
1541
1623
|
};
|
|
1542
1624
|
}
|
|
1543
1625
|
/**
|
|
@@ -1767,7 +1849,7 @@ export type GetStaticPathsResultKeyed = GetStaticPathsResult & {
|
|
|
1767
1849
|
keyed: Map<string, GetStaticPathsItem>;
|
|
1768
1850
|
};
|
|
1769
1851
|
/**
|
|
1770
|
-
* Return an array of pages to generate for a [dynamic route](https://docs.astro.build/en/
|
|
1852
|
+
* Return an array of pages to generate for a [dynamic route](https://docs.astro.build/en/guides/routing/#dynamic-routes). (**SSG Only**)
|
|
1771
1853
|
*
|
|
1772
1854
|
* [Astro Reference](https://docs.astro.build/en/reference/api-reference/#getstaticpaths)
|
|
1773
1855
|
*/
|
|
@@ -1918,7 +2000,7 @@ export type AstroFeatureMap = {
|
|
|
1918
2000
|
/**
|
|
1919
2001
|
* List of features that orbit around the i18n routing
|
|
1920
2002
|
*/
|
|
1921
|
-
|
|
2003
|
+
i18nDomains?: SupportsKind;
|
|
1922
2004
|
};
|
|
1923
2005
|
export interface AstroAssetsFeature {
|
|
1924
2006
|
supportKind?: SupportsKind;
|
|
@@ -1933,9 +2015,9 @@ export interface AstroAssetsFeature {
|
|
|
1933
2015
|
}
|
|
1934
2016
|
export interface AstroInternationalizationFeature {
|
|
1935
2017
|
/**
|
|
1936
|
-
*
|
|
2018
|
+
* The adapter should be able to create the proper redirects
|
|
1937
2019
|
*/
|
|
1938
|
-
|
|
2020
|
+
domains?: SupportsKind;
|
|
1939
2021
|
}
|
|
1940
2022
|
export type Locales = (string | {
|
|
1941
2023
|
codes: string[];
|
|
@@ -2288,6 +2370,7 @@ export interface RouteData {
|
|
|
2288
2370
|
redirect?: RedirectConfig;
|
|
2289
2371
|
redirectRoute?: RouteData;
|
|
2290
2372
|
fallbackRoutes: RouteData[];
|
|
2373
|
+
isIndex: boolean;
|
|
2291
2374
|
}
|
|
2292
2375
|
export type RedirectRouteData = RouteData & {
|
|
2293
2376
|
redirect: string;
|
|
@@ -266,7 +266,8 @@ function invalidateVirtualMod(viteServer) {
|
|
|
266
266
|
}
|
|
267
267
|
function normalizeConfigPath(from, to) {
|
|
268
268
|
const configPath = path.relative(from, to).replace(/\.ts$/, ".js");
|
|
269
|
-
|
|
269
|
+
const normalizedPath = configPath.replaceAll("\\", "/");
|
|
270
|
+
return `"${isRelativePath(configPath) ? "" : "./"}${normalizedPath}"`;
|
|
270
271
|
}
|
|
271
272
|
async function writeContentFiles({
|
|
272
273
|
fs,
|
package/dist/core/app/index.js
CHANGED
|
@@ -5,7 +5,9 @@ import { consoleLogDestination } from "../logger/console.js";
|
|
|
5
5
|
import { AstroIntegrationLogger, Logger } from "../logger/core.js";
|
|
6
6
|
import { sequence } from "../middleware/index.js";
|
|
7
7
|
import {
|
|
8
|
+
appendForwardSlash,
|
|
8
9
|
collapseDuplicateSlashes,
|
|
10
|
+
joinPaths,
|
|
9
11
|
prependForwardSlash,
|
|
10
12
|
removeTrailingForwardSlash
|
|
11
13
|
} from "../path.js";
|
|
@@ -19,6 +21,7 @@ import {
|
|
|
19
21
|
} from "../render/ssr-element.js";
|
|
20
22
|
import { matchRoute } from "../routing/match.js";
|
|
21
23
|
import { SSRRoutePipeline } from "./ssrPipeline.js";
|
|
24
|
+
import { normalizeTheLocale } from "../../i18n/index.js";
|
|
22
25
|
import { deserializeManifest } from "./common.js";
|
|
23
26
|
const localsSymbol = Symbol.for("astro.locals");
|
|
24
27
|
const clientAddressSymbol = Symbol.for("astro.clientAddress");
|
|
@@ -108,12 +111,62 @@ class App {
|
|
|
108
111
|
const url = new URL(request.url);
|
|
109
112
|
if (this.#manifest.assets.has(url.pathname))
|
|
110
113
|
return void 0;
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
let pathname = this.#computePathnameFromDomain(request);
|
|
115
|
+
if (!pathname) {
|
|
116
|
+
pathname = prependForwardSlash(this.removeBase(url.pathname));
|
|
117
|
+
}
|
|
118
|
+
let routeData = matchRoute(pathname, this.#manifestData);
|
|
113
119
|
if (!routeData || routeData.prerender)
|
|
114
120
|
return void 0;
|
|
115
121
|
return routeData;
|
|
116
122
|
}
|
|
123
|
+
#computePathnameFromDomain(request) {
|
|
124
|
+
let pathname = void 0;
|
|
125
|
+
const url = new URL(request.url);
|
|
126
|
+
if (this.#manifest.i18n && (this.#manifest.i18n.routing === "domains-prefix-always" || this.#manifest.i18n.routing === "domains-prefix-other-locales" || this.#manifest.i18n.routing === "domains-prefix-other-no-redirect")) {
|
|
127
|
+
let host = request.headers.get("X-Forwarded-Host");
|
|
128
|
+
let protocol = request.headers.get("X-Forwarded-Proto");
|
|
129
|
+
if (protocol) {
|
|
130
|
+
protocol = protocol + ":";
|
|
131
|
+
} else {
|
|
132
|
+
protocol = url.protocol;
|
|
133
|
+
}
|
|
134
|
+
if (!host) {
|
|
135
|
+
host = request.headers.get("Host");
|
|
136
|
+
}
|
|
137
|
+
if (host && protocol) {
|
|
138
|
+
host = host.split(":")[0];
|
|
139
|
+
try {
|
|
140
|
+
let locale;
|
|
141
|
+
const hostAsUrl = new URL(`${protocol}//${host}`);
|
|
142
|
+
for (const [domainKey, localeValue] of Object.entries(
|
|
143
|
+
this.#manifest.i18n.domainLookupTable
|
|
144
|
+
)) {
|
|
145
|
+
const domainKeyAsUrl = new URL(domainKey);
|
|
146
|
+
if (hostAsUrl.host === domainKeyAsUrl.host && hostAsUrl.protocol === domainKeyAsUrl.protocol) {
|
|
147
|
+
locale = localeValue;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (locale) {
|
|
152
|
+
pathname = prependForwardSlash(
|
|
153
|
+
joinPaths(normalizeTheLocale(locale), this.removeBase(url.pathname))
|
|
154
|
+
);
|
|
155
|
+
if (url.pathname.endsWith("/")) {
|
|
156
|
+
pathname = appendForwardSlash(pathname);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} catch (e) {
|
|
160
|
+
this.#logger.error(
|
|
161
|
+
"router",
|
|
162
|
+
`Astro tried to parse ${protocol}//${host} as an URL, but it threw a parsing error. Check the X-Forwarded-Host and X-Forwarded-Proto headers.`
|
|
163
|
+
);
|
|
164
|
+
this.#logger.error("router", `Error: ${e}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return pathname;
|
|
169
|
+
}
|
|
117
170
|
async render(request, routeDataOrOptions, maybeLocals) {
|
|
118
171
|
let routeData;
|
|
119
172
|
let locals;
|
package/dist/core/app/node.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export declare class NodeApp extends App {
|
|
|
51
51
|
* @param source WhatWG Response
|
|
52
52
|
* @param destination NodeJS ServerResponse
|
|
53
53
|
*/
|
|
54
|
-
static writeResponse(source: Response, destination: ServerResponse): Promise<
|
|
54
|
+
static writeResponse(source: Response, destination: ServerResponse): Promise<ServerResponse<IncomingMessage> | undefined>;
|
|
55
55
|
}
|
|
56
56
|
export declare function loadManifest(rootFolder: URL): Promise<SSRManifest>;
|
|
57
57
|
export declare function loadApp(rootFolder: URL): Promise<NodeApp>;
|
package/dist/core/app/node.js
CHANGED
|
@@ -68,27 +68,27 @@ class NodeApp extends App {
|
|
|
68
68
|
static async writeResponse(source, destination) {
|
|
69
69
|
const { status, headers, body } = source;
|
|
70
70
|
destination.writeHead(status, createOutgoingHttpHeaders(headers));
|
|
71
|
-
if (body)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
if (!body)
|
|
72
|
+
return destination.end();
|
|
73
|
+
try {
|
|
74
|
+
const reader = body.getReader();
|
|
75
|
+
destination.on("close", () => {
|
|
76
|
+
reader.cancel().catch((err) => {
|
|
77
|
+
console.error(
|
|
78
|
+
`There was an uncaught error in the middle of the stream while rendering ${destination.req.url}.`,
|
|
79
|
+
err
|
|
80
|
+
);
|
|
81
81
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
} catch {
|
|
88
|
-
destination.write("Internal server error");
|
|
82
|
+
});
|
|
83
|
+
let result = await reader.read();
|
|
84
|
+
while (!result.done) {
|
|
85
|
+
destination.write(result.value);
|
|
86
|
+
result = await reader.read();
|
|
89
87
|
}
|
|
88
|
+
destination.end();
|
|
89
|
+
} catch {
|
|
90
|
+
destination.end("Internal server error");
|
|
90
91
|
}
|
|
91
|
-
destination.end();
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
function makeRequestHeaders(req) {
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export type SSRManifest = {
|
|
|
32
32
|
site?: string;
|
|
33
33
|
base: string;
|
|
34
34
|
trailingSlash: 'always' | 'never' | 'ignore';
|
|
35
|
-
buildFormat: 'file' | 'directory';
|
|
35
|
+
buildFormat: 'file' | 'directory' | 'preserve';
|
|
36
36
|
compressHTML: boolean;
|
|
37
37
|
assetsPrefix?: string;
|
|
38
38
|
renderers: SSRLoadedRenderer[];
|
|
@@ -53,6 +53,7 @@ export type SSRManifestI18n = {
|
|
|
53
53
|
routing: RoutingStrategies;
|
|
54
54
|
locales: Locales;
|
|
55
55
|
defaultLocale: string;
|
|
56
|
+
domainLookupTable: Record<string, string>;
|
|
56
57
|
};
|
|
57
58
|
export type SerializedSSRManifest = Omit<SSRManifest, 'middleware' | 'routes' | 'assets' | 'componentMetadata' | 'clientDirectives'> & {
|
|
58
59
|
routes: SerializedRouteInfo[];
|
|
@@ -98,6 +98,7 @@ class BuildPipeline extends Pipeline {
|
|
|
98
98
|
}
|
|
99
99
|
const renderersEntryUrl = new URL(`renderers.mjs?time=${Date.now()}`, baseDirectory);
|
|
100
100
|
const renderers = await import(renderersEntryUrl.toString());
|
|
101
|
+
const middleware = await import(new URL("middleware.mjs", baseDirectory).toString()).then((mod) => mod.onRequest).catch(() => manifest.middleware);
|
|
101
102
|
if (!renderers) {
|
|
102
103
|
throw new Error(
|
|
103
104
|
"Astro couldn't find the emitted renderers. This is an internal error, please file an issue."
|
|
@@ -105,7 +106,8 @@ class BuildPipeline extends Pipeline {
|
|
|
105
106
|
}
|
|
106
107
|
return {
|
|
107
108
|
...manifest,
|
|
108
|
-
renderers: renderers.renderers
|
|
109
|
+
renderers: renderers.renderers,
|
|
110
|
+
middleware
|
|
109
111
|
};
|
|
110
112
|
}
|
|
111
113
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AstroConfig,
|
|
2
|
-
export declare function getOutFolder(astroConfig: AstroConfig, pathname: string,
|
|
3
|
-
export declare function getOutFile(astroConfig: AstroConfig, outFolder: URL, pathname: string,
|
|
1
|
+
import type { AstroConfig, RouteData } from '../../@types/astro.js';
|
|
2
|
+
export declare function getOutFolder(astroConfig: AstroConfig, pathname: string, routeData: RouteData): URL;
|
|
3
|
+
export declare function getOutFile(astroConfig: AstroConfig, outFolder: URL, pathname: string, routeData: RouteData): URL;
|
|
4
4
|
/**
|
|
5
5
|
* Ensures the `outDir` is within `process.cwd()`. If not it will fallback to `<cwd>/.astro`.
|
|
6
6
|
* This is used for static `ssrBuild` so the output can access node_modules when we import
|
|
@@ -10,8 +10,9 @@ function getOutRoot(astroConfig) {
|
|
|
10
10
|
return new URL("./", astroConfig.build.client);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
function getOutFolder(astroConfig, pathname,
|
|
13
|
+
function getOutFolder(astroConfig, pathname, routeData) {
|
|
14
14
|
const outRoot = getOutRoot(astroConfig);
|
|
15
|
+
const routeType = routeData.type;
|
|
15
16
|
switch (routeType) {
|
|
16
17
|
case "endpoint":
|
|
17
18
|
return new URL("." + appendForwardSlash(npath.dirname(pathname)), outRoot);
|
|
@@ -29,10 +30,20 @@ function getOutFolder(astroConfig, pathname, routeType) {
|
|
|
29
30
|
const d = pathname === "" ? pathname : npath.dirname(pathname);
|
|
30
31
|
return new URL("." + appendForwardSlash(d), outRoot);
|
|
31
32
|
}
|
|
33
|
+
case "preserve": {
|
|
34
|
+
let dir;
|
|
35
|
+
if (pathname === "" || routeData.isIndex) {
|
|
36
|
+
dir = pathname;
|
|
37
|
+
} else {
|
|
38
|
+
dir = npath.dirname(pathname);
|
|
39
|
+
}
|
|
40
|
+
return new URL("." + appendForwardSlash(dir), outRoot);
|
|
41
|
+
}
|
|
32
42
|
}
|
|
33
43
|
}
|
|
34
44
|
}
|
|
35
|
-
function getOutFile(astroConfig, outFolder, pathname,
|
|
45
|
+
function getOutFile(astroConfig, outFolder, pathname, routeData) {
|
|
46
|
+
const routeType = routeData.type;
|
|
36
47
|
switch (routeType) {
|
|
37
48
|
case "endpoint":
|
|
38
49
|
return new URL(npath.basename(pathname), outFolder);
|
|
@@ -51,6 +62,13 @@ function getOutFile(astroConfig, outFolder, pathname, routeType) {
|
|
|
51
62
|
const baseName = npath.basename(pathname);
|
|
52
63
|
return new URL("./" + (baseName || "index") + ".html", outFolder);
|
|
53
64
|
}
|
|
65
|
+
case "preserve": {
|
|
66
|
+
let baseName = npath.basename(pathname);
|
|
67
|
+
if (!baseName || routeData.isIndex) {
|
|
68
|
+
baseName = "index";
|
|
69
|
+
}
|
|
70
|
+
return new URL(`./${baseName}.html`, outFolder);
|
|
71
|
+
}
|
|
54
72
|
}
|
|
55
73
|
}
|
|
56
74
|
}
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
mergeInlineCss
|
|
48
48
|
} from "./internal.js";
|
|
49
49
|
import { getTimeStat, shouldAppendForwardSlash } from "./util.js";
|
|
50
|
+
import { NoPrerenderedRoutesWithDomains } from "../errors/errors-data.js";
|
|
50
51
|
function createEntryURL(filePath, outFolder) {
|
|
51
52
|
return new URL("./" + filePath + `?time=${Date.now()}`, outFolder);
|
|
52
53
|
}
|
|
@@ -130,9 +131,16 @@ async function generatePages(opts, internals) {
|
|
|
130
131
|
${bgGreen(black(` ${verb} static routes `))}`);
|
|
131
132
|
const builtPaths = /* @__PURE__ */ new Set();
|
|
132
133
|
const pagesToGenerate = pipeline.retrieveRoutesToGenerate();
|
|
134
|
+
const config = pipeline.getConfig();
|
|
133
135
|
if (ssr) {
|
|
134
136
|
for (const [pageData, filePath] of pagesToGenerate) {
|
|
135
137
|
if (pageData.route.prerender) {
|
|
138
|
+
if (config.experimental.i18nDomains) {
|
|
139
|
+
throw new AstroError({
|
|
140
|
+
...NoPrerenderedRoutesWithDomains,
|
|
141
|
+
message: NoPrerenderedRoutesWithDomains.message(pageData.component)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
136
144
|
const ssrEntryURLPage = createEntryURL(filePath, outFolder);
|
|
137
145
|
const ssrEntryPage = await import(ssrEntryURLPage.toString());
|
|
138
146
|
if (opts.settings.adapter?.adapterFeatures?.functionPerRoute) {
|
|
@@ -451,8 +459,8 @@ async function generatePath(pathname, pipeline, gopts, route) {
|
|
|
451
459
|
return;
|
|
452
460
|
body = Buffer.from(await response.arrayBuffer());
|
|
453
461
|
}
|
|
454
|
-
const outFolder = getOutFolder(pipeline.getConfig(), pathname, route
|
|
455
|
-
const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route
|
|
462
|
+
const outFolder = getOutFolder(pipeline.getConfig(), pathname, route);
|
|
463
|
+
const outFile = getOutFile(pipeline.getConfig(), outFolder, pathname, route);
|
|
456
464
|
route.distURL = outFile;
|
|
457
465
|
await fs.promises.mkdir(outFolder, { recursive: true });
|
|
458
466
|
await fs.promises.writeFile(outFile, body);
|
|
@@ -473,7 +481,8 @@ function createBuildManifest(settings, internals, renderers, middleware) {
|
|
|
473
481
|
fallback: settings.config.i18n.fallback,
|
|
474
482
|
routing: settings.config.i18n.routing,
|
|
475
483
|
defaultLocale: settings.config.i18n.defaultLocale,
|
|
476
|
-
locales: settings.config.i18n.locales
|
|
484
|
+
locales: settings.config.i18n.locales,
|
|
485
|
+
domainLookupTable: {}
|
|
477
486
|
};
|
|
478
487
|
}
|
|
479
488
|
return {
|
|
@@ -8,6 +8,7 @@ import { serializeRouteData } from "../../routing/index.js";
|
|
|
8
8
|
import { addRollupInput } from "../add-rollup-input.js";
|
|
9
9
|
import { getOutFile, getOutFolder } from "../common.js";
|
|
10
10
|
import { cssOrder, mergeInlineCss } from "../internal.js";
|
|
11
|
+
import { normalizeTheLocale } from "../../../i18n/index.js";
|
|
11
12
|
const manifestReplace = "@@ASTRO_MANIFEST_REPLACE@@";
|
|
12
13
|
const replaceExp = new RegExp(`['"](${manifestReplace})['"]`, "g");
|
|
13
14
|
const SSR_MANIFEST_VIRTUAL_MODULE_ID = "@astrojs-manifest";
|
|
@@ -111,6 +112,7 @@ function injectManifest(manifest, chunk) {
|
|
|
111
112
|
function buildManifest(opts, internals, staticFiles) {
|
|
112
113
|
const { settings } = opts;
|
|
113
114
|
const routes = [];
|
|
115
|
+
const domainLookupTable = {};
|
|
114
116
|
const entryModules = Object.fromEntries(internals.entrySpecifierToBundleMap.entries());
|
|
115
117
|
if (settings.scripts.some((script) => script.stage === "page")) {
|
|
116
118
|
staticFiles.push(entryModules[PAGE_SCRIPT_ID]);
|
|
@@ -127,8 +129,8 @@ function buildManifest(opts, internals, staticFiles) {
|
|
|
127
129
|
continue;
|
|
128
130
|
if (!route.pathname)
|
|
129
131
|
continue;
|
|
130
|
-
const outFolder = getOutFolder(opts.settings.config, route.pathname, route
|
|
131
|
-
const outFile = getOutFile(opts.settings.config, outFolder, route.pathname, route
|
|
132
|
+
const outFolder = getOutFolder(opts.settings.config, route.pathname, route);
|
|
133
|
+
const outFile = getOutFile(opts.settings.config, outFolder, route.pathname, route);
|
|
132
134
|
const file = outFile.toString().replace(opts.settings.config.build.client.toString(), "");
|
|
133
135
|
routes.push({
|
|
134
136
|
file,
|
|
@@ -174,6 +176,12 @@ function buildManifest(opts, internals, staticFiles) {
|
|
|
174
176
|
routeData: serializeRouteData(route, settings.config.trailingSlash)
|
|
175
177
|
});
|
|
176
178
|
}
|
|
179
|
+
const i18n = settings.config.i18n;
|
|
180
|
+
if (settings.config.experimental.i18nDomains && i18n && i18n.domains && (i18n.routing === "domains-prefix-always" || i18n.routing === "domains-prefix-other-locales" || i18n.routing === "domains-prefix-other-no-redirect")) {
|
|
181
|
+
for (const [locale, domainValue] of Object.entries(i18n.domains)) {
|
|
182
|
+
domainLookupTable[domainValue] = normalizeTheLocale(locale);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
177
185
|
if (!(BEFORE_HYDRATION_SCRIPT_ID in entryModules)) {
|
|
178
186
|
entryModules[BEFORE_HYDRATION_SCRIPT_ID] = "";
|
|
179
187
|
}
|
|
@@ -183,7 +191,8 @@ function buildManifest(opts, internals, staticFiles) {
|
|
|
183
191
|
fallback: settings.config.i18n.fallback,
|
|
184
192
|
routing: settings.config.i18n.routing,
|
|
185
193
|
locales: settings.config.i18n.locales,
|
|
186
|
-
defaultLocale: settings.config.i18n.defaultLocale
|
|
194
|
+
defaultLocale: settings.config.i18n.defaultLocale,
|
|
195
|
+
domainLookupTable
|
|
187
196
|
};
|
|
188
197
|
}
|
|
189
198
|
return {
|
|
@@ -210,7 +210,14 @@ function generateSSRCode(adapter, middlewareId) {
|
|
|
210
210
|
return `export const ${name} = _exports['${name}'];`;
|
|
211
211
|
}
|
|
212
212
|
}) ?? [],
|
|
213
|
-
|
|
213
|
+
// NOTE: This is intentionally obfuscated!
|
|
214
|
+
// Do NOT simplify this to something like `serverEntrypointModule.start?.(_manifest, _args)`
|
|
215
|
+
// They are NOT equivalent! Some bundlers will throw if `start` is not exported, but we
|
|
216
|
+
// only want to silently ignore it... hence the dynamic, obfuscated weirdness.
|
|
217
|
+
`const _start = 'start';
|
|
218
|
+
if (_start in serverEntrypointModule) {
|
|
219
|
+
serverEntrypointModule[_start](_manifest, _args);
|
|
220
|
+
}`
|
|
214
221
|
];
|
|
215
222
|
return {
|
|
216
223
|
imports,
|