|
1 |
| -import { promises } from 'fs' |
2 |
| -import { join } from 'path' |
| 1 | +import { resolve } from 'path' |
3 | 2 |
|
4 |
| -import { build } from '@netlify/esbuild' |
5 |
| -import { FSWatcher, watch } from 'chokidar' |
| 3 | +import { startWatching } from './compiler' |
6 | 4 |
|
7 |
| -const toFileList = (watched: Record<string, Array<string>>) => |
8 |
| - Object.entries(watched).flatMap(([dir, files]) => files.map((file) => join(dir, file))) |
9 |
| - |
10 |
| -/** |
11 |
| - * Compile the middleware file using esbuild |
12 |
| - */ |
13 |
| - |
14 |
| -const buildMiddlewareFile = async (entryPoints: Array<string>, base: string) => { |
15 |
| - try { |
16 |
| - await build({ |
17 |
| - entryPoints, |
18 |
| - outfile: join(base, '.netlify', 'middleware.js'), |
19 |
| - bundle: true, |
20 |
| - format: 'esm', |
21 |
| - target: 'esnext', |
22 |
| - }) |
23 |
| - } catch (error) { |
24 |
| - console.error(error) |
25 |
| - } |
26 |
| -} |
27 |
| - |
28 |
| -/** |
29 |
| - * We only compile middleware if there's exactly one file. If there's more than one, we log a warning and don't compile. |
30 |
| - */ |
31 |
| -const shouldFilesBeCompiled = (watchedFiles: Array<string>, isFirstRun: boolean) => { |
32 |
| - if (watchedFiles.length === 0) { |
33 |
| - if (!isFirstRun) { |
34 |
| - // Only log on subsequent builds, because having it on first build makes it seem like a warning, when it's a normal state |
35 |
| - console.log('No middleware found') |
36 |
| - } |
37 |
| - return false |
38 |
| - } |
39 |
| - if (watchedFiles.length > 1) { |
40 |
| - console.log('Multiple middleware files found:') |
41 |
| - console.log(watchedFiles.join('\n')) |
42 |
| - console.log('This is not supported.') |
43 |
| - return false |
44 |
| - } |
45 |
| - return true |
46 |
| -} |
47 |
| - |
48 |
| -const updateWatchedFiles = async (watcher: FSWatcher, base: string, isFirstRun = false) => { |
49 |
| - try { |
50 |
| - // Start by deleting the old file. If we error out, we don't want to leave the old file around |
51 |
| - await promises.unlink(join(base, '.netlify', 'middleware.js')) |
52 |
| - } catch { |
53 |
| - // Ignore, because it's fine if it didn't exist |
54 |
| - } |
55 |
| - // The list of watched files is an object with the directory as the key and an array of files as the value. |
56 |
| - // We need to flatten this into a list of files |
57 |
| - const watchedFiles = toFileList(watcher.getWatched()) |
58 |
| - |
59 |
| - if (!shouldFilesBeCompiled(watchedFiles, isFirstRun)) { |
60 |
| - return |
61 |
| - } |
62 |
| - |
63 |
| - console.log(`${isFirstRun ? 'Building' : 'Rebuilding'} middleware ${watchedFiles[0]}...`) |
64 |
| - await buildMiddlewareFile(watchedFiles, base) |
65 |
| - console.log('...done') |
66 |
| -} |
67 |
| - |
68 |
| -const start = async (base: string, once = false) => { |
69 |
| - const watcher = watch(['middleware.js', 'middleware.ts', 'src/middleware.js', 'src/middleware.ts'], { |
70 |
| - // Try and ensure renames just emit one event |
71 |
| - atomic: true, |
72 |
| - // Don't emit for every watched file, just once after the scan is done |
73 |
| - ignoreInitial: true, |
74 |
| - cwd: base, |
75 |
| - }) |
76 |
| - |
77 |
| - try { |
78 |
| - watcher |
79 |
| - .on('change', (path) => { |
80 |
| - console.log(`File ${path} has been changed`) |
81 |
| - updateWatchedFiles(watcher, base) |
82 |
| - }) |
83 |
| - .on('add', (path) => { |
84 |
| - console.log(`File ${path} has been added`) |
85 |
| - updateWatchedFiles(watcher, base) |
86 |
| - }) |
87 |
| - .on('unlink', (path) => { |
88 |
| - console.log(`File ${path} has been removed`) |
89 |
| - updateWatchedFiles(watcher, base) |
90 |
| - }) |
91 |
| - .on('ready', async () => { |
92 |
| - console.log('Initial scan complete. Ready for changes') |
93 |
| - // This only happens on the first scan |
94 |
| - await updateWatchedFiles(watcher, base, true) |
95 |
| - if (once) { |
96 |
| - watcher.close() |
97 |
| - } |
98 |
| - }) |
99 |
| - |
100 |
| - await new Promise((resolve) => { |
101 |
| - watcher.on('close', resolve) |
102 |
| - }) |
103 |
| - } finally { |
104 |
| - await watcher.close() |
| 5 | +const run = async () => { |
| 6 | + const { isReady, watcher } = startWatching(resolve(process.argv[2])) |
| 7 | + await isReady |
| 8 | + if (process.argv[3] === '--once') { |
| 9 | + watcher.close() |
105 | 10 | }
|
106 | 11 | }
|
107 | 12 |
|
108 |
| -start(process.argv[2], process.argv[3] === '--once').catch((error) => { |
109 |
| - console.error(error) |
110 |
| - // eslint-disable-next-line n/no-process-exit |
111 |
| - process.exit(1) |
112 |
| -}) |
| 13 | +run() |
0 commit comments