astro 6.2.1 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/handler.d.ts +32 -0
- package/dist/actions/handler.js +45 -0
- package/dist/actions/runtime/server.js +1 -1
- package/dist/assets/build/generate.js +1 -1
- package/dist/assets/build/remote.d.ts +3 -2
- package/dist/assets/build/remote.js +16 -9
- package/dist/assets/endpoint/generic.js +4 -7
- package/dist/assets/endpoint/shared.js +7 -2
- package/dist/assets/index.d.ts +1 -0
- package/dist/assets/index.js +2 -0
- package/dist/assets/internal.js +16 -1
- package/dist/assets/services/sharp.js +16 -1
- package/dist/assets/utils/index.d.ts +1 -0
- package/dist/assets/utils/index.js +2 -0
- package/dist/assets/utils/redirectValidation.d.ts +48 -0
- package/dist/assets/utils/redirectValidation.js +48 -0
- package/dist/assets/utils/remoteProbe.js +25 -2
- package/dist/cli/add/index.js +7 -4
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +18 -14
- package/dist/content/content-layer.js +3 -4
- package/dist/content/loaders/types.d.ts +1 -1
- package/dist/content/server-listeners.js +0 -4
- package/dist/content/vite-plugin-content-virtual-mod.js +9 -1
- package/dist/core/app/base.d.ts +33 -15
- package/dist/core/app/base.js +120 -324
- package/dist/core/app/dev/app.d.ts +3 -2
- package/dist/core/app/dev/app.js +4 -60
- package/dist/core/app/entrypoints/virtual/dev.js +2 -0
- package/dist/core/app/entrypoints/virtual/prod.js +4 -1
- package/dist/core/app/prepare-response.d.ts +11 -0
- package/dist/core/app/prepare-response.js +18 -0
- package/dist/core/app/render-options.d.ts +11 -0
- package/dist/core/app/render-options.js +11 -0
- package/dist/core/base-pipeline.d.ts +38 -1
- package/dist/core/base-pipeline.js +50 -7
- package/dist/core/build/app.d.ts +3 -4
- package/dist/core/build/app.js +3 -17
- package/dist/core/build/plugins/plugin-css.js +7 -1
- package/dist/core/build/plugins/plugin-manifest.js +11 -1
- package/dist/core/build/static-build.js +16 -2
- package/dist/core/cache/handler.d.ts +29 -0
- package/dist/core/cache/handler.js +81 -0
- package/dist/core/compile/style.js +18 -1
- package/dist/core/config/index.d.ts +1 -1
- package/dist/core/config/index.js +4 -1
- package/dist/core/config/schemas/base.d.ts +4 -0
- package/dist/core/config/schemas/base.js +4 -0
- package/dist/core/config/schemas/relative.d.ts +6 -0
- package/dist/core/config/settings.js +2 -4
- package/dist/core/config/tsconfig.d.ts +24 -9
- package/dist/core/config/tsconfig.js +54 -45
- package/dist/core/constants.d.ts +27 -1
- package/dist/core/constants.js +14 -1
- package/dist/core/cookies/cookies.d.ts +7 -2
- package/dist/core/cookies/cookies.js +11 -4
- package/dist/core/cookies/response.d.ts +1 -1
- package/dist/core/cookies/response.js +1 -2
- package/dist/core/create-vite.js +15 -0
- package/dist/core/csp/runtime.js +6 -4
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/build-handler.d.ts +17 -0
- package/dist/core/errors/build-handler.js +22 -0
- package/dist/core/errors/default-handler.d.ts +14 -0
- package/dist/core/errors/default-handler.js +144 -0
- package/dist/core/errors/dev-handler.d.ts +21 -0
- package/dist/core/errors/dev-handler.js +82 -0
- package/dist/core/errors/handler.d.ts +9 -0
- package/dist/core/errors/handler.js +0 -0
- package/dist/core/fetch/default-handler.d.ts +17 -0
- package/dist/core/fetch/default-handler.js +45 -0
- package/dist/core/fetch/fetch-state.d.ts +244 -0
- package/dist/core/fetch/fetch-state.js +779 -0
- package/dist/core/fetch/index.d.ts +61 -0
- package/dist/core/fetch/index.js +121 -0
- package/dist/core/fetch/types.d.ts +6 -0
- package/dist/core/fetch/types.js +0 -0
- package/dist/core/fetch/vite-plugin.d.ts +5 -0
- package/dist/core/fetch/vite-plugin.js +69 -0
- package/dist/core/hono/index.d.ts +21 -0
- package/dist/core/hono/index.js +98 -0
- package/dist/core/i18n/handler.d.ts +18 -0
- package/dist/core/i18n/handler.js +119 -0
- package/dist/core/logger/core.d.ts +8 -0
- package/dist/core/logger/core.js +16 -0
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/middleware/astro-middleware.d.ts +27 -0
- package/dist/core/middleware/astro-middleware.js +53 -0
- package/dist/core/pages/handler.d.ts +20 -0
- package/dist/core/pages/handler.js +74 -0
- package/dist/core/redirects/render.d.ts +2 -2
- package/dist/core/redirects/render.js +7 -8
- package/dist/core/render/params-and-props.js +1 -1
- package/dist/core/render/slots.js +9 -2
- package/dist/core/rewrites/handler.d.ts +37 -0
- package/dist/core/rewrites/handler.js +67 -0
- package/dist/core/routing/3xx.js +8 -4
- package/dist/core/routing/handler.d.ts +17 -0
- package/dist/core/routing/handler.js +172 -0
- package/dist/core/routing/match.d.ts +0 -7
- package/dist/core/routing/match.js +0 -5
- package/dist/core/routing/pattern.js +1 -1
- package/dist/core/routing/rewrite.js +1 -4
- package/dist/core/routing/trailing-slash-handler.d.ts +18 -0
- package/dist/core/routing/trailing-slash-handler.js +67 -0
- package/dist/core/session/drivers.d.ts +1 -1
- package/dist/core/session/handler.d.ts +11 -0
- package/dist/core/session/handler.js +33 -0
- package/dist/core/session/runtime.js +7 -2
- package/dist/core/util/normalized-url.d.ts +10 -0
- package/dist/core/util/normalized-url.js +21 -0
- package/dist/i18n/middleware.d.ts +10 -0
- package/dist/i18n/middleware.js +4 -88
- package/dist/i18n/utils.js +2 -2
- package/dist/prefetch/index.js +12 -7
- package/dist/runtime/server/astro-island.js +57 -20
- package/dist/runtime/server/astro-island.prebuilt-dev.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt-dev.js +1 -1
- package/dist/runtime/server/astro-island.prebuilt.d.ts +1 -1
- package/dist/runtime/server/astro-island.prebuilt.js +1 -1
- package/dist/runtime/server/render/common.js +10 -4
- package/dist/runtime/server/render/server-islands.js +2 -1
- package/dist/runtime/server/scripts.js +6 -0
- package/dist/types/public/config.d.ts +46 -12
- package/dist/types/public/content.d.ts +4 -4
- package/dist/types/public/internal.d.ts +1 -1
- package/dist/vite-plugin-app/app.d.ts +4 -5
- package/dist/vite-plugin-app/app.js +20 -68
- package/dist/vite-plugin-astro/compile.js +2 -2
- package/dist/vite-plugin-astro/utils.d.ts +1 -0
- package/dist/vite-plugin-astro/utils.js +9 -1
- package/dist/vite-plugin-head/index.js +36 -19
- package/dist/vite-plugin-utils/index.d.ts +1 -0
- package/dist/vite-plugin-utils/index.js +3 -0
- package/package.json +13 -6
- package/dist/core/render-context.d.ts +0 -77
- package/dist/core/render-context.js +0 -826
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RouteData } from '../../../types/public/index.js';
|
|
2
|
+
import type { ErrorHandler } from '../../errors/handler.js';
|
|
2
3
|
import type { AstroLogger } from '../../logger/core.js';
|
|
3
|
-
import { BaseApp, type DevMatch, type LogRequestPayload
|
|
4
|
+
import { BaseApp, type DevMatch, type LogRequestPayload } from '../base.js';
|
|
4
5
|
import type { SSRManifest } from '../types.js';
|
|
5
6
|
import { NonRunnablePipeline } from './pipeline.js';
|
|
6
7
|
import type { RoutesList } from '../../../types/astro.js';
|
|
@@ -20,6 +21,6 @@ export declare class DevApp extends BaseApp<NonRunnablePipeline> {
|
|
|
20
21
|
updateRoutes(newRoutesList: RoutesList): void;
|
|
21
22
|
match(request: Request): RouteData | undefined;
|
|
22
23
|
devMatch(pathname: string): Promise<DevMatch | undefined>;
|
|
23
|
-
|
|
24
|
+
protected createErrorHandler(): ErrorHandler;
|
|
24
25
|
logRequest({ pathname, method, statusCode, isRewrite, reqTime }: LogRequestPayload): void;
|
|
25
26
|
}
|
package/dist/core/app/dev/app.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
BaseApp
|
|
5
|
-
} from "../base.js";
|
|
1
|
+
import { DevErrorHandler } from "../../errors/dev-handler.js";
|
|
2
|
+
import { BaseApp } from "../base.js";
|
|
6
3
|
import { NonRunnablePipeline } from "./pipeline.js";
|
|
7
|
-
import { getCustom404Route, getCustom500Route } from "../../routing/helpers.js";
|
|
8
4
|
import { ensure404Route } from "../../routing/astro-designed-error-pages.js";
|
|
9
5
|
import { matchRoute } from "../../routing/dev.js";
|
|
10
6
|
import { req } from "../../messages/runtime.js";
|
|
@@ -53,60 +49,8 @@ class DevApp extends BaseApp {
|
|
|
53
49
|
resolvedPathname: matchedRoute.resolvedPathname
|
|
54
50
|
};
|
|
55
51
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
error,
|
|
59
|
-
status,
|
|
60
|
-
response: _response,
|
|
61
|
-
...resolvedRenderOptions
|
|
62
|
-
}) {
|
|
63
|
-
if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
|
|
64
|
-
throw error;
|
|
65
|
-
}
|
|
66
|
-
const renderRoute = async (routeData) => {
|
|
67
|
-
try {
|
|
68
|
-
const preloadedComponent = await this.pipeline.getComponentByRoute(routeData);
|
|
69
|
-
const renderContext = await this.createRenderContext({
|
|
70
|
-
locals: resolvedRenderOptions.locals,
|
|
71
|
-
pipeline: this.pipeline,
|
|
72
|
-
pathname: this.getPathnameFromRequest(request),
|
|
73
|
-
skipMiddleware,
|
|
74
|
-
request,
|
|
75
|
-
routeData,
|
|
76
|
-
clientAddress: resolvedRenderOptions.clientAddress,
|
|
77
|
-
status,
|
|
78
|
-
shouldInjectCspMetaTags: false
|
|
79
|
-
});
|
|
80
|
-
renderContext.props.error = error;
|
|
81
|
-
const response = await renderContext.render(preloadedComponent);
|
|
82
|
-
if (error) {
|
|
83
|
-
this.logger.error("router", error.stack || error.message);
|
|
84
|
-
}
|
|
85
|
-
return response;
|
|
86
|
-
} catch (_err) {
|
|
87
|
-
if (skipMiddleware === false) {
|
|
88
|
-
return this.renderError(request, {
|
|
89
|
-
...resolvedRenderOptions,
|
|
90
|
-
status: 500,
|
|
91
|
-
skipMiddleware: true,
|
|
92
|
-
error: _err
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
throw _err;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
if (status === 404) {
|
|
99
|
-
const custom404 = getCustom404Route(this.manifestData);
|
|
100
|
-
if (custom404) {
|
|
101
|
-
return renderRoute(custom404);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const custom500 = getCustom500Route(this.manifestData);
|
|
105
|
-
if (!custom500) {
|
|
106
|
-
throw error;
|
|
107
|
-
} else {
|
|
108
|
-
return renderRoute(custom500);
|
|
109
|
-
}
|
|
52
|
+
createErrorHandler() {
|
|
53
|
+
return new DevErrorHandler(this, { shouldInjectCspMetaTags: false });
|
|
110
54
|
}
|
|
111
55
|
logRequest({ pathname, method, statusCode, isRewrite, reqTime }) {
|
|
112
56
|
if (pathname === "/favicon.ico") {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fetchable from "virtual:astro:fetchable";
|
|
1
2
|
import { manifest } from "virtual:astro:manifest";
|
|
2
3
|
import { DevApp } from "../../dev/app.js";
|
|
3
4
|
import { createConsoleLogger } from "../../../logger/impls/console.js";
|
|
@@ -5,6 +6,7 @@ let currentDevApp = null;
|
|
|
5
6
|
const createApp = ({ streaming } = {}) => {
|
|
6
7
|
const logger = createConsoleLogger(manifest.logLevel);
|
|
7
8
|
currentDevApp = new DevApp(manifest, streaming, logger);
|
|
9
|
+
currentDevApp.setFetchHandler(fetchable);
|
|
8
10
|
if (import.meta.hot) {
|
|
9
11
|
import.meta.hot.on("astro:routes-updated", async () => {
|
|
10
12
|
if (!currentDevApp) return;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import fetchable from "virtual:astro:fetchable";
|
|
1
2
|
import { manifest } from "virtual:astro:manifest";
|
|
2
3
|
import { App } from "../../app.js";
|
|
3
4
|
const createApp = ({ streaming } = {}) => {
|
|
4
|
-
|
|
5
|
+
const app = new App(manifest, streaming);
|
|
6
|
+
app.setFetchHandler(fetchable);
|
|
7
|
+
return app;
|
|
5
8
|
};
|
|
6
9
|
export {
|
|
7
10
|
createApp
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips internal-only headers from the response before sending it to the
|
|
3
|
+
* user agent, and optionally appends cookies written via `Astro.cookie.set()`
|
|
4
|
+
* to the `Set-Cookie` header.
|
|
5
|
+
*
|
|
6
|
+
* This is a pure function with no dependencies on the app; it is shared by
|
|
7
|
+
* `AstroHandler` and the various error handlers.
|
|
8
|
+
*/
|
|
9
|
+
export declare function prepareResponse(response: Response, { addCookieHeader }: {
|
|
10
|
+
addCookieHeader: boolean;
|
|
11
|
+
}): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { INTERNAL_RESPONSE_HEADERS, responseSentSymbol } from "../constants.js";
|
|
2
|
+
import { getSetCookiesFromResponse } from "../cookies/index.js";
|
|
3
|
+
function prepareResponse(response, { addCookieHeader }) {
|
|
4
|
+
for (const headerName of INTERNAL_RESPONSE_HEADERS) {
|
|
5
|
+
if (response.headers.has(headerName)) {
|
|
6
|
+
response.headers.delete(headerName);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
if (addCookieHeader) {
|
|
10
|
+
for (const setCookieHeaderValue of getSetCookiesFromResponse(response)) {
|
|
11
|
+
response.headers.append("set-cookie", setCookieHeaderValue);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
Reflect.set(response, responseSentSymbol, true);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
prepareResponse
|
|
18
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResolvedRenderOptions } from './base.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reads `ResolvedRenderOptions` that were attached to a request via
|
|
4
|
+
* `renderOptionsSymbol`. Returns `undefined` if no options are attached.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getRenderOptions(request: Request): ResolvedRenderOptions | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Attaches `ResolvedRenderOptions` to a request via `renderOptionsSymbol` so
|
|
9
|
+
* that downstream handlers can read them.
|
|
10
|
+
*/
|
|
11
|
+
export declare function setRenderOptions(request: Request, options: ResolvedRenderOptions): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const renderOptionsSymbol = /* @__PURE__ */ Symbol.for("astro.renderOptions");
|
|
2
|
+
function getRenderOptions(request) {
|
|
3
|
+
return Reflect.get(request, renderOptionsSymbol);
|
|
4
|
+
}
|
|
5
|
+
function setRenderOptions(request, options) {
|
|
6
|
+
Reflect.set(request, renderOptionsSymbol, options);
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
getRenderOptions,
|
|
10
|
+
setRenderOptions
|
|
11
|
+
};
|
|
@@ -14,13 +14,29 @@ import type { CompiledCacheRoute } from './cache/runtime/route-matching.js';
|
|
|
14
14
|
import type { SessionDriverFactory } from './session/types.js';
|
|
15
15
|
import { NodePool } from '../runtime/server/render/queue/pool.js';
|
|
16
16
|
import { HTMLStringCache } from '../runtime/server/html-string-cache.js';
|
|
17
|
+
/**
|
|
18
|
+
* Bit flags for pipeline features that handler classes register as
|
|
19
|
+
* "used" when a custom `src/app.ts` fetch handler is in play. After the
|
|
20
|
+
* first request (dev) or at runtime (prod SSR), we compare against the
|
|
21
|
+
* manifest to warn about features the user configured but forgot to
|
|
22
|
+
* include in their custom pipeline.
|
|
23
|
+
*/
|
|
24
|
+
export declare const PipelineFeatures: {
|
|
25
|
+
readonly redirects: number;
|
|
26
|
+
readonly sessions: number;
|
|
27
|
+
readonly actions: number;
|
|
28
|
+
readonly middleware: number;
|
|
29
|
+
readonly i18n: number;
|
|
30
|
+
readonly cache: number;
|
|
31
|
+
};
|
|
17
32
|
/**
|
|
18
33
|
* The `Pipeline` represents the static parts of rendering that do not change between requests.
|
|
19
34
|
* These are mostly known when the server first starts up and do not change.
|
|
20
35
|
*
|
|
21
|
-
* Thus, a `Pipeline` is created once at process start and then used by every `
|
|
36
|
+
* Thus, a `Pipeline` is created once at process start and then used by every `FetchState`.
|
|
22
37
|
*/
|
|
23
38
|
export declare abstract class Pipeline {
|
|
39
|
+
#private;
|
|
24
40
|
readonly internalMiddleware: MiddlewareHandler[];
|
|
25
41
|
resolvedMiddleware: MiddlewareHandler | undefined;
|
|
26
42
|
resolvedLogger: boolean;
|
|
@@ -30,6 +46,12 @@ export declare abstract class Pipeline {
|
|
|
30
46
|
compiledCacheRoutes: CompiledCacheRoute[] | undefined;
|
|
31
47
|
nodePool: NodePool | undefined;
|
|
32
48
|
htmlStringCache: HTMLStringCache | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Bit mask of pipeline features activated by handler classes.
|
|
51
|
+
* Each handler sets its bit via `|=`. Only meaningful when a
|
|
52
|
+
* custom `src/app.ts` fetch handler is in use.
|
|
53
|
+
*/
|
|
54
|
+
usedFeatures: number;
|
|
33
55
|
logger: AstroLogger;
|
|
34
56
|
readonly manifest: SSRManifest;
|
|
35
57
|
/**
|
|
@@ -63,6 +85,10 @@ export declare abstract class Pipeline {
|
|
|
63
85
|
readonly cacheProvider: SSRManifest['cacheProvider'];
|
|
64
86
|
readonly cacheConfig: SSRManifest['cacheConfig'];
|
|
65
87
|
readonly serverIslands: SSRManifest['serverIslandMappings'];
|
|
88
|
+
/** Route data derived from the manifest, used for route matching. */
|
|
89
|
+
manifestData: {
|
|
90
|
+
routes: RouteData[];
|
|
91
|
+
};
|
|
66
92
|
constructor(logger: AstroLogger, manifest: SSRManifest,
|
|
67
93
|
/**
|
|
68
94
|
* "development" or "production" only
|
|
@@ -85,6 +111,17 @@ export declare abstract class Pipeline {
|
|
|
85
111
|
}>) | undefined, cacheProvider?: (() => Promise<{
|
|
86
112
|
default: CacheProviderFactory | null;
|
|
87
113
|
}>) | undefined, cacheConfig?: import("./cache/types.js").SSRManifestCache | undefined, serverIslands?: (() => Promise<ServerIslandMappings> | ServerIslandMappings) | undefined);
|
|
114
|
+
/**
|
|
115
|
+
* Low-level route matching against the manifest routes. Returns the
|
|
116
|
+
* matched `RouteData` or `undefined`. Does not filter prerendered
|
|
117
|
+
* routes or check public assets — use `BaseApp.match()` for that.
|
|
118
|
+
*/
|
|
119
|
+
matchRoute(pathname: string): RouteData | undefined;
|
|
120
|
+
/**
|
|
121
|
+
* Rebuilds the internal router after routes have been added or
|
|
122
|
+
* removed (e.g. by the dev server on HMR).
|
|
123
|
+
*/
|
|
124
|
+
rebuildRouter(): void;
|
|
88
125
|
abstract headElements(routeData: RouteData): Promise<HeadElements> | HeadElements;
|
|
89
126
|
abstract componentMetadata(routeData: RouteData): Promise<SSRResult['componentMetadata']> | void;
|
|
90
127
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { NOOP_ACTIONS_MOD } from "../actions/noop-actions.js";
|
|
2
|
-
import { createI18nMiddleware } from "../i18n/middleware.js";
|
|
3
2
|
import { createOriginCheckMiddleware } from "./app/middlewares.js";
|
|
4
3
|
import { ActionNotFoundError } from "./errors/errors-data.js";
|
|
5
4
|
import { AstroError } from "./errors/index.js";
|
|
@@ -8,10 +7,20 @@ import { sequence } from "./middleware/sequence.js";
|
|
|
8
7
|
import { RedirectSinglePageBuiltModule } from "./redirects/index.js";
|
|
9
8
|
import { RouteCache } from "./render/route-cache.js";
|
|
10
9
|
import { createDefaultRoutes } from "./routing/default.js";
|
|
10
|
+
import { ensure404Route } from "./routing/astro-designed-error-pages.js";
|
|
11
|
+
import { Router } from "./routing/router.js";
|
|
11
12
|
import { NodePool } from "../runtime/server/render/queue/pool.js";
|
|
12
13
|
import { HTMLStringCache } from "../runtime/server/html-string-cache.js";
|
|
13
14
|
import { FORBIDDEN_PATH_KEYS } from "@astrojs/internal-helpers/object";
|
|
14
15
|
import { loadLogger } from "./logger/load.js";
|
|
16
|
+
const PipelineFeatures = {
|
|
17
|
+
redirects: 1 << 0,
|
|
18
|
+
sessions: 1 << 1,
|
|
19
|
+
actions: 1 << 2,
|
|
20
|
+
middleware: 1 << 3,
|
|
21
|
+
i18n: 1 << 4,
|
|
22
|
+
cache: 1 << 5
|
|
23
|
+
};
|
|
15
24
|
class Pipeline {
|
|
16
25
|
internalMiddleware;
|
|
17
26
|
resolvedMiddleware = void 0;
|
|
@@ -22,6 +31,12 @@ class Pipeline {
|
|
|
22
31
|
compiledCacheRoutes = void 0;
|
|
23
32
|
nodePool;
|
|
24
33
|
htmlStringCache;
|
|
34
|
+
/**
|
|
35
|
+
* Bit mask of pipeline features activated by handler classes.
|
|
36
|
+
* Each handler sets its bit via `|=`. Only meaningful when a
|
|
37
|
+
* custom `src/app.ts` fetch handler is in use.
|
|
38
|
+
*/
|
|
39
|
+
usedFeatures = 0;
|
|
25
40
|
logger;
|
|
26
41
|
manifest;
|
|
27
42
|
/**
|
|
@@ -55,6 +70,10 @@ class Pipeline {
|
|
|
55
70
|
cacheProvider;
|
|
56
71
|
cacheConfig;
|
|
57
72
|
serverIslands;
|
|
73
|
+
/** Route data derived from the manifest, used for route matching. */
|
|
74
|
+
manifestData;
|
|
75
|
+
/** Pattern-matching router built from manifestData. */
|
|
76
|
+
#router;
|
|
58
77
|
constructor(logger, manifest, runtimeMode, renderers, resolve, streaming, adapterName = manifest.adapterName, clientDirectives = manifest.clientDirectives, inlinedScripts = manifest.inlinedScripts, compressHTML = manifest.compressHTML, i18n = manifest.i18n, middleware = manifest.middleware, routeCache = new RouteCache(logger, runtimeMode), site = manifest.site ? new URL(manifest.site) : void 0, defaultRoutes = createDefaultRoutes(manifest), actions = manifest.actions, sessionDriver = manifest.sessionDriver, cacheProvider = manifest.cacheProvider, cacheConfig = manifest.cacheConfig, serverIslands = manifest.serverIslandMappings) {
|
|
59
78
|
this.logger = logger;
|
|
60
79
|
this.manifest = manifest;
|
|
@@ -76,12 +95,14 @@ class Pipeline {
|
|
|
76
95
|
this.cacheProvider = cacheProvider;
|
|
77
96
|
this.cacheConfig = cacheConfig;
|
|
78
97
|
this.serverIslands = serverIslands;
|
|
98
|
+
this.manifestData = { routes: (manifest.routes ?? []).map((route) => route.routeData) };
|
|
99
|
+
ensure404Route(this.manifestData);
|
|
100
|
+
this.#router = new Router(this.manifestData.routes, {
|
|
101
|
+
base: manifest.base,
|
|
102
|
+
trailingSlash: manifest.trailingSlash,
|
|
103
|
+
buildFormat: manifest.buildFormat
|
|
104
|
+
});
|
|
79
105
|
this.internalMiddleware = [];
|
|
80
|
-
if (i18n?.strategy !== "manual") {
|
|
81
|
-
this.internalMiddleware.push(
|
|
82
|
-
createI18nMiddleware(i18n, manifest.base, manifest.trailingSlash, manifest.buildFormat)
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
106
|
if (manifest.experimentalQueuedRendering.enabled) {
|
|
86
107
|
this.nodePool = this.createNodePool(
|
|
87
108
|
manifest.experimentalQueuedRendering.poolSize ?? 1e3,
|
|
@@ -92,6 +113,27 @@ class Pipeline {
|
|
|
92
113
|
}
|
|
93
114
|
}
|
|
94
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Low-level route matching against the manifest routes. Returns the
|
|
118
|
+
* matched `RouteData` or `undefined`. Does not filter prerendered
|
|
119
|
+
* routes or check public assets — use `BaseApp.match()` for that.
|
|
120
|
+
*/
|
|
121
|
+
matchRoute(pathname) {
|
|
122
|
+
const match = this.#router.match(pathname, { allowWithoutBase: true });
|
|
123
|
+
if (match.type !== "match") return void 0;
|
|
124
|
+
return match.route;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Rebuilds the internal router after routes have been added or
|
|
128
|
+
* removed (e.g. by the dev server on HMR).
|
|
129
|
+
*/
|
|
130
|
+
rebuildRouter() {
|
|
131
|
+
this.#router = new Router(this.manifestData.routes, {
|
|
132
|
+
base: this.manifest.base,
|
|
133
|
+
trailingSlash: this.manifest.trailingSlash,
|
|
134
|
+
buildFormat: this.manifest.buildFormat
|
|
135
|
+
});
|
|
136
|
+
}
|
|
95
137
|
/**
|
|
96
138
|
* Resolves the middleware from the manifest, and returns the `onRequest` function. If `onRequest` isn't there,
|
|
97
139
|
* it returns a no-op function
|
|
@@ -243,5 +285,6 @@ class Pipeline {
|
|
|
243
285
|
}
|
|
244
286
|
}
|
|
245
287
|
export {
|
|
246
|
-
Pipeline
|
|
288
|
+
Pipeline,
|
|
289
|
+
PipelineFeatures
|
|
247
290
|
};
|
package/dist/core/build/app.d.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import { BaseApp
|
|
1
|
+
import { BaseApp } from '../app/entrypoints/index.js';
|
|
2
2
|
import type { SSRManifest } from '../app/types.js';
|
|
3
3
|
import type { BuildInternals } from './internal.js';
|
|
4
4
|
import { BuildPipeline } from './pipeline.js';
|
|
5
5
|
import type { StaticBuildOptions } from './types.js';
|
|
6
|
-
import type { CreateRenderContext, RenderContext } from '../render-context.js';
|
|
7
6
|
import type { LogRequestPayload } from '../app/base.js';
|
|
7
|
+
import type { ErrorHandler } from '../errors/handler.js';
|
|
8
8
|
import type { PoolStatsReport } from '../../runtime/server/render/queue/pool.js';
|
|
9
9
|
export declare class BuildApp extends BaseApp<BuildPipeline> {
|
|
10
10
|
createPipeline(_streaming: boolean, manifest: SSRManifest, ..._args: any[]): BuildPipeline;
|
|
11
|
-
createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
|
|
12
11
|
isDev(): boolean;
|
|
13
12
|
setInternals(internals: BuildInternals): void;
|
|
14
13
|
setOptions(options: StaticBuildOptions): void;
|
|
15
14
|
getOptions(): StaticBuildOptions;
|
|
16
15
|
getSettings(): import("../../types/astro.js").AstroSettings;
|
|
17
|
-
|
|
16
|
+
protected createErrorHandler(): ErrorHandler;
|
|
18
17
|
getQueueStats(): PoolStatsReport | undefined;
|
|
19
18
|
logRequest(_options: LogRequestPayload): void;
|
|
20
19
|
}
|
package/dist/core/build/app.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { BaseApp } from "../app/entrypoints/index.js";
|
|
2
2
|
import { BuildPipeline } from "./pipeline.js";
|
|
3
|
+
import { BuildErrorHandler } from "../errors/build-handler.js";
|
|
3
4
|
class BuildApp extends BaseApp {
|
|
4
5
|
createPipeline(_streaming, manifest, ..._args) {
|
|
5
6
|
return BuildPipeline.create({
|
|
6
7
|
manifest
|
|
7
8
|
});
|
|
8
9
|
}
|
|
9
|
-
async createRenderContext(payload) {
|
|
10
|
-
return await super.createRenderContext({
|
|
11
|
-
...payload
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
10
|
isDev() {
|
|
15
11
|
return true;
|
|
16
12
|
}
|
|
@@ -28,18 +24,8 @@ class BuildApp extends BaseApp {
|
|
|
28
24
|
getSettings() {
|
|
29
25
|
return this.pipeline.getSettings();
|
|
30
26
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (options.response) {
|
|
34
|
-
return options.response;
|
|
35
|
-
}
|
|
36
|
-
throw options.error;
|
|
37
|
-
} else {
|
|
38
|
-
return super.renderError(request, {
|
|
39
|
-
...options,
|
|
40
|
-
prerenderedErrorPageFetch: void 0
|
|
41
|
-
});
|
|
42
|
-
}
|
|
27
|
+
createErrorHandler() {
|
|
28
|
+
return new BuildErrorHandler(this);
|
|
43
29
|
}
|
|
44
30
|
getQueueStats() {
|
|
45
31
|
if (this.pipeline.nodePool) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isCSSRequest } from "vite";
|
|
2
2
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
|
|
3
3
|
import { isPropagatedAssetBoundary } from "../../head-propagation/boundary.js";
|
|
4
|
+
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../../vite-plugin-pages/const.js";
|
|
4
5
|
import {
|
|
5
6
|
getParentExtendedModuleInfos,
|
|
6
7
|
getParentModuleInfos,
|
|
@@ -18,7 +19,12 @@ function pluginCSS(options, internals) {
|
|
|
18
19
|
function isBuildCssBoundary(id, ctx) {
|
|
19
20
|
if (isPropagatedAssetBoundary(id)) return true;
|
|
20
21
|
const info = ctx.getModuleInfo(id);
|
|
21
|
-
|
|
22
|
+
if (!info || !moduleIsTopLevelPage(info)) return false;
|
|
23
|
+
const allImporters = info.importers.concat(info.dynamicImporters);
|
|
24
|
+
const hasNonVirtualPageImporter = allImporters.some(
|
|
25
|
+
(importer) => !importer.includes(VIRTUAL_PAGE_RESOLVED_MODULE_ID)
|
|
26
|
+
);
|
|
27
|
+
return !hasNonVirtualPageImporter;
|
|
22
28
|
}
|
|
23
29
|
function rollupPluginAstroBuildCSS(options) {
|
|
24
30
|
const { internals, buildOptions } = options;
|
|
@@ -47,7 +47,8 @@ async function manifestBuildPostHook(options, internals, {
|
|
|
47
47
|
logger: options.logger,
|
|
48
48
|
middlewareEntryPoint: shouldPassMiddlewareEntryPoint ? internals.middlewareEntryPoint : void 0
|
|
49
49
|
});
|
|
50
|
-
const
|
|
50
|
+
const ssrManifest = stripPrerenderedRouteStyles(manifest);
|
|
51
|
+
const code = injectManifest(ssrManifest, ssrManifestChunk.code);
|
|
51
52
|
mutate(ssrManifestChunk.fileName, code, false);
|
|
52
53
|
}
|
|
53
54
|
const prerenderManifestChunk = chunks.find(
|
|
@@ -82,6 +83,15 @@ function injectManifest(manifest, code) {
|
|
|
82
83
|
return JSON.stringify(manifest);
|
|
83
84
|
});
|
|
84
85
|
}
|
|
86
|
+
function stripPrerenderedRouteStyles(manifest) {
|
|
87
|
+
let stripped = false;
|
|
88
|
+
const routes = manifest.routes.map((route) => {
|
|
89
|
+
if (!route.routeData.prerender || route.styles.length === 0) return route;
|
|
90
|
+
stripped = true;
|
|
91
|
+
return { ...route, styles: [] };
|
|
92
|
+
});
|
|
93
|
+
return stripped ? { ...manifest, routes } : manifest;
|
|
94
|
+
}
|
|
85
95
|
async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
86
96
|
const { settings } = opts;
|
|
87
97
|
const routes = [];
|
|
@@ -186,7 +186,14 @@ async function buildEnvironments(opts, internals) {
|
|
|
186
186
|
}
|
|
187
187
|
return [prefix, cleanChunkName(name), suffix].join("");
|
|
188
188
|
},
|
|
189
|
-
assetFileNames
|
|
189
|
+
assetFileNames(assetInfo) {
|
|
190
|
+
const name = assetInfo.names?.[0] ?? "";
|
|
191
|
+
if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
|
|
192
|
+
const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
|
|
193
|
+
return `${settings.config.build.assets}/${sanitizedName}.[hash][extname]`;
|
|
194
|
+
}
|
|
195
|
+
return `${settings.config.build.assets}/[name].[hash][extname]`;
|
|
196
|
+
},
|
|
190
197
|
...viteConfig.build?.rollupOptions?.output,
|
|
191
198
|
entryFileNames(chunkInfo) {
|
|
192
199
|
if (chunkInfo.facadeModuleId?.startsWith(VIRTUAL_PAGE_RESOLVED_MODULE_ID)) {
|
|
@@ -289,7 +296,14 @@ async function buildEnvironments(opts, internals) {
|
|
|
289
296
|
chunkFileNames(chunkInfo) {
|
|
290
297
|
return `${settings.config.build.assets}/${cleanChunkName(chunkInfo.name)}.[hash].js`;
|
|
291
298
|
},
|
|
292
|
-
assetFileNames
|
|
299
|
+
assetFileNames(assetInfo) {
|
|
300
|
+
const name = assetInfo.names?.[0] ?? "";
|
|
301
|
+
if (name.includes(ASTRO_PAGE_EXTENSION_POST_PATTERN)) {
|
|
302
|
+
const [sanitizedName] = name.split(ASTRO_PAGE_EXTENSION_POST_PATTERN);
|
|
303
|
+
return `${settings.config.build.assets}/${sanitizedName}.[hash][extname]`;
|
|
304
|
+
}
|
|
305
|
+
return `${settings.config.build.assets}/[name].[hash][extname]`;
|
|
306
|
+
},
|
|
293
307
|
...viteConfig.environments?.client?.build?.rollupOptions?.output
|
|
294
308
|
}
|
|
295
309
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { BaseApp } from '../app/base.js';
|
|
2
|
+
import type { FetchState } from '../fetch/fetch-state.js';
|
|
3
|
+
import type { Pipeline } from '../base-pipeline.js';
|
|
4
|
+
/**
|
|
5
|
+
* Registers a cache provider on the given `FetchState`. When
|
|
6
|
+
* `state.resolve('cache')` is first called, the appropriate cache
|
|
7
|
+
* implementation is created (disabled, noop for dev, or real).
|
|
8
|
+
*
|
|
9
|
+
* Returns synchronously when cache is not configured or in dev mode.
|
|
10
|
+
*/
|
|
11
|
+
export declare function provideCache(state: FetchState): Promise<void> | void;
|
|
12
|
+
/**
|
|
13
|
+
* Wraps a render callback with cache provider logic. Handles both
|
|
14
|
+
* runtime caching (onRequest) and CDN-based providers (headers only).
|
|
15
|
+
*
|
|
16
|
+
* - When a cache provider with `onRequest` is configured, the callback
|
|
17
|
+
* is wrapped so the provider can serve from cache or fall through.
|
|
18
|
+
* - When only CDN headers are needed, the callback runs directly and
|
|
19
|
+
* cache headers are applied to the response.
|
|
20
|
+
* - When no cache provider is configured, the callback runs as-is.
|
|
21
|
+
*
|
|
22
|
+
* Cache headers (`CDN-Cache-Control`, `Cache-Tag`) are stripped from
|
|
23
|
+
* the final response after the runtime provider has read them.
|
|
24
|
+
*/
|
|
25
|
+
export declare class CacheHandler {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(app: BaseApp<Pipeline>);
|
|
28
|
+
handle(state: FetchState, next: () => Promise<Response>): Promise<Response>;
|
|
29
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PipelineFeatures } from "../base-pipeline.js";
|
|
2
|
+
import { AstroCache, applyCacheHeaders } from "./runtime/cache.js";
|
|
3
|
+
import { NoopAstroCache, DisabledAstroCache } from "./runtime/noop.js";
|
|
4
|
+
import { compileCacheRoutes, matchCacheRoute } from "./runtime/route-matching.js";
|
|
5
|
+
const CACHE_KEY = "cache";
|
|
6
|
+
function provideCache(state) {
|
|
7
|
+
const pipeline = state.pipeline;
|
|
8
|
+
if (!pipeline.cacheConfig) {
|
|
9
|
+
state.provide(CACHE_KEY, {
|
|
10
|
+
create: () => new DisabledAstroCache(pipeline.logger)
|
|
11
|
+
});
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (pipeline.runtimeMode === "development") {
|
|
15
|
+
state.provide(CACHE_KEY, {
|
|
16
|
+
create: () => new NoopAstroCache()
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
return provideCacheAsync(state, pipeline);
|
|
21
|
+
}
|
|
22
|
+
async function provideCacheAsync(state, pipeline) {
|
|
23
|
+
const cacheProvider = await pipeline.getCacheProvider();
|
|
24
|
+
state.provide(CACHE_KEY, {
|
|
25
|
+
create() {
|
|
26
|
+
const cache = new AstroCache(cacheProvider);
|
|
27
|
+
if (pipeline.cacheConfig?.routes) {
|
|
28
|
+
if (!pipeline.compiledCacheRoutes) {
|
|
29
|
+
pipeline.compiledCacheRoutes = compileCacheRoutes(
|
|
30
|
+
pipeline.cacheConfig.routes,
|
|
31
|
+
pipeline.manifest.base,
|
|
32
|
+
pipeline.manifest.trailingSlash
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const matched = matchCacheRoute(state.pathname, pipeline.compiledCacheRoutes);
|
|
36
|
+
if (matched) {
|
|
37
|
+
cache.set(matched);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return cache;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
class CacheHandler {
|
|
45
|
+
#app;
|
|
46
|
+
constructor(app) {
|
|
47
|
+
this.#app = app;
|
|
48
|
+
}
|
|
49
|
+
async handle(state, next) {
|
|
50
|
+
this.#app.pipeline.usedFeatures |= PipelineFeatures.cache;
|
|
51
|
+
if (!this.#app.pipeline.cacheProvider) {
|
|
52
|
+
return next();
|
|
53
|
+
}
|
|
54
|
+
const cache = state.resolve(CACHE_KEY);
|
|
55
|
+
const cacheProvider = await this.#app.pipeline.getCacheProvider();
|
|
56
|
+
if (cacheProvider?.onRequest) {
|
|
57
|
+
const response2 = await cacheProvider.onRequest(
|
|
58
|
+
{
|
|
59
|
+
request: state.request,
|
|
60
|
+
url: new URL(state.request.url),
|
|
61
|
+
waitUntil: state.renderOptions.waitUntil
|
|
62
|
+
},
|
|
63
|
+
async () => {
|
|
64
|
+
const res = await next();
|
|
65
|
+
applyCacheHeaders(cache, res);
|
|
66
|
+
return res;
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
response2.headers.delete("CDN-Cache-Control");
|
|
70
|
+
response2.headers.delete("Cache-Tag");
|
|
71
|
+
return response2;
|
|
72
|
+
}
|
|
73
|
+
const response = await next();
|
|
74
|
+
applyCacheHeaders(cache, response);
|
|
75
|
+
return response;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
CacheHandler,
|
|
80
|
+
provideCache
|
|
81
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
2
3
|
import { preprocessCSS } from "vite";
|
|
3
4
|
import { AstroErrorData, CSSError, positionAt } from "../errors/index.js";
|
|
4
5
|
import { normalizePath } from "../viteUtils.js";
|
|
@@ -31,6 +32,21 @@ function rewriteCssUrls(css, base) {
|
|
|
31
32
|
return match;
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
function withNestingExcluded(viteConfig) {
|
|
36
|
+
let Features;
|
|
37
|
+
try {
|
|
38
|
+
const requireFromRoot = createRequire(viteConfig.root + "/");
|
|
39
|
+
Features = requireFromRoot("lightningcss").Features;
|
|
40
|
+
} catch {
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
const lcss = viteConfig.css?.lightningcss ?? {};
|
|
44
|
+
const prevExclude = lcss.exclude ?? 0;
|
|
45
|
+
return {
|
|
46
|
+
...viteConfig,
|
|
47
|
+
css: { ...viteConfig.css, lightningcss: { ...lcss, exclude: prevExclude | Features.Nesting } }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
34
50
|
function createStylePreprocessor({
|
|
35
51
|
filename,
|
|
36
52
|
viteConfig,
|
|
@@ -44,7 +60,8 @@ function createStylePreprocessor({
|
|
|
44
60
|
const lang = `.${attrs?.lang || "css"}`.toLowerCase();
|
|
45
61
|
const id = `${filename}?astro&type=style&index=${index}&lang${lang}`;
|
|
46
62
|
try {
|
|
47
|
-
const
|
|
63
|
+
const effectiveViteConfig = viteConfig.css?.transformer === "lightningcss" ? withNestingExcluded(viteConfig) ?? viteConfig : viteConfig;
|
|
64
|
+
const result = await preprocessCSS(content, id, effectiveViteConfig);
|
|
48
65
|
const rewrittenCode = rewriteCssUrls(result.code, astroConfig.base);
|
|
49
66
|
cssPartialCompileResults[index] = {
|
|
50
67
|
// Use `in` operator to handle both Go compiler (boolean `true`) and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { resolveConfig, resolveConfigPath, resolveRoot, } from './config.js';
|
|
2
2
|
export { mergeConfig } from './merge.js';
|
|
3
3
|
export { createSettings } from './settings.js';
|
|
4
|
-
export { loadTSConfig, updateTSConfigForFramework } from './tsconfig.js';
|
|
4
|
+
export { loadTSConfig, updateTSConfigForFramework, type TSConfigLoadedResult, type TSConfigResult, } from './tsconfig.js';
|
|
@@ -5,7 +5,10 @@ import {
|
|
|
5
5
|
} from "./config.js";
|
|
6
6
|
import { mergeConfig } from "./merge.js";
|
|
7
7
|
import { createSettings } from "./settings.js";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
loadTSConfig,
|
|
10
|
+
updateTSConfigForFramework
|
|
11
|
+
} from "./tsconfig.js";
|
|
9
12
|
export {
|
|
10
13
|
createSettings,
|
|
11
14
|
loadTSConfig,
|