2023-03-15 06:42:14 +03:00
|
|
|
/** @file File watch and compile service. */
|
2023-05-11 18:11:03 +03:00
|
|
|
import * as path from 'node:path'
|
|
|
|
import * as url from 'node:url'
|
|
|
|
|
2023-03-15 06:42:14 +03:00
|
|
|
import * as esbuild from 'esbuild'
|
2023-03-31 17:19:07 +03:00
|
|
|
import * as portfinder from 'portfinder'
|
2023-04-11 09:04:27 +03:00
|
|
|
import chalk from 'chalk'
|
2023-03-15 06:42:14 +03:00
|
|
|
|
2023-03-31 17:19:07 +03:00
|
|
|
import * as bundler from './esbuild-config'
|
|
|
|
import * as dashboardBundler from '../dashboard/esbuild-config'
|
2023-03-15 06:42:14 +03:00
|
|
|
|
2023-03-31 17:19:07 +03:00
|
|
|
// =================
|
|
|
|
// === Constants ===
|
|
|
|
// =================
|
2022-08-10 04:41:44 +03:00
|
|
|
|
2023-05-11 18:11:03 +03:00
|
|
|
/** The path of this file. */
|
|
|
|
const THIS_PATH = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)))
|
2023-03-31 17:19:07 +03:00
|
|
|
const PORT = 8080
|
|
|
|
const HTTP_STATUS_OK = 200
|
|
|
|
|
|
|
|
// ===============
|
|
|
|
// === Watcher ===
|
|
|
|
// ===============
|
|
|
|
|
2023-05-19 22:55:29 +03:00
|
|
|
/** Starts the esbuild watcher. */
|
2023-03-31 17:19:07 +03:00
|
|
|
async function watch() {
|
|
|
|
const dashboardOpts = dashboardBundler.bundleOptions()
|
|
|
|
const dashboardBuilder = await esbuild.context(dashboardOpts)
|
|
|
|
// We do not need to serve the dashboard as it outputs to the same directory.
|
|
|
|
// It will not rebuild on request, but it is not intended to rebuild on request anyway.
|
|
|
|
// This MUST be called before `builder.watch()` as `tailwind.css` must be generated
|
|
|
|
// before the copy plugin runs.
|
|
|
|
await dashboardBuilder.watch()
|
2023-05-26 13:17:03 +03:00
|
|
|
const opts = bundler.bundlerOptions(
|
|
|
|
bundler.argumentsFromEnv({
|
|
|
|
devMode: true,
|
|
|
|
supportsLocalBackend: true,
|
|
|
|
supportsDeepLinks: false,
|
|
|
|
})
|
|
|
|
)
|
2023-06-19 02:02:08 +03:00
|
|
|
opts.pure.splice(opts.pure.indexOf('assert'), 1)
|
|
|
|
;(opts.inject = opts.inject ?? []).push(path.resolve(THIS_PATH, '..', '..', 'debugGlobals.ts'))
|
2023-10-11 13:24:33 +03:00
|
|
|
opts.define['process.env.REDIRECT_OVERRIDE'] = JSON.stringify('http://localhost:8080')
|
2023-06-02 12:05:37 +03:00
|
|
|
// This is safe as this entry point is statically known.
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
|
|
const serviceWorkerEntryPoint = opts.entryPoints.find(
|
|
|
|
entryPoint => entryPoint.out === 'serviceWorker'
|
|
|
|
)!
|
|
|
|
serviceWorkerEntryPoint.in = path.resolve(THIS_PATH, 'src', 'devServiceWorker.ts')
|
2023-03-31 17:19:07 +03:00
|
|
|
const builder = await esbuild.context(opts)
|
|
|
|
await builder.watch()
|
|
|
|
await builder.serve({
|
|
|
|
port: await portfinder.getPortPromise({ port: PORT }),
|
|
|
|
servedir: opts.outdir,
|
2023-05-19 22:55:29 +03:00
|
|
|
/** This function is called on every request.
|
|
|
|
* It is used here to show an error if the file to serve was not found. */
|
2023-03-31 17:19:07 +03:00
|
|
|
onRequest(args) {
|
|
|
|
if (args.status !== HTTP_STATUS_OK) {
|
2023-04-11 09:04:27 +03:00
|
|
|
console.error(
|
|
|
|
chalk.red(`HTTP error ${args.status} when serving path '${args.path}'.`)
|
|
|
|
)
|
2023-03-31 17:19:07 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
void watch()
|