Skip to content

feat(tools-scripts): Add tools-scripts package for common cli helpers and routines #3610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

JasonVMo
Copy link
Contributor

@JasonVMo JasonVMo commented May 9, 2025

Description

Adds a tools-scripts package for common routines and helpers for building CLIs. This will be used to share code amongst our CLI implementations and provide helpers for implementing repo scripts folders.

@JasonVMo JasonVMo requested review from acoates-ms and tido64 as code owners May 9, 2025 19:05
@github-actions github-actions bot added the chore Improvements that don't directly affect features label May 9, 2025
@JasonVMo JasonVMo enabled auto-merge (squash) May 10, 2025 22:58
* @returns a script context object to use for run commands
*/
context(overrides: Partial<ScriptContext> = {}): ScriptContext {
return { ...RnxCli.defaultContext, ...this.scriptDefaults, ...overrides };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to copy this.scriptDefaults here? It should already be a part of RnxCli.defaultContext. We should be able to remove this.scriptDefaults entirely.

export { BaseCommand } from "./commands.ts";
export { createLintCommand } from "./lint-command.ts";
export {
defaultLintConfig as defaultLintOptions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename defaultLintConfig to defaultLintOptions?

Comment on lines +13 to +22
cwd() {
return this.context.cwd;
}

/**
* @returns {string}
*/
root() {
return this.context.root;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see these being used anywhere. The lint command accesses cwd directly via this.context.cwd. Do we really need these props here?

type LintConfiguration,
type LintOptions,
} from "./lint.ts";
import { type ScriptContext } from "./types.ts";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

types.ts shouldn't contain anything but types:

Suggested change
import { type ScriptContext } from "./types.ts";
import type { ScriptContext } from "./types.ts";

},
"peerDependencies": {
"eslint": "^9.0.0",
"eslint-formatter-pretty": "^6.0.1"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linting is not formatting. We should keep them separate. ESLint and Prettier will conflict with each other.

*/
constructor(root: string, options: Partial<CliOptions> = {}) {
super(options);
this.scriptDefaults = { root, cwd: process.cwd() };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is process.cwd() always the package root? Can these commands be run outside a package manager?

Comment on lines +75 to +77
/**
* Fix the found issues where possible
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: These comments are unnecessary because we also have descriptions.

Comment on lines +75 to +77

// dynamically import eslint and the pretty formatter since these are optional peer dependencies
const { ESLint } = await import("eslint");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should catch this and output an actionable error message e.g.:

function importESLint() {
  try {
    const { ESLint } = import("eslint");
    return ESLint;
  } catch (_) {
    process.exitCode = 1;
  }
}

...

  // dynamically import eslint and the pretty formatter since these are optional peer dependencies
  const ESLint = importESLint();
  if (!ESLint) {
    console.error("Could not find `eslint`; did you forget to add it as a dev dependency?");
    return;
  }

const { fallbackConfig, cwd } = options;

// default to the local config in cwd if it exists
const eslintConfigPath = path.join(cwd, "eslint.config.js");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const { cwd, filePatterns = [], globalIgnores = [] } = options;

// use git to list the files in the directory
const { stdout } = spawnSync("git", ["ls-files", ...filePatterns], {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git ls-files can also exclude files with :!:<pattern>:

Suggested change
const { stdout } = spawnSync("git", ["ls-files", ...filePatterns], {
const { stdout } = spawnSync("git", ["ls-files", ...filePatterns, globalIgnores.map((p) => `:!:${p}`)], {

/**
* either a list of files to lint, or a list of patterns to use for file matching
*/
filesOrPatterns = Option.Rest();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing I've just recalled is that this pattern basically blackboxes the command i.e., you can no longer pass flags directly to ESLint. Sometimes, this is desirable because we cannot keep adding an entry for every new flag that gets added and it prevents people from learning a generic tool like ESLint. In 1JS, we started out like this and it was a pretty bad experience until we opened up the commands. We should not make the same mistake here.

@JasonVMo JasonVMo marked this pull request as draft June 18, 2025 15:21
auto-merge was automatically disabled June 18, 2025 15:21

Pull request was converted to draft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore Improvements that don't directly affect features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants