Skip to content
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

Various improvements #60

Merged
merged 4 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Depot works on Javascript workspaces that have been created by Depot, specifical
* For libraries, transpiles with [Typescript]
* For scripts and websites, bundles with [Vite]
* `depot test` - runs tests with [Vitest]
* `depot fmt` - formats source files with [Prettier]
* `depot fmt` - formats source files with [Biome]
* `depot doc` - generates documentation with [Typedoc]

A few benefits of using Depot:
Expand Down Expand Up @@ -93,6 +93,6 @@ Depot is used in a few of our projects:
[Typescript]: https://www.typescriptlang.org/
[Vite]: https://vitejs.dev/
[Vitest]: https://vitest.dev/
[Prettier]: https://prettier.io/
[Biome]: https://biomejs.dev/
[Typedoc]: https://typedoc.org/
[pnpm]: https://pnpm.io/
13 changes: 7 additions & 6 deletions crates/depot/src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub struct BuildArgs {
#[clap(short, long, action)]
pub watch: bool,

/// Fail if eslint finds a lint issue
/// Fail if biome finds a lint issue
#[clap(short, long, action)]
pub lint_fail: bool,
}
Expand Down Expand Up @@ -62,7 +62,7 @@ impl PackageCommand for BuildCommand {
Target::Lib => processes.push(self.copy_assets(pkg).boxed()),
}

processes.extend([self.tsc(pkg).boxed(), self.eslint(pkg).boxed()]);
processes.extend([self.tsc(pkg).boxed(), self.biome(pkg).boxed()]);

try_join_all(processes).await?;

Expand Down Expand Up @@ -105,15 +105,16 @@ impl BuildCommand {
.await
}

async fn eslint(&self, pkg: &Package) -> Result<()> {
let process = pkg.start_process("eslint", |cmd| {
async fn biome(&self, pkg: &Package) -> Result<()> {
let process = pkg.start_process("biome", |cmd| {
cmd.arg("check");
cmd.args(pkg.source_files());
cmd.arg("--color");
cmd.arg("--colors=force");
// TODO: watch mode
})?;

let status = process.wait().await?;
ensure!(!self.args.lint_fail || status.success(), "eslint failed");
ensure!(!self.args.lint_fail || status.success(), "biome failed");

Ok(())
}
Expand Down
9 changes: 5 additions & 4 deletions crates/depot/src/commands/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use anyhow::{Context, Result};

use crate::workspace::{package::Package, Command, CoreCommand, PackageCommand};

/// Fix eslint issues where possible
/// Fix biome issues where possible
#[derive(clap::Parser, Debug)]
pub struct FixArgs {
/// Additional arguments to pass to prettier
#[arg(last = true)]
pub eslint_args: Option<String>,
pub biome_args: Option<String>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -35,13 +35,14 @@ impl CoreCommand for FixCommand {
#[async_trait::async_trait]
impl PackageCommand for FixCommand {
async fn run_pkg(&self, pkg: &Package) -> Result<()> {
let extra = match &self.args.eslint_args {
let extra = match &self.args.biome_args {
Some(args) => shlex::split(args).context("Failed to parse prettier args")?,
None => Vec::new(),
};

let _ = pkg
.exec("eslint", |cmd| {
.exec("biome", |cmd| {
cmd.arg("check");
cmd.arg("--fix");
cmd.args(pkg.source_files());
cmd.args(extra);
Expand Down
7 changes: 5 additions & 2 deletions crates/depot/src/commands/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ impl PackageCommand for FmtCommand {
};

pkg
.exec("prettier", |cmd| {
cmd.arg(if self.args.check { "-c" } else { "-w" });
.exec("biome", |cmd| {
cmd.arg("format");
if !self.args.check {
cmd.arg("--write");
}
cmd.args(pkg.source_files());
cmd.args(extra);
})
Expand Down
118 changes: 34 additions & 84 deletions crates/depot/src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl NewCommand {
("pnpm-workspace.yaml".into(), PNPM_WORKSPACE.into()),
];
files.extend(self.make_tsconfig()?);
files.extend(self.make_eslint_config()?);
files.extend(Self::make_biome_config()?);
files.extend(self.make_typedoc_config()?);
files.extend(Self::make_prettier_config());
files.extend(Self::make_gitignore());
Expand Down Expand Up @@ -242,7 +242,9 @@ impl NewCommand {
// Allows special Vite things like importing files with ?raw
files.push((
"src/bindings/vite.d.ts".into(),
r#"/// <reference types="vite/client" />"#.into(),
r#"/// <reference types="vite/client" />
"#
.into(),
));
}
}
Expand All @@ -252,77 +254,28 @@ impl NewCommand {
Ok(files)
}

fn make_eslint_config(&self) -> Result<FileVec> {
let mut config = json!({
"env": {
"es2021": true,
fn make_biome_config() -> Result<FileVec> {
let config = json!({
"$schema": "https://biomejs.dev/schemas/1.8.2/schema.json",
"organizeImports": {
"enabled": true
},
"extends": ["eslint:recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 13,
"sourceType": "module",
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"plugins": ["@typescript-eslint", "prettier", "eslint-plugin-unused-imports"],
"ignorePatterns": ["*.d.ts"],
"rules": {
"no-empty-pattern": "off",
"no-undef": "off",
"no-unused-vars": "off",
"no-cond-assign": "off",
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_",
},
],
"no-constant-condition": ["error", { "checkLoops": false }],
"prettier/prettier": "error",
},
});

if !self.args.workspace && self.ws_opt.is_some() {
config = json!({
"extends": "../../.eslintrc.cjs"
});

let platform_config = match self.args.platform {
Platform::Browser => json!({
"env": {"browser": true},
}),
Platform::Node => json!({
"env": {"node": true},
}),
};

json_merge(&mut config, platform_config);
}

if self.args.react {
let react_config = json!({
"plugins": ["react"],
"linter": {
"enabled": true,
"rules": {
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
},
"settings": {
"react": {
"version": "detect",
},
"recommended": true,
"correctness": {"noUnusedImports": "warn"},
"style": {"noNonNullAssertion": "off", "useConst": "off"}
}
});

json_merge(&mut config, react_config);
}
}
});

let config_str = serde_json::to_string_pretty(&config)?;
let src = format!("module.exports = {config_str}");
Ok(vec![(".eslintrc.cjs".into(), src.into())])
Ok(vec![("biome.json".into(), config_str.into())])
}

#[allow(clippy::too_many_lines)]
Expand Down Expand Up @@ -539,7 +492,7 @@ export default defineConfig(({{ mode }}) => ({{

fn install_ws_dependencies(&self, root: &Path, is_workspace: bool) -> Result<()> {
#[rustfmt::skip]
let mut ws_dependencies: Vec<&str> = vec![
let ws_dependencies: Vec<&str> = vec![
// Building
"vite",

Expand All @@ -550,32 +503,29 @@ export default defineConfig(({{ mode }}) => ({{
"typescript",
"@types/node",

// Linting
"eslint@8",
"@typescript-eslint/eslint-plugin@7",
"@typescript-eslint/parser@7",
"eslint-plugin-prettier@4",
"eslint-plugin-unused-imports@3",

// Formatting
"prettier@2",
"@trivago/prettier-plugin-sort-imports@4",
// Linting and formatting
"@biomejs/biome",

// Documentation generation
"typedoc"
];

if self.args.react {
ws_dependencies.extend(["eslint-plugin-react", "eslint-plugin-react-hooks"]);
}

self.run_pnpm(|pnpm| {
pnpm.args(["add", "--save-dev"]).args(&ws_dependencies);
if is_workspace {
pnpm.arg("--workspace-root");
}
pnpm.current_dir(root);
})
})?;

// Temporary fix for installing native modules on M-series Macs.
// --force ensures that the arm64 package is installed for Biome.
self.run_pnpm(|pnpm| {
pnpm.args(["install", "--force"]);
pnpm.current_dir(root);
})?;

Ok(())
}

fn make_index_html(js_entry_point: &str, css_entry_point: &str) -> String {
Expand Down Expand Up @@ -747,7 +697,7 @@ export default defineConfig(({{ mode }}) => ({{
),
]);
files.extend(self.make_tsconfig()?);
files.extend(self.make_eslint_config()?);
files.extend(Self::make_biome_config()?);
files.extend(self.make_vite_config(src_path));

if self.ws_opt.is_none() {
Expand Down
1 change: 1 addition & 0 deletions crates/depot/src/workspace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ impl WorkspaceInner {

let mut cmd = tokio::process::Command::new(script_path);
cmd.current_dir(&self.root);
cmd.env("NODE_PATH", self.root.join("node_modules"));

configure(&mut cmd);

Expand Down
11 changes: 8 additions & 3 deletions crates/depot/src/workspace/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ pub struct PackageInner {
// Metadata
pub root: PathBuf,
pub manifest: PackageManifest,
#[allow(unused)]
pub platform: Platform,
pub target: Target,
pub name: PackageName,
Expand Down Expand Up @@ -300,13 +301,17 @@ impl PackageInner {
}

pub fn source_files(&self) -> impl Iterator<Item = PathBuf> + '_ {
// TODO: make this configurable
let source_extensions = hashset! { "ts", "tsx", "html" };

["src", "tests"]
.into_iter()
.flat_map(|dir| self.iter_files(dir))
.filter_map(|path| {
.filter_map(move |path| {
let ext = path.extension()?;
let is_src_file = ext == "ts" || ext == "tsx";
is_src_file.then_some(path)
source_extensions
.contains(ext.to_str().unwrap())
.then_some(path)
})
}

Expand Down
1 change: 1 addition & 0 deletions crates/depot/src/workspace/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub enum OutputChannel {
/// A string emitted by a shell command on a given [`OutputChannel`].
pub struct LogLine {
pub line: String,
#[allow(unused)] // We may eventually want to distinguish stdout/stderr in the logs
pub channel: OutputChannel,
}

Expand Down
11 changes: 8 additions & 3 deletions crates/depot/src/workspace/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ impl Workspace {
})
}

fn build_task_graph(&self, cmd_graph: &CommandGraph) -> (TaskGraph, HashMap<Task, TaskFuture>) {
fn build_task_graph(
&self,
cmd_graph: &CommandGraph,
runtime: &Option<CommandRuntime>,
) -> (TaskGraph, HashMap<Task, TaskFuture>) {
let futures = RefCell::new(HashMap::new());
let task_pool = RefCell::new(HashMap::new());

Expand All @@ -125,6 +129,7 @@ impl Workspace {
.entry($key.clone())
.or_insert_with(|| {
let can_skip = !self.common.no_incremental
&& !matches!(runtime, Some(CommandRuntime::RunForever))
&& match $files {
Some(files) => {
let fingerprints = self.fingerprints.read().unwrap();
Expand Down Expand Up @@ -190,16 +195,16 @@ impl Workspace {
}

pub async fn run(&self, root: Command) -> Result<()> {
let runtime = root.runtime();
let cmd_graph = build_command_graph(&root);
let (task_graph, mut task_futures) = self.build_task_graph(&cmd_graph);
let (task_graph, mut task_futures) = self.build_task_graph(&cmd_graph, &runtime);

let log_should_exit: Arc<Notify> = Arc::new(Notify::new());
let runner_should_exit: Arc<Notify> = Arc::new(Notify::new());

let runner_should_exit_fut = runner_should_exit.notified();
tokio::pin!(runner_should_exit_fut);

let runtime = root.runtime();
let cleanup_logs = self.spawn_log_thread(&log_should_exit, &runner_should_exit, &runtime);

let mut running_futures = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion crates/depot/tests/tests/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use depot_test_utils::{project, workspace_single_lib};

#[test]
fn basic() {
let p = project();
let p = project().persist();
p.file("src/lib.ts", "let x = 1 + 2;");
p.depot("fmt");
assert_eq!(p.read("src/lib.ts"), "let x = 1 + 2;\n");
Expand Down
2 changes: 1 addition & 1 deletion crates/depot/tests/tests/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ use depot_test_utils::project;
#[test]
fn formatting() {
let p = project();
p.depot("fmt -- --check");
p.depot("fmt --check");
}
Loading