import type { Buffer } from 'buffer' import { resolve } from 'path' import { Transform } from 'stream' import { OnPreBuild } from '@netlify/build' import execa from 'execa' import { unlink } from 'fs-extra' import mergeStream from 'merge-stream' import { writeDevEdgeFunction } from './edge' import { patchNextFiles } from './files' // The types haven't been updated yet export const onPreDev: OnPreBuild = async ({ constants, netlifyConfig }) => { const base = netlifyConfig.build.base ?? process.cwd() // Need to patch the files, because build might not have been run await patchNextFiles(base) // Clean up old functions await unlink(resolve('.netlify', 'middleware.js')).catch(() => { // Ignore if it doesn't exist }) await writeDevEdgeFunction(constants) // Eventually we might want to do this via esbuild's API, but for now the CLI works fine const common = [`--bundle`, `--outdir=${resolve('.netlify')}`, `--format=esm`, `--target=esnext`, '--watch'] const opts = { all: true, env: { ...process.env, FORCE_COLOR: '1' }, } // TypeScript const tsout = execa(`esbuild`, [...common, resolve(base, 'middleware.ts')], opts).all // JavaScript const jsout = execa(`esbuild`, [...common, resolve(base, 'middleware.js')], opts).all const filter = new Transform({ transform(chunk: Buffer, encoding, callback) { const str = chunk.toString(encoding) // Skip if message includes this, because we run even when the files are missing if (!str.includes('[ERROR] Could not resolve')) { this.push(chunk) } callback() }, }) mergeStream(tsout, jsout).pipe(filter).pipe(process.stdout) // Don't return the promise because we don't want to wait for the child process to finish }