diff --git a/.changeset/long-grapes-serve.md b/.changeset/long-grapes-serve.md new file mode 100644 index 0000000..5745536 --- /dev/null +++ b/.changeset/long-grapes-serve.md @@ -0,0 +1,5 @@ +--- +"@vlandoss/run-run": patch +--- + +Reorder commands diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9ea9d4..1ab75f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: uses: variableland/gh-actions/actions/setup-pnpm-bun@main - name: ๐Ÿ’… Test static - run: pnpm rr check tsc + run: pnpm rr test:static - name: ๐Ÿงช Test unit run: pnpm test diff --git a/README.md b/README.md index 83d56e3..79166e8 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,6 @@ To use this monorepo, you need to have the following tools installed: 3. Run tests: ```bash - pnpm rr check tsc pnpm test ``` diff --git a/packages/run-run/src/program/__tests__/__snapshots__/snapshots.test.ts.snap b/packages/run-run/src/program/__tests__/__snapshots__/snapshots.test.ts.snap index 4c45be1..d651883 100644 --- a/packages/run-run/src/program/__tests__/__snapshots__/snapshots.test.ts.snap +++ b/packages/run-run/src/program/__tests__/__snapshots__/snapshots.test.ts.snap @@ -7,19 +7,19 @@ The CLI toolbox for Variable Land ๐Ÿ‘Š Usage: rr|run-run [options] Options: - -v, --version output the version number - -h, --help display help for command + -v, --version output the version number + -h, --help display help for command Commands: - build:lib build a ts project ๐Ÿ—๏ธ (tsdown) - lint [options] lint the code ๐Ÿงน (biome) - fmt|format [options] format the code ๐ŸŽจ (biome) - check|test:static [options] check format and lint ๐Ÿ” (biome) - tsc|typecheck check if ts code is well typed ๐ŸŽจ (tsc) - clean [options] delete dirty folders or files ๐Ÿ—‘๏ธ (rimraf) - pkgs|packages [options] list unique affected packages from list of files - ๐Ÿ“ฆ - config|cfg display the current config ๐Ÿ› ๏ธ + build:lib build a ts library ๐Ÿ—๏ธ (tsdown) + jsc|jscheck [options] check format and lint ๐Ÿ” (biome) + tsc|tscheck check typescript errors ๐Ÿงฉ (tsc) + lint [options] check & fix lint errors ๐Ÿ” (biome) + format [options] check & fix format errors ๐ŸŽจ (biome) + test:static run static tests ๐Ÿ”ฌ (run-run) + clean [options] delete dirty files ๐Ÿ—‘๏ธ (rimraf) + pkgs [options] list affected packages ๐Ÿ“ฆ + config display the current config ๐Ÿ› ๏ธ Acknowledgment: - kcd-scripts: for main inspiration @@ -43,7 +43,8 @@ exports[`should match all root commands: root-command--v 1`] = ` exports[`should match help messages for all commands: help-command-build:lib 1`] = ` "Usage: rr build:lib [options] -build a ts project ๐Ÿ—๏ธ (tsdown) +Compiles TypeScript code into JavaScript and generates type declaration files, +making it ready for distribution. Options: -h, --help display help for command @@ -52,64 +53,79 @@ Under the hood, this command uses the tsdown CLI to build the project. " `; -exports[`should match help messages for all commands: help-command-lint 1`] = ` -"Usage: rr lint [options] +exports[`should match help messages for all commands: help-command-jsc 1`] = ` +"Usage: rr jsc|jscheck [options] -lint the code ๐Ÿงน (biome) +Checks the code for formatting and linting issues, ensuring it adheres to the +defined style and quality standards. Options: - -c, --check check if the code is valid (default: true) - -f, --fix try to fix all the code - -h, --help display help for command + --fix try to fix issues automatically + --fix-staged try to fix staged files only + -h, --help display help for command -Under the hood, this command uses the biome CLI to lint the code. +Under the hood, this command uses the biome CLI to check the code. " `; -exports[`should match help messages for all commands: help-command-fmt 1`] = ` -"Usage: rr fmt|format [options] +exports[`should match help messages for all commands: help-command-tsc 1`] = ` +"Usage: rr tsc|tscheck [options] -format the code ๐ŸŽจ (biome) +Checks the TypeScript code for type errors, ensuring that the code adheres to +the defined type constraints and helps catch potential issues before runtime. Options: - -c, --check check if the code is formatted (default: true) - -f, --fix format all the code - -h, --help display help for command + -h, --help display help for command -Under the hood, this command uses the biome CLI to format the code. +Under the hood, this command uses the tsc CLI to check the code. " `; -exports[`should match help messages for all commands: help-command-check 1`] = ` -"Usage: rr check|test:static [options] +exports[`should match help messages for all commands: help-command-lint 1`] = ` +"Usage: rr lint [options] -check format and lint ๐Ÿ” (biome) +Checks the code for linting issues and optionally fixes them, ensuring it +adheres to the defined quality standards. Options: - -f, --fix try to fix issues automatically - --fix-staged try to fix staged files only - -h, --help display help for command + -c, --check check if the code is valid (default: true) + --fix try to fix all the code + -h, --help display help for command -Under the hood, this command uses the biome CLI to check the code. +Under the hood, this command uses the biome CLI to lint the code. " `; -exports[`should match help messages for all commands: help-command-tsc 1`] = ` -"Usage: rr tsc|typecheck [options] +exports[`should match help messages for all commands: help-command-format 1`] = ` +"Usage: rr format [options] -check if ts code is well typed ๐ŸŽจ (tsc) +Checks the code for formatting issues and optionally fixes them, ensuring it +adheres to the defined style standards. Options: + --fix format all the code -h, --help display help for command -Under the hood, this command uses the tsc CLI to check the code. +Under the hood, this command uses the biome CLI to format the code. +" +`; + +exports[`should match help messages for all commands: help-command-test:static 1`] = ` +"Usage: rr test:static [options] + +Runs static tests, including linting, formatting checks, and TypeScript type +checking, to ensure code quality and correctness without executing the code. + +Options: + -h, --help display help for command " `; exports[`should match help messages for all commands: help-command-clean 1`] = ` "Usage: rr clean [options] -delete dirty folders or files ๐Ÿ—‘๏ธ (rimraf) +Deletes generated files and folders such as 'dist', 'node_modules', and lock +files to ensure a clean state. Options: --only-dist delete 'dist' folders only @@ -121,9 +137,10 @@ Under the hood, this command uses rimraf to delete dirty folders or files. `; exports[`should match help messages for all commands: help-command-pkgs 1`] = ` -"Usage: rr pkgs|packages [options] +"Usage: rr pkgs [options] -list unique affected packages from list of files ๐Ÿ“ฆ +Given a list of files, returns the list of affected packages. Useful to run +commands only on affected packages. Options: --files list of files to check @@ -133,9 +150,10 @@ Options: `; exports[`should match help messages for all commands: help-command-config 1`] = ` -"Usage: rr config|cfg [options] +"Usage: rr config [options] -display the current config ๐Ÿ› ๏ธ +Displays the current configuration settings, including their source file path if +available. Options: -h, --help display help for command diff --git a/packages/run-run/src/program/commands/build-lib.ts b/packages/run-run/src/program/commands/build-lib.ts index 0e24b6f..8367f9d 100644 --- a/packages/run-run/src/program/commands/build-lib.ts +++ b/packages/run-run/src/program/commands/build-lib.ts @@ -4,7 +4,10 @@ import type { Context } from "#/services/ctx"; export function createBuildLibCommand(ctx: Context) { return createCommand("build:lib") - .description(`build a ts project ๐Ÿ—๏ธ (${TOOL_LABELS.TSDOWN})`) + .summary(`build a ts library ๐Ÿ—๏ธ (${TOOL_LABELS.TSDOWN})`) + .description( + "Compiles TypeScript code into JavaScript and generates type declaration files, making it ready for distribution.", + ) .action(async function buildAction() { await ctx.shell.$`tsdown`; }) diff --git a/packages/run-run/src/program/commands/check.ts b/packages/run-run/src/program/commands/check.ts deleted file mode 100644 index cc5fc68..0000000 --- a/packages/run-run/src/program/commands/check.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { createCommand } from "commander"; -import isCI from "is-ci"; -import { BiomeService } from "#/services/biome"; -import type { Context } from "#/services/ctx"; - -export function createCheckCommand(ctx: Context) { - const biome = new BiomeService(ctx.shell); - - return createCommand("check") - .alias("test:static") - .description(`check format and lint ๐Ÿ” (${biome.ui})`) - .option("-f, --fix", "try to fix issues automatically") - .option("--fix-staged", "try to fix staged files only") - .action(async function checkAction(options) { - const toolCmd = (cmd = "check") => `${cmd} --colors=force`; - - if (options.fix) { - await biome.exec(`${toolCmd()} --fix`); - } else if (options.fixStaged) { - await biome.exec(`${toolCmd()} --no-errors-on-unmatched --fix --staged`); - } else { - await biome.exec(`${toolCmd(isCI ? "ci" : "check")}`); - } - }) - .addHelpText("afterAll", `\nUnder the hood, this command uses the ${biome.ui} CLI to check the code.`); -} diff --git a/packages/run-run/src/program/commands/clean.ts b/packages/run-run/src/program/commands/clean.ts index 39d74f9..6064e0f 100644 --- a/packages/run-run/src/program/commands/clean.ts +++ b/packages/run-run/src/program/commands/clean.ts @@ -12,7 +12,8 @@ type Options = { export function createCleanCommand() { return createCommand("clean") - .description(`delete dirty folders or files ๐Ÿ—‘๏ธ (${TOOL_LABELS.RIMRAF})`) + .summary(`delete dirty files ๐Ÿ—‘๏ธ (${TOOL_LABELS.RIMRAF})`) + .description("Deletes generated files and folders such as 'dist', 'node_modules', and lock files to ensure a clean state.") .option("--only-dist", "delete 'dist' folders only") .option("--dry-run", "outputs the paths that would be deleted") .action(async function cleanCommandAction(options: Options) { diff --git a/packages/run-run/src/program/commands/config.ts b/packages/run-run/src/program/commands/config.ts index 64262ce..e07bd1a 100644 --- a/packages/run-run/src/program/commands/config.ts +++ b/packages/run-run/src/program/commands/config.ts @@ -4,8 +4,8 @@ import type { Context } from "#/services/ctx"; export function createConfigCommand(ctx: Context) { return createCommand("config") - .alias("cfg") - .description("display the current config ๐Ÿ› ๏ธ") + .summary("display the current config ๐Ÿ› ๏ธ") + .description("Displays the current configuration settings, including their source file path if available.") .action(async function configAction() { const { config, meta } = ctx.config; console.log(palette.muted("Config:")); diff --git a/packages/run-run/src/program/commands/format.ts b/packages/run-run/src/program/commands/format.ts index 44f2e7d..23f418a 100644 --- a/packages/run-run/src/program/commands/format.ts +++ b/packages/run-run/src/program/commands/format.ts @@ -5,7 +5,6 @@ import { OxfmtService } from "#/services/oxfmt"; import type { Formatter } from "#/types/tool"; type ActionOptions = { - check?: boolean; fix?: boolean; }; @@ -22,11 +21,12 @@ function getToolService(ctx: Context): Formatter { export function createFormatCommand(ctx: Context) { const toolService = getToolService(ctx); - return createCommand("fmt") - .alias("format") - .description(`format the code ๐ŸŽจ (${toolService.ui})`) - .option("-c, --check", "check if the code is formatted", true) - .option("-f, --fix", "format all the code") + return createCommand("format") + .summary(`check & fix format errors ๐ŸŽจ (${toolService.ui})`) + .description( + "Checks the code for formatting issues and optionally fixes them, ensuring it adheres to the defined style standards.", + ) + .option("--fix", "format all the code") .action(async function formatAction(options: ActionOptions) { await toolService.format(options); }) diff --git a/packages/run-run/src/program/commands/jscheck.ts b/packages/run-run/src/program/commands/jscheck.ts new file mode 100644 index 0000000..0466f83 --- /dev/null +++ b/packages/run-run/src/program/commands/jscheck.ts @@ -0,0 +1,27 @@ +import { createCommand } from "commander"; +import { BiomeService } from "#/services/biome"; +import type { Context } from "#/services/ctx"; +import type { StaticChecker } from "#/types/tool"; + +type ActionOptions = { + fix?: boolean; + fixStaged?: boolean; +}; + +export function createJsCheckCommand(ctx: Context) { + const checkerService: StaticChecker = new BiomeService(ctx.shell); + + return createCommand("jsc") + .alias("jscheck") + .alias("check") + .summary(`check format and lint ๐Ÿ” (${checkerService.ui})`) + .description( + "Checks the code for formatting and linting issues, ensuring it adheres to the defined style and quality standards.", + ) + .option("--fix", "try to fix issues automatically") + .option("--fix-staged", "try to fix staged files only") + .action(async function checkAction(options: ActionOptions) { + await checkerService.check(options); + }) + .addHelpText("afterAll", `\nUnder the hood, this command uses the ${checkerService.ui} CLI to check the code.`); +} diff --git a/packages/run-run/src/program/commands/lint.ts b/packages/run-run/src/program/commands/lint.ts index 653e87c..a3d96fc 100644 --- a/packages/run-run/src/program/commands/lint.ts +++ b/packages/run-run/src/program/commands/lint.ts @@ -23,9 +23,12 @@ export function createLintCommand(ctx: Context) { const toolService = getToolService(ctx); return createCommand("lint") - .description(`lint the code ๐Ÿงน (${toolService.ui})`) + .summary(`check & fix lint errors ๐Ÿ” (${toolService.ui})`) + .description( + "Checks the code for linting issues and optionally fixes them, ensuring it adheres to the defined quality standards.", + ) .option("-c, --check", "check if the code is valid", true) - .option("-f, --fix", "try to fix all the code") + .option("--fix", "try to fix all the code") .action(async function lintAction(options: ActionOptions) { await toolService.lint(options); }) diff --git a/packages/run-run/src/program/commands/pkgs.ts b/packages/run-run/src/program/commands/pkgs.ts index 6be64e8..d5a8ac0 100644 --- a/packages/run-run/src/program/commands/pkgs.ts +++ b/packages/run-run/src/program/commands/pkgs.ts @@ -14,8 +14,10 @@ type Options = { export function createPkgsCommand(ctx: Context) { return createCommand("pkgs") - .alias("packages") - .description("list unique affected packages from list of files ๐Ÿ“ฆ") + .summary("list affected packages ๐Ÿ“ฆ") + .description( + "Given a list of files, returns the list of affected packages. Useful to run commands only on affected packages.", + ) .addOption(new Option("--files ", "list of files to check")) .addOption(new Option("--decorator [type]", "type of decorator to use").choices(decorators)) .action(async function pkgsAction({ files, decorator }: Options, cmd: Command) { diff --git a/packages/run-run/src/program/commands/test-static.ts b/packages/run-run/src/program/commands/test-static.ts new file mode 100644 index 0000000..3ecefda --- /dev/null +++ b/packages/run-run/src/program/commands/test-static.ts @@ -0,0 +1,14 @@ +import { createCommand } from "commander"; +import { TOOL_LABELS } from "#/program/ui"; +import type { Context } from "#/services/ctx"; + +export function createTestStaticCommand(ctx: Context) { + return createCommand("test:static") + .summary(`run static tests ๐Ÿ”ฌ (${TOOL_LABELS.RUN_RUN})`) + .description( + "Runs static tests, including linting, formatting checks, and TypeScript type checking, to ensure code quality and correctness without executing the code.", + ) + .action(async function testStaticAction() { + await ctx.shell.$`rr jscheck tscheck`; + }); +} diff --git a/packages/run-run/src/program/commands/typecheck.ts b/packages/run-run/src/program/commands/tscheck.ts similarity index 90% rename from packages/run-run/src/program/commands/typecheck.ts rename to packages/run-run/src/program/commands/tscheck.ts index 68debed..68ce990 100644 --- a/packages/run-run/src/program/commands/typecheck.ts +++ b/packages/run-run/src/program/commands/tscheck.ts @@ -45,7 +45,7 @@ async function typecheckAt({ dir, scripts, log, shell, run }: TypecheckAtOptions } } -export function createTypecheckCommand(ctx: Context) { +export function createTsCheckCommand(ctx: Context) { const { appPkg, shell, @@ -55,8 +55,11 @@ export function createTypecheckCommand(ctx: Context) { const toolUi = config.future?.oxc ? TOOL_LABELS.OXLINT : TOOL_LABELS.TSC; return createCommand("tsc") - .alias("typecheck") - .description(`check if ts code is well typed ๐ŸŽจ (${toolUi})`) + .alias("tscheck") + .summary(`check typescript errors ๐Ÿงฉ (${toolUi})`) + .description( + "Checks the TypeScript code for type errors, ensuring that the code adheres to the defined type constraints and helps catch potential issues before runtime.", + ) .addHelpText("afterAll", `\nUnder the hood, this command uses the ${toolUi} CLI to check the code.`) .action(async function typecheckAction() { const isTsProject = (dir: string) => appPkg.hasFile("tsconfig.json", dir); diff --git a/packages/run-run/src/program/index.ts b/packages/run-run/src/program/index.ts index 003dcc4..4a8359f 100644 --- a/packages/run-run/src/program/index.ts +++ b/packages/run-run/src/program/index.ts @@ -2,15 +2,16 @@ import { getVersion } from "@vlandoss/clibuddy"; import { createCommand } from "commander"; import { createContext } from "#/services/ctx"; import { createBuildLibCommand } from "./commands/build-lib"; -import { createCheckCommand } from "./commands/check"; import { createCleanCommand } from "./commands/clean"; import { createConfigCommand } from "./commands/config"; import { createFormatCommand } from "./commands/format"; +import { createJsCheckCommand } from "./commands/jscheck"; import { createLintCommand } from "./commands/lint"; import { createPkgsCommand } from "./commands/pkgs"; import { createRunCommand } from "./commands/run"; +import { createTestStaticCommand } from "./commands/test-static"; import { createToolsCommand } from "./commands/tools"; -import { createTypecheckCommand } from "./commands/typecheck"; +import { createTsCheckCommand } from "./commands/tscheck"; import { CREDITS_TEXT, getBannerText } from "./ui"; export type Options = { @@ -31,10 +32,12 @@ export async function createProgram(options: Options) { // build .addCommand(createBuildLibCommand(ctx)) // check + .addCommand(createJsCheckCommand(ctx)) + .addCommand(createTsCheckCommand(ctx)) .addCommand(createLintCommand(ctx)) .addCommand(createFormatCommand(ctx)) - .addCommand(createCheckCommand(ctx)) - .addCommand(createTypecheckCommand(ctx)) + // test + .addCommand(createTestStaticCommand(ctx)) // misc .addCommand(createCleanCommand()) .addCommand(createPkgsCommand(ctx)) diff --git a/packages/run-run/src/program/ui.ts b/packages/run-run/src/program/ui.ts index 718a221..ea3d2b4 100644 --- a/packages/run-run/src/program/ui.ts +++ b/packages/run-run/src/program/ui.ts @@ -13,6 +13,7 @@ const oxlintColor = colorize("#32F3E9"); const oxfmtColor = colorize("#32F3E9"); const tscColor = colorize("#3178C6"); const rimrafColor = colorize("#7C7270"); +const runRunColor = colorize("FC7A1E"); export const TOOL_LABELS = { TSDOWN: tsdownColor("tsdown"), @@ -21,6 +22,7 @@ export const TOOL_LABELS = { OXFMT: oxfmtColor("oxfmt"), TSC: tscColor("tsc"), RIMRAF: rimrafColor("rimraf"), + RUN_RUN: runRunColor("run-run"), }; export function getBannerText(version: string) { @@ -36,7 +38,7 @@ export function getBannerText(version: string) { const FOX_COLORS = { BLACK: colorize("#39393A"), - ORANGE: colorize("FC7A1e"), + ORANGE: runRunColor, WHITE: colorize("#FFFFFF"), }; diff --git a/packages/run-run/src/services/biome.ts b/packages/run-run/src/services/biome.ts index bcbe013..06bd1b1 100644 --- a/packages/run-run/src/services/biome.ts +++ b/packages/run-run/src/services/biome.ts @@ -1,9 +1,10 @@ import type { ShellService } from "@vlandoss/clibuddy"; +import isCI from "is-ci"; import { TOOL_LABELS } from "#/program/ui"; -import type { FormatOptions, Formatter, Linter, LintOptions } from "#/types/tool"; +import type { FormatOptions, Formatter, Linter, LintOptions, StaticChecker, StaticCheckerOptions } from "#/types/tool"; import { ToolService } from "./tool"; -export class BiomeService extends ToolService implements Formatter, Linter { +export class BiomeService extends ToolService implements Formatter, Linter, StaticChecker { constructor(shellService: ShellService) { super({ bin: "biome", ui: TOOL_LABELS.BIOME, shellService }); } @@ -13,22 +14,34 @@ export class BiomeService extends ToolService implements Formatter, Linter { } async format(options: FormatOptions) { - const commonOptions = "format --no-errors-on-unmatched --colors=force"; + const commonOptions = "format --colors=force --no-errors-on-unmatched"; if (options.fix) { await this.exec(`${commonOptions} --fix`); - } else if (options.check) { + } else { await this.exec(`${commonOptions}`); } } async lint(options: LintOptions) { - const commonOptions = "check --colors=force --formatter-enabled=false"; + const commonOptions = "check --colors=force --no-errors-on-unmatched --formatter-enabled=false"; if (options.fix) { await this.exec(`${commonOptions} --fix --unsafe`); - } else if (options.check) { + } else { await this.exec(`${commonOptions}`); } } + + async check(options: StaticCheckerOptions): Promise { + const commonOptions = (cmd = "check") => `${cmd} --colors=force --no-errors-on-unmatched`; + + if (options.fix) { + await this.exec(`${commonOptions()} --fix`); + } else if (options.fixStaged) { + await this.exec(`${commonOptions()} --fix --staged`); + } else { + await this.exec(`${commonOptions(isCI ? "ci" : "check")}`); + } + } } diff --git a/packages/run-run/src/services/oxfmt.ts b/packages/run-run/src/services/oxfmt.ts index d6c0a92..b978c85 100644 --- a/packages/run-run/src/services/oxfmt.ts +++ b/packages/run-run/src/services/oxfmt.ts @@ -17,7 +17,7 @@ export class OxfmtService extends ToolService implements Formatter { if (options.fix) { await this.exec(`${commonOptions} --fix`); - } else if (options.check) { + } else { await this.exec(`${commonOptions} --check`); } } diff --git a/packages/run-run/src/services/oxlint.ts b/packages/run-run/src/services/oxlint.ts index 83fdf53..4436434 100644 --- a/packages/run-run/src/services/oxlint.ts +++ b/packages/run-run/src/services/oxlint.ts @@ -17,7 +17,7 @@ export class OxlintService extends ToolService implements Linter { if (options.fix) { await this.exec(`${commonOptions} --fix`); - } else if (options.check) { + } else { await this.exec(`${commonOptions} --check`); } } diff --git a/packages/run-run/src/types/tool.ts b/packages/run-run/src/types/tool.ts index 1ac8854..5cec2da 100644 --- a/packages/run-run/src/types/tool.ts +++ b/packages/run-run/src/types/tool.ts @@ -1,13 +1,16 @@ export type FormatOptions = { - check?: boolean; fix?: boolean; }; export type LintOptions = { - check?: boolean; fix?: boolean; }; +export type StaticCheckerOptions = { + fix?: boolean; + fixStaged?: boolean; +}; + export type Formatter = { bin: string; ui: string; @@ -19,3 +22,13 @@ export type Linter = { ui: string; lint(options: LintOptions): Promise; }; + +export type StaticChecker = { + bin: string; + ui: string; + check(options: StaticCheckerOptions): Promise; +}; + +export type TypeChecker = { + check(): Promise; +};