diff --git a/bin/run.js b/bin/run.js index daa3a38de..8fd0e4b23 100755 --- a/bin/run.js +++ b/bin/run.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import { runCLI } from "../dist/index.js"; +import { runCLI } from "../dist/cli/index.js"; // Disable Clack spinners and animations in non-interactive environments. // Clack only checks the CI env var, so we set it when stdin/stdout aren't TTYs. diff --git a/infra/build.ts b/infra/build.ts new file mode 100644 index 000000000..0d9e3d459 --- /dev/null +++ b/infra/build.ts @@ -0,0 +1,56 @@ +import { watch } from "node:fs"; +import chalk from "chalk"; + +const runBuild = async () => { + const result = await Bun.build({ + entrypoints: ["./src/cli/index.ts"], + outdir: "./dist/cli", + target: "node", + format: "esm", + sourcemap: "inline", + }); + + if (!result.success) { + console.error(chalk.red.bold("\nāœ— Build failed\n")); + for (const log of result.logs) { + console.error(chalk.red(` ${log}`)); + } + process.exit(1); + } + + return result; +}; + +const formatOutput = (outputs: { path: string }[]) => { + return outputs.map((o) => chalk.cyan(o.path)).join("\n "); +}; + +if (process.argv.includes("--watch")) { + console.log(chalk.yellow("Watching for changes...")); + + const changeHandler = async (event: "rename" | "change", filename: string | null) => { + const time = new Date().toLocaleTimeString(); + console.log(chalk.dim(`[${time}]`), chalk.gray(`${filename} ${event}d`)); + + const result = await runBuild(); + console.log( + chalk.green(` āœ“ Rebuilt`), + chalk.dim(`→`), + formatOutput(result.outputs) + ); + }; + + await runBuild(); + + for (const dir of ["./src"]) { + watch(dir, { recursive: true }, changeHandler); + } + + // Keep process alive + await new Promise(() => {}); +} else { + const result = await runBuild(); + console.log(chalk.green.bold(`\nāœ“ Build complete\n`)); + console.log(chalk.dim(" Output:")); + console.log(` ${formatOutput(result.outputs)}\n`); +} diff --git a/package.json b/package.json index 13b3a794f..7fc0b3588 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,12 @@ "bin" ], "scripts": { - "build": "rm -rf dist && bun build src/cli/index.ts --outdir dist --target node --format esm --sourcemap=inline && cp -r templates dist/", + "build": "bun run clean && cp -r templates dist/ && bun run infra/build.ts", + "build:watch": "bun run clean && cp -r templates dist/ && bun run infra/build.ts --watch", "typecheck": "tsc --noEmit", "dev": "./bin/dev.ts", "start": "./bin/run.js", - "clean": "rm -rf dist", + "clean": "rm -rf dist && mkdir -p dist", "lint": "biome check src tests", "lint:fix": "biome check --write src tests", "test": "vitest run", diff --git a/src/core/config.ts b/src/core/config.ts index 2f7b7c10b..7ec86e197 100644 --- a/src/core/config.ts +++ b/src/core/config.ts @@ -8,7 +8,7 @@ import { } from "@/core/project/schema.js"; // After bundling, import.meta.url points to dist/cli/index.js -// Templates are copied to dist/cli/templates/ +// Templates are copied to dist/templates/ const __dirname = dirname(fileURLToPath(import.meta.url)); export function getBase44GlobalDir(): string { @@ -20,7 +20,7 @@ export function getAuthFilePath(): string { } export function getTemplatesDir(): string { - return join(__dirname, "templates"); + return join(__dirname, "../templates"); } export function getTemplatesIndexPath(): string { diff --git a/tests/cli/testkit/CLITestkit.ts b/tests/cli/testkit/CLITestkit.ts index 81f041745..d32c8357d 100644 --- a/tests/cli/testkit/CLITestkit.ts +++ b/tests/cli/testkit/CLITestkit.ts @@ -9,7 +9,7 @@ import type { CLIResult } from "./CLIResultMatcher.js"; import { CLIResultMatcher } from "./CLIResultMatcher.js"; const __dirname = dirname(fileURLToPath(import.meta.url)); -const DIST_INDEX_PATH = join(__dirname, "../../../dist/index.js"); +const DIST_INDEX_PATH = join(__dirname, "../../../dist/cli/index.js"); /** Type for CLIContext */ interface CLIContext {