vite-plugin-entry-shaking-debugger
Version:
Debugger for vite-plugin-entry-shaking
89 lines (76 loc) • 3.12 kB
text/typescript
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { ViteDevServer } from 'vite';
import sirv from 'sirv';
import colors from 'picocolors';
import type { Context } from 'vite-plugin-entry-shaking';
import type { ConsumerPackageInfo } from '../types';
import { PLUGIN_NAME, VERSION } from '../constants';
import { createChannel } from './channel';
import { getConsumerPackageInfo } from './paths';
const PATH_TO_CLIENT = resolve(dirname(fileURLToPath(import.meta.url)), '../dist/client');
/**
* Attaches a debugger to a Vite dev server instance.
* @param server Vite dev server instance.
* @param ctx Plugin context.
*/
export async function attachDebugger(server: ViteDevServer, ctx: Context) {
const { base } = server.config;
const debuggerPath = `${base}__debugger`;
const sirvConfig = { dev: true, single: true };
server.middlewares.use(debuggerPath, sirv(PATH_TO_CLIENT, sirvConfig));
const consumer = await getConsumerPackageInfo();
createChannel(server, ctx, consumer);
printUrls(server, debuggerPath, consumer);
}
/**
* Hijacks Vite's printUrls method to append debugger's URL.
* @param server Vite dev server instance.
* @param debuggerRoute Route to plugin's debugger client.
* @param consumer Information about the consuming package.
*/
function printUrls(server: ViteDevServer, debuggerRoute: string, consumer: ConsumerPackageInfo) {
// eslint-disable-next-line @typescript-eslint/unbound-method
const printViteUrls = server.printUrls;
server.printUrls = () => {
printViteUrls();
const resolvedLocalUrls = server.resolvedUrls?.local ?? [];
const pluginHeader = colors.green(`${colors.bold(PLUGIN_NAME)} v${VERSION}`);
const pluginName = colors.dim('debugger');
server.config.logger.info(`\n ${pluginHeader} ${pluginName}\n`);
resolvedLocalUrls.forEach((url, i) => {
const baseUrl = url.endsWith('/') && debuggerRoute.startsWith('/') ? url.slice(0, -1) : url;
const debugPath = debuggerRoute.endsWith('/') ? debuggerRoute : `${debuggerRoute}/`;
const debugUrl = `${baseUrl}${debugPath}`;
if (!i) {
openBrowser(baseUrl);
openBrowser(debugUrl, 300);
}
server.config.logger.info(
colors.dim(colors.green(' ➜')) +
colors.dim(` ${colors.bold('Local:')} ${colors.cyan(debugUrl)}`),
);
if (consumer.name && consumer.version) {
const debuggee = `${consumer.name}@${consumer.version}`;
server.config.logger.info(
colors.dim(colors.green(' ➜')) + colors.dim(` Debugging ${colors.bold(debuggee)}`),
);
}
});
};
}
/**
* Opens a browser window with the given address.
* @param address Target address to open.
* @param delay Delay before opening the browser.
*/
function openBrowser(address: string, delay = 0) {
setTimeout(() => {
import('open')
.then((r) => r.default(address, { newInstance: true }))
.catch(() => {
// Silent error, debugger should still be accessible from printed url.
});
}, delay);
}
export default attachDebugger;