|
| 1 | +import { isAbsolute } from 'node:path'; |
| 2 | +import { pathToFileURL } from 'node:url'; |
1 | 3 | import { AstroLogger, type AstroLoggerDestination } from './core.js'; |
2 | 4 | import { AstroError } from '../errors/index.js'; |
3 | 5 | import { UnableToLoadLogger } from '../errors/errors-data.js'; |
4 | 6 | import type { LoggerHandlerConfig } from './config.js'; |
5 | 7 | import type { AstroConfig, AstroInlineConfig } from '../../types/public/index.js'; |
6 | | -import { default as nodeLoggerCreator, createNodeLoggerFromFlags } from './impls/node.js'; |
7 | | -import { default as consoleLoggerCreator } from './impls/console.js'; |
8 | | -import { default as jsonLoggerCreator } from './impls/json.js'; |
9 | | -import { default as composeLoggerCreator } from './impls/compose.js'; |
| 8 | +import { createNodeLoggerFromFlags } from './impls/node.js'; |
| 9 | +import { |
| 10 | + COMPOSE_LOGGER_ENTRYPOINT, |
| 11 | + normalizeLoggerConfig, |
| 12 | + type NormalizedLoggerConfig, |
| 13 | +} from './utils.js'; |
10 | 14 |
|
11 | | -function normalizeEntrypoint(entrypoint: LoggerHandlerConfig['entrypoint']): string { |
12 | | - return entrypoint instanceof URL ? entrypoint.href : entrypoint; |
| 15 | +/** |
| 16 | + * Instantiates a logger destination in a Node context. |
| 17 | + * |
| 18 | + * This is the runtime counterpart of `emitDestination()` in `./vite-plugin.ts`: both walk |
| 19 | + * the same normalized config, but this one imports and instantiates the handler directly, |
| 20 | + * while the Vite one *generates code* doing so, to bundle the handler into the build output. |
| 21 | + */ |
| 22 | +async function createDestination(config: NormalizedLoggerConfig): Promise<AstroLoggerDestination> { |
| 23 | + // `normalizeLoggerConfig()` turns `URL` entrypoints into absolute paths, which |
| 24 | + // `import()` only accepts as file URLs on Windows. Package entrypoints keep their |
| 25 | + // specifier and resolve through the regular module resolution. |
| 26 | + const specifier = isAbsolute(config.entrypoint) |
| 27 | + ? pathToFileURL(config.entrypoint).href |
| 28 | + : config.entrypoint; |
| 29 | + const logger = await import(/* @vite-ignore */ specifier); |
| 30 | + |
| 31 | + // `astro/logger/compose` takes the composed destinations rather than a serializable config. |
| 32 | + if (config.entrypoint === COMPOSE_LOGGER_ENTRYPOINT) { |
| 33 | + return logger.default(await Promise.all((config.loggers ?? []).map(createDestination))); |
| 34 | + } |
| 35 | + |
| 36 | + return logger.default(config.config); |
13 | 37 | } |
14 | 38 |
|
| 39 | +/** |
| 40 | + * Loads a logger destination in a Node context, i.e. outside of a built server bundle. |
| 41 | + * Inside the bundle, the destination comes from the `virtual:astro:logger` module instead. |
| 42 | + */ |
15 | 43 | export async function loadLoggerDestination( |
16 | 44 | config: LoggerHandlerConfig, |
17 | 45 | ): Promise<AstroLoggerDestination> { |
18 | | - let cause: Error | undefined = undefined; |
19 | | - const entrypoint = normalizeEntrypoint(config.entrypoint); |
| 46 | + const normalized = normalizeLoggerConfig(config); |
20 | 47 |
|
21 | 48 | try { |
22 | | - switch (config.entrypoint) { |
23 | | - case 'astro/logger/node': { |
24 | | - return nodeLoggerCreator(config.config); |
25 | | - } |
26 | | - case 'astro/logger/console': { |
27 | | - return consoleLoggerCreator(config.config); |
28 | | - } |
29 | | - case 'astro/logger/json': { |
30 | | - return jsonLoggerCreator(config.config); |
31 | | - } |
32 | | - case 'astro/logger/compose': { |
33 | | - let destinations: AstroLoggerDestination[] = []; |
34 | | - if (config.config?.loggers) { |
35 | | - const loggers: LoggerHandlerConfig[] = config.config?.loggers; |
36 | | - destinations = await Promise.all( |
37 | | - loggers.map(async (loggerConfig) => { |
38 | | - const logger = await import( |
39 | | - /* @vite-ignore */ normalizeEntrypoint(loggerConfig.entrypoint) |
40 | | - ); |
41 | | - return logger.default(loggerConfig.config) as AstroLoggerDestination; |
42 | | - }), |
43 | | - ); |
44 | | - } |
45 | | - |
46 | | - return composeLoggerCreator(destinations); |
47 | | - } |
48 | | - default: { |
49 | | - const logger = await import(/* @vite-ignore */ entrypoint); |
50 | | - return logger.default(config.config); |
51 | | - } |
52 | | - } |
| 49 | + return await createDestination(normalized); |
53 | 50 | } catch (e: unknown) { |
| 51 | + const error = new AstroError({ |
| 52 | + ...UnableToLoadLogger, |
| 53 | + message: UnableToLoadLogger.message(normalized.entrypoint), |
| 54 | + }); |
54 | 55 | if (e instanceof Error) { |
55 | | - cause = e; |
| 56 | + error.cause = e; |
56 | 57 | } |
| 58 | + throw error; |
57 | 59 | } |
58 | | - |
59 | | - const error = new AstroError({ |
60 | | - ...UnableToLoadLogger, |
61 | | - message: UnableToLoadLogger.message(entrypoint), |
62 | | - }); |
63 | | - if (cause) { |
64 | | - error.cause = cause; |
65 | | - } |
66 | | - throw error; |
67 | 60 | } |
68 | 61 |
|
69 | 62 | /** |
|
0 commit comments