astro
Version:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
56 lines (55 loc) • 2.18 kB
JavaScript
import { createAsyncManifestMemo } from "../manifest/memo.js";
import { createConsoleLogger } from "./impls/console.js";
const loggers = new WeakMap();
/**
* One identity-stable logger per manifest. Created on first access as a
* console logger at `manifest.logLevel`.
*
* The instance is never replaced: `getResolvedLogger` swaps the
* destination in place via `AstroLogger.setDestination`, so every holder
* (state-captured logger, adapterLogger's retained options) writes to the
* new destination immediately.
*/
export function getLogger(manifest) {
let logger = loggers.get(manifest);
if (!logger) {
logger = createConsoleLogger({ level: manifest.logLevel });
loggers.set(manifest, logger);
}
return logger;
}
/**
* Composition-time injection (dev server logger, DevApp console logger, an
* App facade constructed with a custom logger path, tests). Must be called
* before the first `getLogger()` read to take effect deterministically;
* replaces the stored instance either way.
*/
export function setLogger(manifest, logger) {
loggers.set(manifest, logger);
}
const resolvedLogger = createAsyncManifestMemo(async (manifest) => {
const logger = getLogger(manifest);
try {
const destination = (await manifest.logger?.())?.default;
if (destination) {
logger.setDestination(destination);
}
} catch (error) {
logger.error("config", "Failed to load the configured logger destination; continuing with the console logger.\n" + (error instanceof Error ? error.stack ?? error.message : String(error)));
}
return logger;
});
/**
* The manifest's logger with the user-configured destination (the
* `manifest.logger` thunk) resolved and applied via `setDestination` on the
* identity-stable logger. Memoized single-flight; awaited at request entry.
*
* Never rejects: a destination that fails to load is reported through the
* unswapped (console) logger, which stays in place — a broken custom
* destination cannot fail a request. Because the derivation always resolves,
* the memo's delete-on-rejection retry path never triggers: the thunk runs
* at most once per manifest.
*/
export function getResolvedLogger(manifest) {
return resolvedLogger.get(manifest);
}