Skip to content

Commit

Permalink
add dev command
Browse files Browse the repository at this point in the history
  • Loading branch information
The-Best-Codes committed Jan 8, 2025
1 parent 7529b0e commit 924b67f
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 6 deletions.
9 changes: 7 additions & 2 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"workspaces": {
"": {
"dependencies": {
"chokidar": "latest",
"commander": "latest",
"consola": "latest",
"esbuild": "latest",
Expand Down Expand Up @@ -159,7 +160,7 @@

"@oven/bun-windows-x64-baseline": ["@oven/[email protected]", "", { "os": "win32", "cpu": "x64" }, "sha512-xnlYa1jKknImCw7xmSD91H8e+w3BC6mIShOfHhFWfNhdyvEtundXhIu7VddwxKBMs5S/iiFJiutnZ2EyLq4CAQ=="],

"@types/bun": ["@types/[email protected].14", "", { "dependencies": { "bun-types": "1.1.37" } }, "sha512-opVYiFGtO2af0dnWBdZWlioLBoxSdDO5qokaazLhq8XQtGZbY4pY3/JxY8Zdf/hEwGubbp7ErZXoN1+h2yesxA=="],
"@types/bun": ["@types/[email protected].15", "", { "dependencies": { "bun-types": "1.1.42" } }, "sha512-Fi7ND1jCq8O5iU3s9z3TKHggD0hidgpe7wSxyisviXpbMmY4B1KiokF3f/mmjOoDrEcf873tSpixgen7Wm9X0g=="],

"@types/estree": ["@types/[email protected]", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="],

Expand Down Expand Up @@ -211,14 +212,16 @@

"bun": ["[email protected]", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.1.42", "@oven/bun-darwin-x64": "1.1.42", "@oven/bun-darwin-x64-baseline": "1.1.42", "@oven/bun-linux-aarch64": "1.1.42", "@oven/bun-linux-aarch64-musl": "1.1.42", "@oven/bun-linux-x64": "1.1.42", "@oven/bun-linux-x64-baseline": "1.1.42", "@oven/bun-linux-x64-musl": "1.1.42", "@oven/bun-linux-x64-musl-baseline": "1.1.42", "@oven/bun-windows-x64": "1.1.42", "@oven/bun-windows-x64-baseline": "1.1.42" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bun.exe" } }, "sha512-PckeNolMEBaBEzixTMvp0jJD9r/9lly8AfctILi1ve14zwwChFjsxI4TJLQO2yezzOjVeG0u7xf8WQFbS7GjAA=="],

"bun-types": ["[email protected].37", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-C65lv6eBr3LPJWFZ2gswyrGZ82ljnH8flVE03xeXxKhi2ZGtFiO4isRKTKnitbSqtRAcaqYSR6djt1whI66AbA=="],
"bun-types": ["[email protected].42", "", { "dependencies": { "@types/node": "~20.12.8", "@types/ws": "~8.5.10" } }, "sha512-beMbnFqWbbBQHll/bn3phSwmoOQmnX2nt8NI9iOQKFbgR5Z6rlH3YuaMdlid8vp5XGct3/W4QVQBmhoOEoe4nw=="],

"callsites": ["[email protected]", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],

"chalk": ["[email protected]", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],

"chardet": ["[email protected]", "", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="],

"chokidar": ["[email protected]", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],

"cli-width": ["[email protected]", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],

"color-convert": ["[email protected]", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
Expand Down Expand Up @@ -385,6 +388,8 @@

"queue-microtask": ["[email protected]", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],

"readdirp": ["[email protected]", "", {}, "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA=="],

"resolve-from": ["[email protected]", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],

"reusify": ["[email protected]", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="],
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "discraft",
"version": "1.6.2-beta.11",
"version": "1.6.2-beta.12",
"description": "Ultimate Discord bot framework",
"type": "module",
"packageManager": "[email protected]",
Expand Down Expand Up @@ -48,7 +48,7 @@
"homepage": "https://github.com/The-Best-Codes/discraft-js#readme",
"devDependencies": {
"@eslint/js": "^9.17.0",
"@types/bun": "^1.1.14",
"@types/bun": "^1.1.15",
"@types/fs-extra": "^11.0.4",
"bun": "^1.1.42",
"eslint": "^9.17.0",
Expand All @@ -59,6 +59,7 @@
"typescript": "^5.7.2"
},
"dependencies": {
"chokidar": "^4.0.3",
"commander": "^13.0.0",
"consola": "^3.3.3",
"esbuild": "^0.24.2",
Expand Down
25 changes: 25 additions & 0 deletions package/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { program } from "commander";
import consola from "consola";
import { version } from "../../package.json";
import { build } from "./cli/build";
import { dev } from "./cli/dev";
import { init } from "./cli/init";
import { start } from "./cli/start";

Expand Down Expand Up @@ -40,6 +41,30 @@ program
});
});

program
.command("dev")
.description("Start the bot in development mode")
.option(
"-b, --builder <builder>",
"Specify the builder to use (esbuild or bun). Defaults to auto-detect.",
(value) => {
if (value !== "esbuild" && value !== "bun") {
consola.error("Invalid builder value. Must be 'esbuild' or 'bun'.");
process.exit(1);
}
return value;
},
)
.option("-c, --clear-console", "Clear the console on each rebuild.", false)
.action((options) => {
dev({ builder: options.builder, clearConsole: options.clearConsole }).catch(
(error) => {
consola.error("An error occurred during development:", error);
process.exit(1);
},
);
});

program
.command("init")
.description("Initialize a new Discraft project")
Expand Down
13 changes: 11 additions & 2 deletions package/src/cli/build/build.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { spawn } from "child_process";
import consola from "consola";
import { build as esbuild } from "esbuild";
import { nodeExternalsPlugin } from "esbuild-node-externals";
import { promisify } from "util";

// eslint-disable-next-line @typescript-eslint/no-require-imports
const exec = promisify(require("child_process").exec);

type Builder = "esbuild" | "bun";
Expand Down Expand Up @@ -71,7 +74,10 @@ async function build(
});
} catch (error: any) {
consola.error(`Error during bun build: ${error.message}`);
process.exit(1);
if (env !== "dev") {
process.exit(1);
}
throw error; // Throw the error, to be caught by `rebuildBot`
}
} else {
try {
Expand All @@ -87,7 +93,10 @@ async function build(
consola.success("Build complete using esbuild.");
} catch (error: any) {
consola.error(`Error during esbuild: ${error.message}`);
process.exit(1);
if (env !== "dev") {
process.exit(1);
}
throw error; // Throw the error, to be caught by `rebuildBot`
}
}
}
Expand Down
1 change: 1 addition & 0 deletions package/src/cli/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ async function startBuild(options?: BuildOptions) {
await build("prod", srcPath, outputPath, options?.builder);
consola.info("Build output: " + outputPath);
consola.success(`Build finished successfully!`);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
consola.error(`Build failed: ${error.message}`);
}
Expand Down
156 changes: 156 additions & 0 deletions package/src/cli/dev/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { spawn } from "child_process";
import chokidar from "chokidar";
import consola from "consola";
import path from "path";
import { promisify } from "util";
import { build } from "../build/build";
import { generateIndexFiles } from "../build/commandsAndEvents";

// eslint-disable-next-line @typescript-eslint/no-require-imports
const exec = promisify(require("child_process").exec);

type Builder = "esbuild" | "bun";

interface DevOptions {
builder?: Builder;
clearConsole?: boolean;
}

const CWD = process.cwd();
const DIST_DIR = path.join(CWD, "dist");
const DISCRAFT_DIR = path.join(CWD, ".discraft");
const NODE_MODULES_DIR = path.join(CWD, "node_modules");
const IGNORED_FILES = [
DIST_DIR,
DISCRAFT_DIR,
NODE_MODULES_DIR,
"*.log",
".git",
".env",
];

async function startDev(options?: DevOptions) {
let botProcess: any = null;
let runner: string = "node";
const clearConsole = options?.clearConsole ?? false;

// Function to start bot
const startBot = async () => {
const distPath = path.join(DIST_DIR, "index.js");

if (botProcess) {
consola.info("🔄 Restarting bot...");
botProcess.kill("SIGINT");
await new Promise((resolve) => botProcess.on("exit", resolve));
consola.info("Old bot process terminated.");
}

try {
botProcess = spawn(runner, [distPath], {
stdio: "inherit",
});

botProcess.on("error", (error: any) => {
consola.error(`Error starting the bot: ${error.message}`);
});

botProcess.on("exit", (code: number | null) => {
if (code === 0) {
consola.info("Bot process exited.");
} else {
consola.error(`Bot process exited with code ${code}`);
}
});

consola.info("Listening for bot output...");
} catch (error: any) {
consola.error(`Error starting the bot: ${error.message}`);
}
};

// Function to rebuild the bot
const rebuildBot = async () => {
if (clearConsole) {
process.stdout.write("\x1bc");
}

consola.info("Change detected, rebuilding...");
try {
await generateIndexFiles();
await build(
"dev",
path.join(CWD, "index.ts"),
DIST_DIR,
options?.builder,
);
consola.success("Rebuild complete.");
await startBot();
} catch (error: any) {
consola.error(`Rebuild failed: ${error.message}`);
consola.info("Waiting for changes...");
// Do NOT exit here
}
};

// Setup file watching and initial build
try {
consola.info("Starting in development mode...");
consola.info("Performing initial build...");

if (!options?.builder) {
try {
// Use bun --version to check for bun existence
await exec("bun --version");
runner = "bun";
consola.info("Bun detected. Using Bun CLI for dev.");
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
consola.info("Bun not detected. Using Node CLI for dev.");
}
} else {
runner = options.builder;
consola.info(`Using ${options.builder} instead of auto-detect.`);
}

await generateIndexFiles();
await build("dev", path.join(CWD, "index.ts"), DIST_DIR, options?.builder);
consola.success("Initial build complete.");
await startBot();

consola.info("Starting file watcher...");
const watcher = chokidar.watch(CWD, {
ignored: IGNORED_FILES,
ignoreInitial: true,
});

watcher.on("all", async (event, path) => {
consola.verbose(`File system event ${event} detected at ${path}`);
await rebuildBot();
});

process.on("SIGINT", () => {
consola.info("SIGINT signal received. Exiting development mode...");
if (botProcess) {
botProcess.kill("SIGINT");
}
watcher.close();
process.exit(0);
});

process.on("SIGTERM", () => {
consola.info("SIGTERM signal received. Exiting development mode...");
if (botProcess) {
botProcess.kill("SIGTERM");
}
watcher.close();
process.exit(0);
});
consola.success("Development environment is ready.");
} catch (error: any) {
consola.error(`Error during setup: ${error.message}`);
process.exit(1);
}
}

export { startDev as dev };

0 comments on commit 924b67f

Please sign in to comment.