diff --git a/bun.lockb b/bun.lockb index 5782428..f357785 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 64c6717..f02e978 100644 --- a/package.json +++ b/package.json @@ -23,5 +23,10 @@ "pretest": "bun scripts/cleanupTestData.ts", "test": "bun test", "prepublishOnly": "bun run build" + }, + "bin": "dist/cli/index.js", + "optionalDependencies": { + "ansi-colors": "^4.1.3", + "enquirer": "^2.4.1" } } diff --git a/scripts/build.ts b/scripts/build.ts index 53b6ef6..4ef0311 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -4,7 +4,7 @@ await tsc.exited; // Build the project await Bun.build({ - entrypoints: ["src/index.ts"], + entrypoints: ["src/index.ts", "src/cli/index.ts"], root: "src", target: "node", minify: true, diff --git a/src/cli/help.ts b/src/cli/help.ts new file mode 100644 index 0000000..c7611fb --- /dev/null +++ b/src/cli/help.ts @@ -0,0 +1,41 @@ +import { colors } from "../log"; + +export function help(exit: number | false = 0) { + // If exiting with a non-zero exit code, + // print the error message to stderr + console[exit !== false && exit !== 0 ? "error" : "log"]( + colors.reset(`${colors.magenta.bold("Usage:")} ${colors.green( + "fast-asar" + )} ${colors.blue("")} + +${colors.blue.bold("Commands:")} + ${colors.blue("extract")} ${colors.yellow( + " " + )} Extract an archive + ${colors.blue("pack")} ${colors.yellow( + " " + )} Pack a directory into an archive + ${colors.blue("list")} ${colors.yellow( + "" + )} List the contents of an archive + ${colors.blue("help")} Show this help message + +${colors.magenta.bold("Examples:")} + ${colors.magenta("bunx")} ${colors.green("fast-asar")} ${colors.blue( + "extract" + )} ${colors.yellow("app.asar app/")} + ${colors.magenta("bunx")} ${colors.green("fast-asar")} ${colors.blue( + "pack" + )} ${colors.yellow("app/ app.asar")} + ${colors.magenta("bunx")} ${colors.green("fast-asar")} ${colors.blue( + "list" + )} ${colors.yellow("app.asar")} + ${colors.magenta("bunx")} ${colors.green("fast-asar")} ${colors.blue( + "help" + )}`) + ); + + if (exit !== false) { + process.exit(exit); + } +} diff --git a/src/cli/index.ts b/src/cli/index.ts new file mode 100644 index 0000000..1330f11 --- /dev/null +++ b/src/cli/index.ts @@ -0,0 +1,14 @@ +#!/usr/bin/env node + +import { help } from "./help"; +import { colors } from "../log"; + +const command = process.argv[2]; + +if (!command) { + console.error( + colors.red("error") + colors.gray(":"), + "No command specified\n" + ); + help(2); +} diff --git a/src/log/colors.ts b/src/log/colors.ts new file mode 100644 index 0000000..069e253 --- /dev/null +++ b/src/log/colors.ts @@ -0,0 +1,26 @@ +let colors: typeof import("ansi-colors"); +try { + colors = await import("ansi-colors"); +} catch { + // If ansi-colors is not installed, return a proxy that returns itself + // when any property is accessed + // @ts-expect-error + colors = new Proxy((a: string) => a, { + get() { + return colors; + }, + }); + + // This is done so that if color functions are called, they will + // just return the string that was passed to them without any + // colors, instead of throwing an error because the function + // doesn't exist. + + // So for example, the following code would log "Hello, world!" + // in red if ansi-colors is installed, and just "Hello, world!" + // with no colors if it isn't installed: + // + // console.log(colors.red("Hello, world!")); +} + +export { colors }; diff --git a/src/log/index.ts b/src/log/index.ts new file mode 100644 index 0000000..c2a87de --- /dev/null +++ b/src/log/index.ts @@ -0,0 +1,9 @@ +import { colors } from "./colors"; + +export function error(message: string) { + console.error(colors.red("error") + colors.gray(":"), message); +} + +export const ok = colors.ok; + +export { colors };