2024-10-21 15:56:39 +03:00
|
|
|
/**
|
|
|
|
* @file This script is for watching the whole IDE and spawning the electron process.
|
2024-03-27 17:42:23 +03:00
|
|
|
*
|
|
|
|
* It sets up watchers for the client and content, and spawns the electron process with the IDE.
|
|
|
|
* The spawned electron process can then use its refresh capability to pull the latest changes
|
|
|
|
* from the watchers.
|
2024-10-21 15:56:39 +03:00
|
|
|
*/
|
2024-11-15 15:12:55 +03:00
|
|
|
import chalk from 'chalk'
|
|
|
|
import { spawn } from 'node:child_process'
|
|
|
|
import { mkdir, rm, symlink } from 'node:fs/promises'
|
2024-03-27 17:42:23 +03:00
|
|
|
import * as path from 'node:path'
|
|
|
|
import process from 'node:process'
|
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
import { BuildResult, context } from 'esbuild'
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
import { bundlerOptionsFromEnv } from './esbuildConfig'
|
|
|
|
import { getIdeDirectory, getProjectManagerBundlePath, PROJECT_MANAGER_BUNDLE } from './paths'
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
const IDE_DIR_PATH = getIdeDirectory()
|
|
|
|
const PROJECT_MANAGER_BUNDLE_PATH = getProjectManagerBundlePath()
|
2024-03-27 17:42:23 +03:00
|
|
|
|
|
|
|
// @ts-expect-error This is the only place where an environment variable should be written to.
|
|
|
|
process.env.ELECTRON_DEV_MODE = 'true'
|
2024-11-15 15:12:55 +03:00
|
|
|
|
|
|
|
console.log(chalk.cyan('Cleaning IDE dist directory.'))
|
|
|
|
await rm(IDE_DIR_PATH, { recursive: true, force: true })
|
|
|
|
await mkdir(IDE_DIR_PATH, { recursive: true })
|
2024-07-10 12:04:20 +03:00
|
|
|
const NODE_MODULES_PATH = path.resolve('./node_modules')
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
const BUNDLE_READY = new Promise<BuildResult>((resolve, reject) => {
|
2024-07-26 09:34:51 +03:00
|
|
|
void (async () => {
|
2024-11-15 15:12:55 +03:00
|
|
|
console.log(chalk.cyan('Bundling client.'))
|
2024-07-26 09:34:51 +03:00
|
|
|
const devMode = true
|
2024-11-15 15:12:55 +03:00
|
|
|
const clientBundlerOpts = bundlerOptionsFromEnv(devMode)
|
2024-07-26 09:34:51 +03:00
|
|
|
clientBundlerOpts.outdir = path.resolve(IDE_DIR_PATH)
|
|
|
|
;(clientBundlerOpts.plugins ??= []).push({
|
|
|
|
name: 'enso-on-rebuild',
|
|
|
|
setup: build => {
|
|
|
|
build.onEnd(result => {
|
|
|
|
if (result.errors.length) {
|
|
|
|
// We cannot carry on if the client failed to build, because electron
|
|
|
|
// would immediately exit with an error.
|
2024-11-15 15:12:55 +03:00
|
|
|
console.error(chalk.red('Client bundle update failed:'), result.errors[0])
|
2024-07-26 09:34:51 +03:00
|
|
|
reject(result.errors[0])
|
|
|
|
} else {
|
2024-11-15 15:12:55 +03:00
|
|
|
console.log(chalk.green('Client bundle updated.'))
|
|
|
|
for (const error of result.errors) {
|
|
|
|
console.error(error)
|
|
|
|
}
|
|
|
|
for (const warning of result.warnings) {
|
|
|
|
console.warn(warning)
|
|
|
|
}
|
2024-07-26 09:34:51 +03:00
|
|
|
}
|
2024-03-27 17:42:23 +03:00
|
|
|
})
|
2024-07-26 09:34:51 +03:00
|
|
|
},
|
|
|
|
})
|
2024-11-15 15:12:55 +03:00
|
|
|
const clientBuilder = await context(clientBundlerOpts)
|
2024-07-26 09:34:51 +03:00
|
|
|
const client = await clientBuilder.rebuild()
|
|
|
|
void clientBuilder.watch()
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
resolve(client)
|
2024-07-26 09:34:51 +03:00
|
|
|
})()
|
2024-03-27 17:42:23 +03:00
|
|
|
})
|
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
await BUNDLE_READY
|
2024-04-08 05:20:28 +03:00
|
|
|
console.log(
|
2024-11-15 15:12:55 +03:00
|
|
|
chalk.cyan(
|
|
|
|
`Linking Project Manager bundle at '${PROJECT_MANAGER_BUNDLE_PATH}' to '${path.join(
|
|
|
|
IDE_DIR_PATH,
|
|
|
|
PROJECT_MANAGER_BUNDLE,
|
|
|
|
)}'.`,
|
|
|
|
),
|
2024-03-27 17:42:23 +03:00
|
|
|
)
|
2024-11-15 15:12:55 +03:00
|
|
|
await symlink(PROJECT_MANAGER_BUNDLE_PATH, path.join(IDE_DIR_PATH, PROJECT_MANAGER_BUNDLE), 'dir')
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-05-06 10:43:11 +03:00
|
|
|
const ELECTRON_FLAGS =
|
2024-07-26 09:34:51 +03:00
|
|
|
process.env.ELECTRON_FLAGS == null ? [] : String(process.env.ELECTRON_FLAGS).split(' ')
|
2024-05-06 10:43:11 +03:00
|
|
|
const ELECTRON_ARGS = [
|
2024-08-08 15:12:05 +03:00
|
|
|
path.join(IDE_DIR_PATH, 'index.mjs'),
|
2024-07-26 09:34:51 +03:00
|
|
|
...ELECTRON_FLAGS,
|
|
|
|
'--',
|
2024-09-08 09:54:41 +03:00
|
|
|
...process.argv.slice(2).map(arg => `'${arg}'`),
|
2024-05-06 10:43:11 +03:00
|
|
|
]
|
2024-03-27 17:42:23 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
const exit = (code = 0) => {
|
|
|
|
void rm(IDE_DIR_PATH, { recursive: true, force: true }).then(() => {
|
2024-07-26 09:34:51 +03:00
|
|
|
// The `esbuild` process seems to remain alive at this point and will keep our process
|
|
|
|
// from ending. Thus, we exit manually. It seems to terminate the child `esbuild` process
|
|
|
|
// as well.
|
2024-11-15 15:12:55 +03:00
|
|
|
process.exit(code)
|
2024-07-26 09:34:51 +03:00
|
|
|
})
|
2024-11-15 15:12:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
process.on('SIGINT', () => {
|
|
|
|
exit()
|
2024-03-27 17:42:23 +03:00
|
|
|
})
|
|
|
|
|
2024-10-21 15:56:39 +03:00
|
|
|
/** Starts the electron process with the IDE. */
|
2024-05-22 16:56:42 +03:00
|
|
|
function startElectronProcess() {
|
2024-11-15 15:12:55 +03:00
|
|
|
console.log(chalk.cyan('Spawning Electron process.'))
|
2024-07-26 09:34:51 +03:00
|
|
|
|
2024-11-15 15:12:55 +03:00
|
|
|
const electronProcess = spawn('electron', ELECTRON_ARGS, {
|
2024-07-26 09:34:51 +03:00
|
|
|
stdio: 'inherit',
|
|
|
|
shell: true,
|
|
|
|
env: Object.assign({ NODE_MODULES_PATH }, process.env),
|
|
|
|
})
|
|
|
|
|
|
|
|
electronProcess.on('close', code => {
|
|
|
|
if (code === 0) {
|
|
|
|
electronProcess.removeAllListeners()
|
2024-11-15 15:12:55 +03:00
|
|
|
exit()
|
2024-07-26 09:34:51 +03:00
|
|
|
}
|
|
|
|
})
|
2024-11-15 15:12:55 +03:00
|
|
|
|
2024-07-26 09:34:51 +03:00
|
|
|
electronProcess.on('error', error => {
|
2024-11-15 15:12:55 +03:00
|
|
|
console.error(chalk.red('Electron process failed:'), error)
|
|
|
|
console.error(chalk.red('Killing electron process.'))
|
2024-07-26 09:34:51 +03:00
|
|
|
electronProcess.removeAllListeners()
|
|
|
|
electronProcess.kill()
|
2024-11-15 15:12:55 +03:00
|
|
|
exit(1)
|
2024-07-26 09:34:51 +03:00
|
|
|
})
|
2024-03-27 17:42:23 +03:00
|
|
|
}
|
2024-05-22 16:56:42 +03:00
|
|
|
|
|
|
|
startElectronProcess()
|