From 9fb9bed8062869cdc1419aac3297d6a649fa308a Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 13 Aug 2023 18:51:02 +0530 Subject: [PATCH] chore: Add live-reload --- .esbuild/server.ts | 89 ++++++++++++++++++++++++++++++++++-------- demos/dev/example.html | 28 +++++++++++++ package.json | 3 +- pnpm-lock.yaml | 3 ++ 4 files changed, 105 insertions(+), 18 deletions(-) diff --git a/.esbuild/server.ts b/.esbuild/server.ts index c93b4bbda..e25c0f714 100644 --- a/.esbuild/server.ts +++ b/.esbuild/server.ts @@ -1,29 +1,84 @@ import express from 'express'; +import type { NextFunction, Request, Response } from 'express'; import cors from 'cors'; import { getBuildConfig } from './util.js'; import { context } from 'esbuild'; +import chokidar from 'chokidar'; + +const mermaidCtx = await context( + getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }) +); +const mermaidIIFECtx = await context( + getBuildConfig({ minify: false, core: false, entryName: 'mermaid', format: 'iife' }) +); +const externalCtx = await context( + getBuildConfig({ minify: false, core: false, entryName: 'mermaid-example-diagram' }) +); +const zenumlCtx = await context( + getBuildConfig({ minify: false, core: false, entryName: 'mermaid-zenuml' }) +); +const contexts = [mermaidCtx, mermaidIIFECtx, externalCtx, zenumlCtx]; + +const rebuildAll = async () => { + await Promise.all(contexts.map((ctx) => ctx.rebuild())); +}; + +let clients: { id: number; response: Response }[] = []; +function eventsHandler(request: Request, response: Response, next: NextFunction) { + const headers = { + 'Content-Type': 'text/event-stream', + Connection: 'keep-alive', + 'Cache-Control': 'no-cache', + }; + response.writeHead(200, headers); + const clientId = Date.now(); + clients.push({ + id: clientId, + response, + }); + request.on('close', () => { + clients = clients.filter((client) => client.id !== clientId); + }); +} + +let timeoutId: NodeJS.Timeout | undefined = undefined; + +/** + * Debounce file change events to avoid rebuilding multiple times. + */ +function handleFileChange() { + if (timeoutId !== undefined) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(async () => { + await rebuildAll(); + sendEventsToAll(); + timeoutId = undefined; + }, 100); +} + +function sendEventsToAll() { + clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`)); +} async function createServer() { const app = express(); - const mermaidCtx = await context( - getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }) - ); - const mermaidIIFECtx = await context( - getBuildConfig({ minify: false, core: false, entryName: 'mermaid', format: 'iife' }) - ); - const externalCtx = await context( - getBuildConfig({ minify: false, core: false, entryName: 'mermaid-example-diagram' }) - ); - const zenuml = await context( - getBuildConfig({ minify: false, core: false, entryName: 'mermaid-zenuml' }) - ); - - mermaidCtx.watch(); - mermaidIIFECtx.watch(); - externalCtx.watch(); - zenuml.watch(); + chokidar + .watch('**/src/**/*.{js,ts,yaml,json}', { + ignoreInitial: true, + ignored: [/node_modules/, /dist/, /docs/, /coverage/], + }) + .on('all', async (event, path) => { + // Ignore other events. + if (!['add', 'change'].includes(event)) { + return; + } + console.log(`${path} changed. Rebuilding...`); + handleFileChange(); + }); app.use(cors()); + app.get('/events', eventsHandler); app.use(express.static('./packages/mermaid/dist')); app.use(express.static('./packages/mermaid-zenuml/dist')); app.use(express.static('./packages/mermaid-example-diagram/dist')); diff --git a/demos/dev/example.html b/demos/dev/example.html index 482343014..c13bd03ca 100644 --- a/demos/dev/example.html +++ b/demos/dev/example.html @@ -30,5 +30,33 @@ graph TB console.log(svg); el.innerHTML = svg; + + diff --git a/package.json b/package.json index bd45762f5..2e0391d5a 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "git graph" ], "scripts": { - "build": "pnpm build:esbuild && pnpm build:types", + "build": "pnpm run -r clean && pnpm build:esbuild && pnpm build:types", "build:esbuild": "pnpm run -r clean && ts-node-esm --transpileOnly .esbuild/build.ts", "build:mermaid": "pnpm build:esbuild --mermaid", "build:viz": "pnpm build:esbuild --visualize", @@ -82,6 +82,7 @@ "@vitest/spy": "^0.33.0", "@vitest/ui": "^0.33.0", "ajv": "^8.12.0", + "chokidar": "^3.5.3", "concurrently": "^8.0.1", "cors": "^2.8.5", "cypress": "^12.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0f524dcd..d6e90660b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,6 +74,9 @@ importers: ajv: specifier: ^8.12.0 version: 8.12.0 + chokidar: + specifier: ^3.5.3 + version: 3.5.3 concurrently: specifier: ^8.0.1 version: 8.0.1