astro 7.1.3 → 7.1.5
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/assets/types.d.ts +11 -0
- package/dist/cli/dev/background.js +1 -0
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +18 -22
- package/dist/content/content-layer.js +3 -3
- package/dist/content/loaders/file.js +1 -1
- package/dist/content/loaders/glob.js +6 -1
- package/dist/core/app/types.d.ts +0 -2
- package/dist/core/base-pipeline.js +9 -3
- package/dist/core/build/internal.d.ts +8 -0
- package/dist/core/build/internal.js +1 -0
- package/dist/core/build/plugins/plugin-css.js +44 -0
- package/dist/core/build/plugins/plugin-manifest.js +1 -6
- package/dist/core/config/schemas/base.d.ts +2 -68
- package/dist/core/config/schemas/base.js +2 -65
- package/dist/core/config/schemas/defaults.d.ts +67 -0
- package/dist/core/config/schemas/defaults.js +65 -0
- package/dist/core/config/settings.js +1 -1
- package/dist/core/config/vite-load.js +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/cookies/cookies.js +1 -1
- package/dist/core/create-vite.js +2 -0
- package/dist/core/createMinimalViteDevServer.d.ts +1 -1
- package/dist/core/createMinimalViteDevServer.js +3 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/default-handler.d.ts +1 -1
- package/dist/core/errors/default-handler.js +16 -0
- package/dist/core/errors/dev-handler.d.ts +1 -1
- package/dist/core/errors/dev-handler.js +10 -0
- package/dist/core/errors/handler.d.ts +14 -0
- package/dist/core/errors/handler.js +7 -0
- package/dist/core/logger/load.d.ts +4 -0
- package/dist/core/logger/load.js +25 -51
- package/dist/core/logger/utils.d.ts +21 -0
- package/dist/core/logger/utils.js +20 -0
- package/dist/core/logger/vite-plugin.d.ts +30 -0
- package/dist/core/logger/vite-plugin.js +79 -0
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/routing/handler.js +16 -2
- package/dist/core/session/drivers.d.ts +1 -1
- package/dist/core/session/handler.js +2 -1
- package/dist/core/session/runtime.d.ts +10 -7
- package/dist/core/session/runtime.js +10 -7
- package/dist/manifest/serialized.js +4 -6
- package/dist/types/public/config.d.ts +3 -3
- package/package.json +10 -10
- package/components/env.d.ts +0 -2
package/dist/core/create-vite.js
CHANGED
|
@@ -48,6 +48,7 @@ import { ServerIslandsState } from "./server-islands/shared-state.js";
|
|
|
48
48
|
import { vitePluginServerIslands } from "./server-islands/vite-plugin-server-islands.js";
|
|
49
49
|
import { vitePluginCacheProvider } from "./cache/vite-plugin.js";
|
|
50
50
|
import { vitePluginSessionDriver } from "./session/vite-plugin.js";
|
|
51
|
+
import { vitePluginLogger } from "./logger/vite-plugin.js";
|
|
51
52
|
import { isObject } from "./util-runtime.js";
|
|
52
53
|
import { vitePluginEnvironment } from "../vite-plugin-environment/index.js";
|
|
53
54
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "./constants.js";
|
|
@@ -180,6 +181,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
180
181
|
vitePluginServerIslands({ settings, logger, serverIslandsState }),
|
|
181
182
|
vitePluginSessionDriver({ settings }),
|
|
182
183
|
vitePluginCacheProvider({ settings }),
|
|
184
|
+
vitePluginLogger({ settings }),
|
|
183
185
|
astroContainer(),
|
|
184
186
|
astroHmrReloadPlugin(),
|
|
185
187
|
vitePluginChromedevtools({ settings }),
|
|
@@ -5,4 +5,4 @@ import { type ViteDevServer, type Plugin } from 'vite';
|
|
|
5
5
|
* NOTE: This is intentionally in its own module to avoid pulling `vite`'s heavy `createServer`
|
|
6
6
|
* (and transitively Rollup) into every file that imports from `viteUtils.ts`.
|
|
7
7
|
*/
|
|
8
|
-
export declare function createMinimalViteDevServer(plugins?: Plugin[]): Promise<ViteDevServer>;
|
|
8
|
+
export declare function createMinimalViteDevServer(plugins?: Plugin[], root?: string): Promise<ViteDevServer>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createServer } from "vite";
|
|
2
|
-
async function createMinimalViteDevServer(plugins = []) {
|
|
2
|
+
async function createMinimalViteDevServer(plugins = [], root) {
|
|
3
3
|
return await createServer({
|
|
4
|
+
root,
|
|
4
5
|
configFile: false,
|
|
5
6
|
server: { middlewareMode: true, hmr: false, watch: null, ws: false },
|
|
6
7
|
optimizeDeps: { noDiscovery: true },
|
|
7
8
|
clearScreen: false,
|
|
8
9
|
appType: "custom",
|
|
9
10
|
ssr: { external: true },
|
|
11
|
+
resolve: { tsconfigPaths: true },
|
|
10
12
|
plugins
|
|
11
13
|
});
|
|
12
14
|
}
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "7.1.
|
|
29
|
+
const currentVersion = "7.1.5";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseApp, RenderErrorOptions } from '../app/base.js';
|
|
2
2
|
import type { Pipeline } from '../base-pipeline.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type ErrorHandler } from './handler.js';
|
|
4
4
|
/**
|
|
5
5
|
* The default error handler used in production SSR. Attempts to render the
|
|
6
6
|
* matching error route (404.astro / 500.astro), falling back to a plain
|
|
@@ -9,6 +9,7 @@ import { provideSession } from "../session/handler.js";
|
|
|
9
9
|
import { validateHost } from "../app/validate-headers.js";
|
|
10
10
|
import { getErrorRoutePath } from "../../i18n/error-routes.js";
|
|
11
11
|
import { getOutputFilename } from "../output-filename.js";
|
|
12
|
+
import { rewroteToEmptyErrorResponse } from "./handler.js";
|
|
12
13
|
class DefaultErrorHandler {
|
|
13
14
|
#app;
|
|
14
15
|
#astroMiddleware;
|
|
@@ -82,6 +83,21 @@ class DefaultErrorHandler {
|
|
|
82
83
|
errorState,
|
|
83
84
|
this.#pagesHandler.handle.bind(this.#pagesHandler)
|
|
84
85
|
);
|
|
86
|
+
if (rewroteToEmptyErrorResponse(
|
|
87
|
+
skipMiddleware,
|
|
88
|
+
errorRouteData,
|
|
89
|
+
errorState.routeData,
|
|
90
|
+
response2
|
|
91
|
+
)) {
|
|
92
|
+
return this.renderError(request, {
|
|
93
|
+
...resolvedRenderOptions,
|
|
94
|
+
status,
|
|
95
|
+
error,
|
|
96
|
+
response: originalResponse,
|
|
97
|
+
skipMiddleware: true,
|
|
98
|
+
pathname: resolvedPathname
|
|
99
|
+
});
|
|
100
|
+
}
|
|
85
101
|
const newResponse = mergeResponses(response2, originalResponse);
|
|
86
102
|
prepareResponse(newResponse, resolvedRenderOptions);
|
|
87
103
|
return newResponse;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseApp, RenderErrorOptions } from '../app/base.js';
|
|
2
2
|
import type { Pipeline } from '../base-pipeline.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type ErrorHandler } from './handler.js';
|
|
4
4
|
export interface DevErrorHandlerOptions {
|
|
5
5
|
/**
|
|
6
6
|
* Whether to inject CSP meta tags into the rendered error page response.
|
|
@@ -4,6 +4,7 @@ import { PagesHandler } from "../pages/handler.js";
|
|
|
4
4
|
import { getCustom404Route, getCustom500Route } from "../routing/helpers.js";
|
|
5
5
|
import { isAstroError } from "./index.js";
|
|
6
6
|
import { MiddlewareNoDataOrNextCalled, MiddlewareNotAResponse } from "./errors-data.js";
|
|
7
|
+
import { rewroteToEmptyErrorResponse } from "./handler.js";
|
|
7
8
|
class DevErrorHandler {
|
|
8
9
|
#app;
|
|
9
10
|
#shouldInjectCspMetaTags;
|
|
@@ -46,6 +47,15 @@ class DevErrorHandler {
|
|
|
46
47
|
errorState,
|
|
47
48
|
this.#pagesHandler.handle.bind(this.#pagesHandler)
|
|
48
49
|
);
|
|
50
|
+
if (rewroteToEmptyErrorResponse(skipMiddleware, routeData, errorState.routeData, response)) {
|
|
51
|
+
return this.renderError(request, {
|
|
52
|
+
...resolvedRenderOptions,
|
|
53
|
+
status,
|
|
54
|
+
error,
|
|
55
|
+
skipMiddleware: true,
|
|
56
|
+
pathname: resolvedPathname
|
|
57
|
+
});
|
|
58
|
+
}
|
|
49
59
|
if (error) {
|
|
50
60
|
app.logger.error("router", error.stack || error.message);
|
|
51
61
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RenderErrorOptions } from '../app/base.js';
|
|
2
|
+
import type { RouteData } from '../../types/public/index.js';
|
|
2
3
|
/**
|
|
3
4
|
* A strategy for rendering error responses (404, 500, etc.). Each execution
|
|
4
5
|
* environment (prod SSR, build/prerender, dev server) supplies its own
|
|
@@ -7,3 +8,16 @@ import type { RenderErrorOptions } from '../app/base.js';
|
|
|
7
8
|
export interface ErrorHandler {
|
|
8
9
|
renderError(request: Request, options: RenderErrorOptions): Promise<Response>;
|
|
9
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Whether a middleware rewrite (`ctx.rewrite()` / `next(payload)`) issued while
|
|
13
|
+
* rendering the error page dead-ended in another empty reroutable (404/500)
|
|
14
|
+
* response. The rewrite swaps the state's routeData away from the error route,
|
|
15
|
+
* so returning that render as-is would produce a blank page; the error handler
|
|
16
|
+
* should instead retry rendering the error page without middleware.
|
|
17
|
+
*
|
|
18
|
+
* @param skipMiddleware Whether middleware was already skipped for this render.
|
|
19
|
+
* @param errorRouteData The error route matched before middleware ran.
|
|
20
|
+
* @param renderedRouteData The route data on the state after middleware ran.
|
|
21
|
+
* @param response The response produced by the middleware-driven render.
|
|
22
|
+
*/
|
|
23
|
+
export declare function rewroteToEmptyErrorResponse(skipMiddleware: boolean, errorRouteData: RouteData, renderedRouteData: RouteData | undefined, response: Response): boolean;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { REROUTABLE_STATUS_CODES } from "../constants.js";
|
|
2
|
+
function rewroteToEmptyErrorResponse(skipMiddleware, errorRouteData, renderedRouteData, response) {
|
|
3
|
+
return skipMiddleware === false && renderedRouteData !== errorRouteData && response.body === null && REROUTABLE_STATUS_CODES.includes(response.status);
|
|
4
|
+
}
|
|
5
|
+
export {
|
|
6
|
+
rewroteToEmptyErrorResponse
|
|
7
|
+
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { AstroLogger, type AstroLoggerDestination } from './core.js';
|
|
2
2
|
import type { LoggerHandlerConfig } from './config.js';
|
|
3
3
|
import type { AstroConfig, AstroInlineConfig } from '../../types/public/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Loads a logger destination in a Node context, i.e. outside of a built server bundle.
|
|
6
|
+
* Inside the bundle, the destination comes from the `virtual:astro:logger` module instead.
|
|
7
|
+
*/
|
|
4
8
|
export declare function loadLoggerDestination(config: LoggerHandlerConfig): Promise<AstroLoggerDestination>;
|
|
5
9
|
/**
|
|
6
10
|
* It attempts to load a logger from the entrypoint.
|
package/dist/core/logger/load.js
CHANGED
|
@@ -1,64 +1,38 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
1
3
|
import { AstroLogger } from "./core.js";
|
|
2
4
|
import { AstroError } from "../errors/index.js";
|
|
3
5
|
import { UnableToLoadLogger } from "../errors/errors-data.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { createNodeLoggerFromFlags } from "./impls/node.js";
|
|
7
|
+
import {
|
|
8
|
+
COMPOSE_LOGGER_ENTRYPOINT,
|
|
9
|
+
normalizeLoggerConfig
|
|
10
|
+
} from "./utils.js";
|
|
11
|
+
async function createDestination(config) {
|
|
12
|
+
const specifier = isAbsolute(config.entrypoint) ? pathToFileURL(config.entrypoint).href : config.entrypoint;
|
|
13
|
+
const logger = await import(
|
|
14
|
+
/* @vite-ignore */
|
|
15
|
+
specifier
|
|
16
|
+
);
|
|
17
|
+
if (config.entrypoint === COMPOSE_LOGGER_ENTRYPOINT) {
|
|
18
|
+
return logger.default(await Promise.all((config.loggers ?? []).map(createDestination)));
|
|
19
|
+
}
|
|
20
|
+
return logger.default(config.config);
|
|
10
21
|
}
|
|
11
22
|
async function loadLoggerDestination(config) {
|
|
12
|
-
|
|
13
|
-
const entrypoint = normalizeEntrypoint(config.entrypoint);
|
|
23
|
+
const normalized = normalizeLoggerConfig(config);
|
|
14
24
|
try {
|
|
15
|
-
|
|
16
|
-
case "astro/logger/node": {
|
|
17
|
-
return nodeLoggerCreator(config.config);
|
|
18
|
-
}
|
|
19
|
-
case "astro/logger/console": {
|
|
20
|
-
return consoleLoggerCreator(config.config);
|
|
21
|
-
}
|
|
22
|
-
case "astro/logger/json": {
|
|
23
|
-
return jsonLoggerCreator(config.config);
|
|
24
|
-
}
|
|
25
|
-
case "astro/logger/compose": {
|
|
26
|
-
let destinations = [];
|
|
27
|
-
if (config.config?.loggers) {
|
|
28
|
-
const loggers = config.config?.loggers;
|
|
29
|
-
destinations = await Promise.all(
|
|
30
|
-
loggers.map(async (loggerConfig) => {
|
|
31
|
-
const logger = await import(
|
|
32
|
-
/* @vite-ignore */
|
|
33
|
-
normalizeEntrypoint(loggerConfig.entrypoint)
|
|
34
|
-
);
|
|
35
|
-
return logger.default(loggerConfig.config);
|
|
36
|
-
})
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
return composeLoggerCreator(destinations);
|
|
40
|
-
}
|
|
41
|
-
default: {
|
|
42
|
-
const logger = await import(
|
|
43
|
-
/* @vite-ignore */
|
|
44
|
-
entrypoint
|
|
45
|
-
);
|
|
46
|
-
return logger.default(config.config);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
25
|
+
return await createDestination(normalized);
|
|
49
26
|
} catch (e) {
|
|
27
|
+
const error = new AstroError({
|
|
28
|
+
...UnableToLoadLogger,
|
|
29
|
+
message: UnableToLoadLogger.message(normalized.entrypoint)
|
|
30
|
+
});
|
|
50
31
|
if (e instanceof Error) {
|
|
51
|
-
cause = e;
|
|
32
|
+
error.cause = e;
|
|
52
33
|
}
|
|
34
|
+
throw error;
|
|
53
35
|
}
|
|
54
|
-
const error = new AstroError({
|
|
55
|
-
...UnableToLoadLogger,
|
|
56
|
-
message: UnableToLoadLogger.message(entrypoint)
|
|
57
|
-
});
|
|
58
|
-
if (cause) {
|
|
59
|
-
error.cause = cause;
|
|
60
|
-
}
|
|
61
|
-
throw error;
|
|
62
36
|
}
|
|
63
37
|
async function loadOrCreateNodeLogger(astroConfig, inlineAstroConfig) {
|
|
64
38
|
if (inlineAstroConfig._logger) return inlineAstroConfig._logger;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { LoggerHandlerConfig } from './config.js';
|
|
2
|
+
export declare const COMPOSE_LOGGER_ENTRYPOINT = "astro/logger/compose";
|
|
3
|
+
export interface NormalizedLoggerConfig {
|
|
4
|
+
/** An absolute file path or a package specifier */
|
|
5
|
+
entrypoint: string;
|
|
6
|
+
/** Serializable options passed to the handler factory */
|
|
7
|
+
config?: Record<string, any> | undefined;
|
|
8
|
+
/** The composed handlers. Only set for `astro/logger/compose` */
|
|
9
|
+
loggers?: NormalizedLoggerConfig[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Normalizes a user-provided logger config by turning its `entrypoint` into a string that
|
|
13
|
+
* can be resolved as-is, either by Vite (see `vitePluginLogger`) or by Node
|
|
14
|
+
* (see `loadLoggerDestination`), and by applying the same treatment to the handlers
|
|
15
|
+
* composed through `astro/logger/compose`.
|
|
16
|
+
*
|
|
17
|
+
* Concretely, a `URL` entrypoint becomes an absolute file path — mirroring what session
|
|
18
|
+
* drivers do, since both Vite and `import()` can handle those — while a string entrypoint,
|
|
19
|
+
* e.g. a package specifier, is left untouched.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizeLoggerConfig(logger: LoggerHandlerConfig): NormalizedLoggerConfig;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
const COMPOSE_LOGGER_ENTRYPOINT = "astro/logger/compose";
|
|
3
|
+
function normalizeLoggerConfig(logger) {
|
|
4
|
+
const entrypoint = normalizeEntrypoint(logger.entrypoint);
|
|
5
|
+
if (entrypoint === COMPOSE_LOGGER_ENTRYPOINT) {
|
|
6
|
+
const loggers = logger.config?.loggers ?? [];
|
|
7
|
+
return {
|
|
8
|
+
entrypoint,
|
|
9
|
+
loggers: loggers.map((nested) => normalizeLoggerConfig(nested))
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
return { entrypoint, config: logger.config };
|
|
13
|
+
}
|
|
14
|
+
function normalizeEntrypoint(entrypoint) {
|
|
15
|
+
return entrypoint instanceof URL ? fileURLToPath(entrypoint) : entrypoint;
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
COMPOSE_LOGGER_ENTRYPOINT,
|
|
19
|
+
normalizeLoggerConfig
|
|
20
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Plugin as VitePlugin } from 'vite';
|
|
2
|
+
import type { AstroSettings } from '../../types/astro.js';
|
|
3
|
+
import { type NormalizedLoggerConfig } from './utils.js';
|
|
4
|
+
export declare const VIRTUAL_LOGGER_ID = "virtual:astro:logger";
|
|
5
|
+
/** Resolves an entrypoint to a module id, or `null` if it cannot be resolved. */
|
|
6
|
+
type ResolveEntrypoint = (entrypoint: string) => Promise<string | null>;
|
|
7
|
+
interface EmittedDestination {
|
|
8
|
+
/** The expression instantiating the destination, e.g. `_logger0({ level: 'info' })` */
|
|
9
|
+
expression: string;
|
|
10
|
+
/** The import statements `expression` depends on, in declaration order */
|
|
11
|
+
imports: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Emits the source of a logger destination, so that the handler is part of the bundle
|
|
15
|
+
* rather than imported at runtime from a path that no longer exists once deployed.
|
|
16
|
+
*
|
|
17
|
+
* This is the build-time counterpart of `createDestination()` in `./load.ts`: both walk
|
|
18
|
+
* the same normalized config, but this one *generates code* that instantiates the
|
|
19
|
+
* destination, while the Node one instantiates it directly through `import()`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function emitDestination(config: NormalizedLoggerConfig, resolveEntrypoint: ResolveEntrypoint,
|
|
22
|
+
/**
|
|
23
|
+
* Import names must be unique across the whole virtual module, so nested
|
|
24
|
+
* destinations continue numbering where their parent left off.
|
|
25
|
+
*/
|
|
26
|
+
nameOffset?: number): Promise<EmittedDestination>;
|
|
27
|
+
export declare function vitePluginLogger({ settings, }: {
|
|
28
|
+
settings: AstroSettings;
|
|
29
|
+
}): VitePlugin | undefined;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { UnableToLoadLogger } from "../errors/errors-data.js";
|
|
3
|
+
import { AstroError } from "../errors/index.js";
|
|
4
|
+
import { normalizeLoggerConfig } from "./utils.js";
|
|
5
|
+
const VIRTUAL_LOGGER_ID = "virtual:astro:logger";
|
|
6
|
+
const RESOLVED_VIRTUAL_LOGGER_ID = "\0" + VIRTUAL_LOGGER_ID;
|
|
7
|
+
async function emitDestination(config, resolveEntrypoint, nameOffset = 0) {
|
|
8
|
+
let resolved = null;
|
|
9
|
+
let cause;
|
|
10
|
+
try {
|
|
11
|
+
resolved = await resolveEntrypoint(config.entrypoint);
|
|
12
|
+
} catch (e) {
|
|
13
|
+
cause = e;
|
|
14
|
+
}
|
|
15
|
+
if (!resolved) {
|
|
16
|
+
const error = new AstroError({
|
|
17
|
+
...UnableToLoadLogger,
|
|
18
|
+
message: UnableToLoadLogger.message(config.entrypoint)
|
|
19
|
+
});
|
|
20
|
+
if (cause instanceof Error) {
|
|
21
|
+
error.cause = cause;
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
const name = `_logger${nameOffset}`;
|
|
26
|
+
const imports = [`import ${name} from ${JSON.stringify(resolved)};`];
|
|
27
|
+
if (config.loggers) {
|
|
28
|
+
const expressions = [];
|
|
29
|
+
for (const nested of config.loggers) {
|
|
30
|
+
const emitted = await emitDestination(nested, resolveEntrypoint, nameOffset + imports.length);
|
|
31
|
+
imports.push(...emitted.imports);
|
|
32
|
+
expressions.push(emitted.expression);
|
|
33
|
+
}
|
|
34
|
+
return { expression: `${name}([${expressions.join(", ")}])`, imports };
|
|
35
|
+
}
|
|
36
|
+
return { expression: `${name}(${JSON.stringify(config.config) ?? "undefined"})`, imports };
|
|
37
|
+
}
|
|
38
|
+
function vitePluginLogger({
|
|
39
|
+
settings
|
|
40
|
+
}) {
|
|
41
|
+
const loggerConfig = settings.config.logger;
|
|
42
|
+
if (!loggerConfig) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
name: VIRTUAL_LOGGER_ID,
|
|
47
|
+
enforce: "pre",
|
|
48
|
+
resolveId: {
|
|
49
|
+
filter: {
|
|
50
|
+
id: new RegExp(`^${VIRTUAL_LOGGER_ID}$`)
|
|
51
|
+
},
|
|
52
|
+
handler() {
|
|
53
|
+
return RESOLVED_VIRTUAL_LOGGER_ID;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
load: {
|
|
57
|
+
filter: {
|
|
58
|
+
id: new RegExp(`^${RESOLVED_VIRTUAL_LOGGER_ID}$`)
|
|
59
|
+
},
|
|
60
|
+
async handler() {
|
|
61
|
+
const importerPath = fileURLToPath(new URL("package.json", settings.config.root));
|
|
62
|
+
const { expression, imports } = await emitDestination(
|
|
63
|
+
normalizeLoggerConfig(loggerConfig),
|
|
64
|
+
async (entrypoint) => (await this.resolve(entrypoint, importerPath))?.id ?? null
|
|
65
|
+
);
|
|
66
|
+
return {
|
|
67
|
+
code: `${imports.join("\n")}
|
|
68
|
+
export default ${expression};
|
|
69
|
+
`
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
VIRTUAL_LOGGER_ID,
|
|
77
|
+
emitDestination,
|
|
78
|
+
vitePluginLogger
|
|
79
|
+
};
|
|
@@ -93,6 +93,7 @@ class AstroHandler {
|
|
|
93
93
|
const defaultStatus = this.#app.getDefaultStatusCode(routeData, pathname);
|
|
94
94
|
state.status = defaultStatus;
|
|
95
95
|
let response;
|
|
96
|
+
let finalizeError;
|
|
96
97
|
try {
|
|
97
98
|
const sessionP = this.#hasSession ? provideSession(state) : void 0;
|
|
98
99
|
const cacheP = provideCache(state);
|
|
@@ -143,8 +144,21 @@ class AstroHandler {
|
|
|
143
144
|
pathname: state.pathname
|
|
144
145
|
});
|
|
145
146
|
} finally {
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
try {
|
|
148
|
+
const finalize = state.finalizeAll();
|
|
149
|
+
if (finalize) await finalize;
|
|
150
|
+
} catch (err) {
|
|
151
|
+
finalizeError = err;
|
|
152
|
+
this.#app.logger.error(null, err.stack || err.message || String(err));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (finalizeError) {
|
|
156
|
+
return this.#app.renderError(request, {
|
|
157
|
+
...state.renderOptions,
|
|
158
|
+
status: 500,
|
|
159
|
+
error: finalizeError,
|
|
160
|
+
pathname: state.pathname
|
|
161
|
+
});
|
|
148
162
|
}
|
|
149
163
|
if (REROUTABLE_STATUS_CODES.includes(response.status) && // If the body isn't null, that means the user sets the 404 status
|
|
150
164
|
// but uses the current route to handle the 404
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SessionDriverConfig } from './types.js';
|
|
2
2
|
export declare const sessionDrivers: {
|
|
3
|
-
http: (config?: import("unstorage/drivers/http").HTTPOptions | undefined) => SessionDriverConfig;
|
|
4
3
|
fs: (config?: import("unstorage/drivers/fs").FSStorageOptions | undefined) => SessionDriverConfig;
|
|
4
|
+
http: (config?: import("unstorage/drivers/http").HTTPOptions | undefined) => SessionDriverConfig;
|
|
5
5
|
azureAppConfiguration: (config?: import("unstorage/drivers/azure-app-configuration").AzureAppConfigurationOptions | undefined) => SessionDriverConfig;
|
|
6
6
|
azureCosmos: (config?: import("unstorage/drivers/azure-cosmos").AzureCosmosOptions | undefined) => SessionDriverConfig;
|
|
7
7
|
azureKeyVault: (config?: import("unstorage/drivers/azure-key-vault").AzureKeyVaultOptions | undefined) => SessionDriverConfig;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import type { RuntimeMode } from '../../types/public/config.js';
|
|
2
2
|
import type { AstroCookies } from '../cookies/cookies.js';
|
|
3
|
+
import type { AstroLogger } from '../logger/core.js';
|
|
3
4
|
import type { SessionDriverFactory } from './types.js';
|
|
4
5
|
import type { SSRManifestSession } from '../app/types.js';
|
|
5
6
|
import { type Storage } from 'unstorage';
|
|
6
7
|
export declare const PERSIST_SYMBOL: unique symbol;
|
|
8
|
+
export interface AstroSessionOptions {
|
|
9
|
+
cookies: AstroCookies;
|
|
10
|
+
config: SSRManifestSession | undefined;
|
|
11
|
+
runtimeMode: RuntimeMode;
|
|
12
|
+
driverFactory: SessionDriverFactory | null;
|
|
13
|
+
mockStorage: Storage | null;
|
|
14
|
+
logger: AstroLogger;
|
|
15
|
+
}
|
|
7
16
|
export declare class AstroSession {
|
|
8
17
|
#private;
|
|
9
|
-
constructor({ cookies, config, runtimeMode, driverFactory, mockStorage, }:
|
|
10
|
-
cookies: AstroCookies;
|
|
11
|
-
config: SSRManifestSession | undefined;
|
|
12
|
-
runtimeMode: RuntimeMode;
|
|
13
|
-
driverFactory: SessionDriverFactory | null;
|
|
14
|
-
mockStorage: Storage | null;
|
|
15
|
-
});
|
|
18
|
+
constructor({ cookies, config, runtimeMode, driverFactory, mockStorage, logger, }: AstroSessionOptions);
|
|
16
19
|
/**
|
|
17
20
|
* Gets a session value. Returns `undefined` if the session or value does not exist.
|
|
18
21
|
*/
|
|
@@ -46,7 +46,7 @@ class AstroSession {
|
|
|
46
46
|
// When we load the data from storage, we need to merge it with the local partial data,
|
|
47
47
|
// preserving in-memory changes and deletions.
|
|
48
48
|
#partial = true;
|
|
49
|
-
|
|
49
|
+
#logger;
|
|
50
50
|
#driverFactory;
|
|
51
51
|
static #sharedStorage = /* @__PURE__ */ new Map();
|
|
52
52
|
constructor({
|
|
@@ -54,8 +54,10 @@ class AstroSession {
|
|
|
54
54
|
config,
|
|
55
55
|
runtimeMode,
|
|
56
56
|
driverFactory,
|
|
57
|
-
mockStorage
|
|
57
|
+
mockStorage,
|
|
58
|
+
logger
|
|
58
59
|
}) {
|
|
60
|
+
this.#logger = logger;
|
|
59
61
|
if (!config) {
|
|
60
62
|
throw new AstroError({
|
|
61
63
|
...SessionStorageInitError,
|
|
@@ -185,7 +187,8 @@ class AstroSession {
|
|
|
185
187
|
try {
|
|
186
188
|
data = await this.#ensureData();
|
|
187
189
|
} catch (err) {
|
|
188
|
-
|
|
190
|
+
this.#logger.error("session", `Failed to load session data during regeneration: ${err}`);
|
|
191
|
+
this.#partial = false;
|
|
189
192
|
}
|
|
190
193
|
const oldSessionId = this.#sessionID;
|
|
191
194
|
this.#sessionID = crypto.randomUUID();
|
|
@@ -195,7 +198,7 @@ class AstroSession {
|
|
|
195
198
|
await this.#setCookie();
|
|
196
199
|
if (oldSessionId && this.#storage) {
|
|
197
200
|
this.#storage.removeItem(oldSessionId).catch((err) => {
|
|
198
|
-
|
|
201
|
+
this.#logger.error("session", `Failed to remove old session ${oldSessionId}: ${err}`);
|
|
199
202
|
});
|
|
200
203
|
}
|
|
201
204
|
}
|
|
@@ -232,7 +235,7 @@ class AstroSession {
|
|
|
232
235
|
if (this.#toDestroy.size > 0) {
|
|
233
236
|
const cleanupPromises = [...this.#toDestroy].map(
|
|
234
237
|
(sessionId) => storage.removeItem(sessionId).catch((err) => {
|
|
235
|
-
|
|
238
|
+
this.#logger.error("session", `Failed to remove session ${sessionId}: ${err}`);
|
|
236
239
|
})
|
|
237
240
|
);
|
|
238
241
|
await Promise.all(cleanupPromises);
|
|
@@ -296,7 +299,7 @@ class AstroSession {
|
|
|
296
299
|
try {
|
|
297
300
|
const storedMap = unflatten(raw);
|
|
298
301
|
if (!(storedMap instanceof Map)) {
|
|
299
|
-
|
|
302
|
+
this.destroy();
|
|
300
303
|
throw new AstroError({
|
|
301
304
|
...SessionStorageInitError,
|
|
302
305
|
message: SessionStorageInitError.message(
|
|
@@ -315,7 +318,7 @@ class AstroSession {
|
|
|
315
318
|
this.#partial = false;
|
|
316
319
|
return this.#data;
|
|
317
320
|
} catch (err) {
|
|
318
|
-
|
|
321
|
+
this.destroy();
|
|
319
322
|
if (err instanceof AstroError) {
|
|
320
323
|
throw err;
|
|
321
324
|
}
|
|
@@ -20,6 +20,7 @@ import { MIDDLEWARE_MODULE_ID } from "../core/middleware/vite-plugin.js";
|
|
|
20
20
|
import { SERVER_ISLAND_MANIFEST } from "../core/server-islands/vite-plugin-server-islands.js";
|
|
21
21
|
import { VIRTUAL_CACHE_PROVIDER_ID } from "../core/cache/vite-plugin.js";
|
|
22
22
|
import { VIRTUAL_SESSION_DRIVER_ID } from "../core/session/vite-plugin.js";
|
|
23
|
+
import { VIRTUAL_LOGGER_ID } from "../core/logger/vite-plugin.js";
|
|
23
24
|
import { VIRTUAL_PAGES_MODULE_ID } from "../vite-plugin-pages/index.js";
|
|
24
25
|
import { ASTRO_RENDERERS_MODULE_ID } from "../vite-plugin-renderers/index.js";
|
|
25
26
|
import { ASTRO_ROUTES_MODULE_ID } from "../vite-plugin-routes/index.js";
|
|
@@ -86,6 +87,7 @@ function serializedManifestPlugin({
|
|
|
86
87
|
}
|
|
87
88
|
const hasCacheConfig = !!settings.config.cache?.provider;
|
|
88
89
|
const cacheProviderLine = hasCacheConfig ? `cacheProvider: () => import('${VIRTUAL_CACHE_PROVIDER_ID}'),` : "";
|
|
90
|
+
const loggerLine = settings.config.logger ? `logger: () => import('${VIRTUAL_LOGGER_ID}'),` : "";
|
|
89
91
|
const code = `
|
|
90
92
|
import { deserializeManifest as _deserializeManifest } from 'astro/app';
|
|
91
93
|
import { renderers } from '${ASTRO_RENDERERS_MODULE_ID}';
|
|
@@ -106,6 +108,7 @@ function serializedManifestPlugin({
|
|
|
106
108
|
middleware: () => import('${MIDDLEWARE_MODULE_ID}'),
|
|
107
109
|
sessionDriver: () => import('${VIRTUAL_SESSION_DRIVER_ID}'),
|
|
108
110
|
${cacheProviderLine}
|
|
111
|
+
${loggerLine}
|
|
109
112
|
serverIslandMappings: () => import('${SERVER_ISLAND_MANIFEST}'),
|
|
110
113
|
routes: manifestRoutes,
|
|
111
114
|
pageMap,
|
|
@@ -157,10 +160,6 @@ async function createSerializedManifest(settings, encodedKey) {
|
|
|
157
160
|
styleDirective
|
|
158
161
|
};
|
|
159
162
|
}
|
|
160
|
-
let loggerConfig = void 0;
|
|
161
|
-
if (settings.config.logger) {
|
|
162
|
-
loggerConfig = settings.config.logger;
|
|
163
|
-
}
|
|
164
163
|
return {
|
|
165
164
|
rootDir: settings.config.root.toString(),
|
|
166
165
|
srcDir: settings.config.srcDir.toString(),
|
|
@@ -210,8 +209,7 @@ async function createSerializedManifest(settings, encodedKey) {
|
|
|
210
209
|
placement: settings.config.devToolbar.placement
|
|
211
210
|
},
|
|
212
211
|
logLevel: settings.logLevel,
|
|
213
|
-
shouldInjectCspMetaTags: false
|
|
214
|
-
loggerConfig
|
|
212
|
+
shouldInjectCspMetaTags: false
|
|
215
213
|
};
|
|
216
214
|
}
|
|
217
215
|
export {
|
|
@@ -1516,8 +1516,7 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
1516
1516
|
*
|
|
1517
1517
|
* By default, Astro uses a built-in logger that outputs human-friendly logs to the console. You can customize this behavior by providing [your own logger handler](https://docs.astro.build/en/reference/logger-reference/#custom-loggers) or by using one of the [built-in log handlers](https://docs.astro.build/en/reference/logger-reference/#built-in-loggers):
|
|
1518
1518
|
*
|
|
1519
|
-
* ```js
|
|
1520
|
-
* // astro.config.mjs
|
|
1519
|
+
* ```js title="astro.config.mjs"
|
|
1521
1520
|
* import { defineConfig, logHandlers } from 'astro/config';
|
|
1522
1521
|
*
|
|
1523
1522
|
* export default defineConfig({
|
|
@@ -1535,7 +1534,8 @@ export interface AstroUserConfig<TLocales extends Locales = never, TDriver exten
|
|
|
1535
1534
|
* @version 7.0.0
|
|
1536
1535
|
* @description
|
|
1537
1536
|
*
|
|
1538
|
-
* The entrypoint
|
|
1537
|
+
* The entrypoint for the [logger implementation](https://docs.astro.build/en/reference/logger-reference/#the-logger-implementation).
|
|
1538
|
+
* This can be an npm package, or a `URL` pointing to a file in your project:
|
|
1539
1539
|
*
|
|
1540
1540
|
* ```js title="astro.config.mjs"
|
|
1541
1541
|
* import { defineConfig } from 'astro/config';
|