feat: pass logger to integrations

This commit is contained in:
Emanuele Stoppa 2023-07-25 12:52:54 +01:00
parent 25e04a2ecb
commit 9658f6cd17
3 changed files with 172 additions and 81 deletions

View file

@ -22,6 +22,7 @@ import type { AstroCookies } from '../core/cookies';
import type { LogOptions } from '../core/logger/core'; import type { LogOptions } from '../core/logger/core';
import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server'; import type { AstroComponentFactory, AstroComponentInstance } from '../runtime/server';
import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js'; import type { SUPPORTED_MARKDOWN_FILE_EXTENSIONS } from './../core/constants.js';
import { Logger } from '../core/logger/core';
export type { export type {
MarkdownHeading, MarkdownHeading,
MarkdownMetadata, MarkdownMetadata,
@ -1856,56 +1857,87 @@ export interface AstroIntegration {
name: string; name: string;
/** The different hooks available to extend. */ /** The different hooks available to extend. */
hooks: { hooks: {
'astro:config:setup'?: (options: { 'astro:config:setup'?: (
config: AstroConfig; options: {
command: 'dev' | 'build' | 'preview'; config: AstroConfig;
isRestart: boolean; command: 'dev' | 'build' | 'preview';
updateConfig: (newConfig: Record<string, any>) => void; isRestart: boolean;
addRenderer: (renderer: AstroRenderer) => void; updateConfig: (newConfig: Record<string, any>) => void;
addWatchFile: (path: URL | string) => void; addRenderer: (renderer: AstroRenderer) => void;
injectScript: (stage: InjectedScriptStage, content: string) => void; addWatchFile: (path: URL | string) => void;
injectRoute: (injectRoute: InjectedRoute) => void; injectScript: (stage: InjectedScriptStage, content: string) => void;
addClientDirective: (directive: ClientDirectiveConfig) => void; injectRoute: (injectRoute: InjectedRoute) => void;
// TODO: Add support for `injectElement()` for full HTML element injection, not just scripts. addClientDirective: (directive: ClientDirectiveConfig) => void;
// This may require some refactoring of `scripts`, `styles`, and `links` into something // TODO: Add support for `injectElement()` for full HTML element injection, not just scripts.
// more generalized. Consider the SSR use-case as well. // This may require some refactoring of `scripts`, `styles`, and `links` into something
// injectElement: (stage: vite.HtmlTagDescriptor, element: string) => void; // more generalized. Consider the SSR use-case as well.
}) => void | Promise<void>; // injectElement: (stage: vite.HtmlTagDescriptor, element: string) => void;
'astro:config:done'?: (options: { },
config: AstroConfig; bag: AstroIntegrationBag
setAdapter: (adapter: AstroAdapter) => void; ) => void | Promise<void>;
}) => void | Promise<void>; 'astro:config:done'?: (
'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise<void>; options: {
'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise<void>; config: AstroConfig;
'astro:server:done'?: () => void | Promise<void>; setAdapter: (adapter: AstroAdapter) => void;
'astro:build:ssr'?: (options: { },
manifest: SerializedSSRManifest; bag: AstroIntegrationBag
/** ) => void | Promise<void>;
* This maps a {@link RouteData} to an {@link URL}, this URL represents 'astro:server:setup'?: (
* the physical file you should import. options: { server: vite.ViteDevServer },
*/ bag: AstroIntegrationBag
entryPoints: Map<RouteData, URL>; ) => void | Promise<void>;
/** 'astro:server:start'?: (
* File path of the emitted middleware options: { address: AddressInfo },
*/ bag: AstroIntegrationBag
middlewareEntryPoint: URL | undefined; ) => void | Promise<void>;
}) => void | Promise<void>; 'astro:server:done'?: (bag: AstroIntegrationBag) => void | Promise<void>;
'astro:build:start'?: () => void | Promise<void>; 'astro:build:ssr'?: (
'astro:build:setup'?: (options: { options: {
vite: vite.InlineConfig; manifest: SerializedSSRManifest;
pages: Map<string, PageBuildData>; /**
target: 'client' | 'server'; * This maps a {@link RouteData} to an {@link URL}, this URL represents
updateConfig: (newConfig: vite.InlineConfig) => void; * the physical file you should import.
}) => void | Promise<void>; */
'astro:build:generated'?: (options: { dir: URL }) => void | Promise<void>; entryPoints: Map<RouteData, URL>;
'astro:build:done'?: (options: { /**
pages: { pathname: string }[]; * File path of the emitted middleware
dir: URL; */
routes: RouteData[]; middlewareEntryPoint: URL | undefined;
}) => void | Promise<void>; },
bag: AstroIntegrationBag
) => void | Promise<void>;
'astro:build:start'?: (bag: AstroIntegrationBag) => void | Promise<void>;
'astro:build:setup'?: (
options: {
vite: vite.InlineConfig;
pages: Map<string, PageBuildData>;
target: 'client' | 'server';
updateConfig: (newConfig: vite.InlineConfig) => void;
},
bag: AstroIntegrationBag
) => void | Promise<void>;
'astro:build:generated'?: (
options: { dir: URL },
bag: AstroIntegrationBag
) => void | Promise<void>;
'astro:build:done'?: (
options: {
pages: { pathname: string }[];
dir: URL;
routes: RouteData[];
},
bag: AstroIntegrationBag
) => void | Promise<void>;
}; };
} }
/**
* A set of utilities that are passed at each hook
*/
export type AstroIntegrationBag = {
logger: Logger;
};
export type MiddlewareNext<R> = () => Promise<R>; export type MiddlewareNext<R> = () => Promise<R>;
export type MiddlewareHandler<R> = ( export type MiddlewareHandler<R> = (
context: APIContext, context: APIContext,

View file

@ -127,3 +127,32 @@ export function timerMessage(message: string, startTime: number = Date.now()) {
timeDiff < 750 ? `${Math.round(timeDiff)}ms` : `${(timeDiff / 1000).toFixed(1)}s`; timeDiff < 750 ? `${Math.round(timeDiff)}ms` : `${(timeDiff / 1000).toFixed(1)}s`;
return `${message} ${dim(timeDisplay)}`; return `${message} ${dim(timeDisplay)}`;
} }
export class Logger {
type: string;
options: LogOptions;
constructor(type: string, options: LogOptions) {
this.type = type;
this.options = options;
}
/**
* Creates a new Logger instance using the same log options
*/
fork(type: string): Logger {
return new Logger(type, this.options);
}
info(message: string) {
info(this.options, this.type, message);
}
warn(message: string) {
warn(this.options, this.type, message);
}
error(message: string) {
error(this.options, this.type, message);
}
debug(message: string) {
debug(this.options, this.type, message);
}
}

View file

@ -16,7 +16,7 @@ import type { SerializedSSRManifest } from '../core/app/types';
import type { PageBuildData } from '../core/build/types'; import type { PageBuildData } from '../core/build/types';
import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js'; import { buildClientDirectiveEntrypoint } from '../core/client-directive/index.js';
import { mergeConfig } from '../core/config/index.js'; import { mergeConfig } from '../core/config/index.js';
import { info, type LogOptions } from '../core/logger/core.js'; import { info, type LogOptions, Logger } from '../core/logger/core.js';
import { isServerLikeOutput } from '../prerender/utils.js'; import { isServerLikeOutput } from '../prerender/utils.js';
async function withTakingALongTimeMsg<T>({ async function withTakingALongTimeMsg<T>({
@ -72,6 +72,8 @@ export async function runHookConfigSetup({
* ``` * ```
*/ */
if (integration.hooks?.['astro:config:setup']) { if (integration.hooks?.['astro:config:setup']) {
const logger = new Logger(`${integration.name}`, logging);
const hooks: HookParameters<'astro:config:setup'> = { const hooks: HookParameters<'astro:config:setup'> = {
config: updatedConfig, config: updatedConfig,
command, command,
@ -144,7 +146,7 @@ export async function runHookConfigSetup({
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:config:setup'](hooks), hookResult: integration.hooks['astro:config:setup'](hooks, { logger }),
logging, logging,
}); });
@ -167,20 +169,24 @@ export async function runHookConfigDone({
logging: LogOptions; logging: LogOptions;
}) { }) {
for (const integration of settings.config.integrations) { for (const integration of settings.config.integrations) {
const logger = new Logger(`${integration.name}`, logging);
if (integration?.hooks?.['astro:config:done']) { if (integration?.hooks?.['astro:config:done']) {
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:config:done']({ hookResult: integration.hooks['astro:config:done'](
config: settings.config, {
setAdapter(adapter) { config: settings.config,
if (settings.adapter && settings.adapter.name !== adapter.name) { setAdapter(adapter) {
throw new Error( if (settings.adapter && settings.adapter.name !== adapter.name) {
`Integration "${integration.name}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.` throw new Error(
); `Integration "${integration.name}" conflicts with "${settings.adapter.name}". You can only configure one deployment integration.`
} );
settings.adapter = adapter; }
settings.adapter = adapter;
},
}, },
}), { logger }
),
logging, logging,
}); });
} }
@ -198,9 +204,10 @@ export async function runHookServerSetup({
}) { }) {
for (const integration of config.integrations) { for (const integration of config.integrations) {
if (integration?.hooks?.['astro:server:setup']) { if (integration?.hooks?.['astro:server:setup']) {
const logger = new Logger(`${integration.name}`, logging);
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:server:setup']({ server }), hookResult: integration.hooks['astro:server:setup']({ server }, { logger }),
logging, logging,
}); });
} }
@ -217,10 +224,12 @@ export async function runHookServerStart({
logging: LogOptions; logging: LogOptions;
}) { }) {
for (const integration of config.integrations) { for (const integration of config.integrations) {
const logger = new Logger(`${integration.name}`, logging);
if (integration?.hooks?.['astro:server:start']) { if (integration?.hooks?.['astro:server:start']) {
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:server:start']({ address }), hookResult: integration.hooks['astro:server:start']({ address }, { logger }),
logging, logging,
}); });
} }
@ -235,10 +244,12 @@ export async function runHookServerDone({
logging: LogOptions; logging: LogOptions;
}) { }) {
for (const integration of config.integrations) { for (const integration of config.integrations) {
const logger = new Logger(`${integration.name}`, logging);
if (integration?.hooks?.['astro:server:done']) { if (integration?.hooks?.['astro:server:done']) {
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:server:done'](), hookResult: integration.hooks['astro:server:done']({ logger }),
logging, logging,
}); });
} }
@ -254,9 +265,11 @@ export async function runHookBuildStart({
}) { }) {
for (const integration of config.integrations) { for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:start']) { if (integration?.hooks?.['astro:build:start']) {
const logger = new Logger(`${integration.name}`, logging);
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:build:start'](), hookResult: integration.hooks['astro:build:start']({ logger }),
logging, logging,
}); });
} }
@ -280,16 +293,21 @@ export async function runHookBuildSetup({
for (const integration of config.integrations) { for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:setup']) { if (integration?.hooks?.['astro:build:setup']) {
const logger = new Logger(`${integration.name}`, logging);
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:build:setup']({ hookResult: integration.hooks['astro:build:setup'](
vite, {
pages, vite,
target, pages,
updateConfig: (newConfig) => { target,
updatedConfig = mergeConfig(updatedConfig, newConfig); updateConfig: (newConfig) => {
updatedConfig = mergeConfig(updatedConfig, newConfig);
},
}, },
}), { logger }
),
logging, logging,
}); });
} }
@ -315,13 +333,18 @@ export async function runHookBuildSsr({
}: RunHookBuildSsr) { }: RunHookBuildSsr) {
for (const integration of config.integrations) { for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:ssr']) { if (integration?.hooks?.['astro:build:ssr']) {
const logger = new Logger(`${integration.name}`, logging);
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:build:ssr']({ hookResult: integration.hooks['astro:build:ssr'](
manifest, {
entryPoints, manifest,
middlewareEntryPoint, entryPoints,
}), middlewareEntryPoint,
},
{ logger }
),
logging, logging,
}); });
} }
@ -338,10 +361,12 @@ export async function runHookBuildGenerated({
const dir = isServerLikeOutput(config) ? config.build.client : config.outDir; const dir = isServerLikeOutput(config) ? config.build.client : config.outDir;
for (const integration of config.integrations) { for (const integration of config.integrations) {
const logger = new Logger(`${integration.name}`, logging);
if (integration?.hooks?.['astro:build:generated']) { if (integration?.hooks?.['astro:build:generated']) {
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:build:generated']({ dir }), hookResult: integration.hooks['astro:build:generated']({ dir }, { logger }),
logging, logging,
}); });
} }
@ -361,13 +386,18 @@ export async function runHookBuildDone({ config, pages, routes, logging }: RunHo
for (const integration of config.integrations) { for (const integration of config.integrations) {
if (integration?.hooks?.['astro:build:done']) { if (integration?.hooks?.['astro:build:done']) {
const logger = new Logger(`${integration.name}`, logging);
await withTakingALongTimeMsg({ await withTakingALongTimeMsg({
name: integration.name, name: integration.name,
hookResult: integration.hooks['astro:build:done']({ hookResult: integration.hooks['astro:build:done'](
pages: pages.map((p) => ({ pathname: p })), {
dir, pages: pages.map((p) => ({ pathname: p })),
routes, dir,
}), routes,
},
{ logger }
),
logging, logging,
}); });
} }