(opts = {})
| 339 | } |
| 340 | |
| 341 | export function startServer(opts = {}) { |
| 342 | const host = opts.host || defaultHost |
| 343 | const port = opts.port || defaultPort |
| 344 | const absWorkingDir = opts.absWorkingDir || '.' |
| 345 | |
| 346 | console.log(`🍱 Starting server at http://${host}:${port}`) |
| 347 | |
| 348 | let resolve = null |
| 349 | let ifPaused = null |
| 350 | function pauseServer() { |
| 351 | if (!ifPaused) { |
| 352 | ifPaused = new Promise((r) => (resolve = r)) |
| 353 | } |
| 354 | } |
| 355 | function resumeServer() { |
| 356 | resolve?.() |
| 357 | ifPaused = null |
| 358 | } |
| 359 | resumeServer() |
| 360 | |
| 361 | const app = express() |
| 362 | app.on('error', function (e) { |
| 363 | if (e.code === 'EADDRINUSE') { |
| 364 | console.error(`🛑 http://${host}:${port} is already in use. Trying another port.`) |
| 365 | } else { |
| 366 | console.error(`🛑 ${e}`) |
| 367 | } |
| 368 | process.exit(1) |
| 369 | }) |
| 370 | app.use(cors()) |
| 371 | app.get('/_reload', (request, response) => { |
| 372 | response.writeHead(200, { |
| 373 | 'Content-Type': 'text/event-stream', |
| 374 | Connection: 'keep-alive', |
| 375 | 'Cache-Control': 'no-cache', |
| 376 | }) |
| 377 | clients.add(response) |
| 378 | request.on('close', () => clients.delete(response)) |
| 379 | }) |
| 380 | app.get('*', async (req, res) => { |
| 381 | if (req.url.startsWith('/static/')) { |
| 382 | if (ifPaused) { |
| 383 | if (!ifPaused.logged) { |
| 384 | console.log('⌛️ Waiting for build to complete...') |
| 385 | ifPaused.logged = true |
| 386 | } |
| 387 | await ifPaused |
| 388 | } |
| 389 | const pathFromUrl = req.url.replace(/^\/static\//, '') |
| 390 | const filePath = path.resolve(absWorkingDir, 'dist', pathFromUrl) |
| 391 | // protect against "/../" urls |
| 392 | if (filePath.startsWith(path.resolve(absWorkingDir, 'dist'))) { |
| 393 | res.sendFile(filePath.split('?')[0]) |
| 394 | return |
| 395 | } |
| 396 | } |
| 397 | res.sendFile(path.resolve(absWorkingDir, 'dist', 'index.html')) |
| 398 | }) |
no test coverage detected
searching dependent graphs…