Skip to content

Commit

Permalink
feat: add path
Browse files Browse the repository at this point in the history
  • Loading branch information
mysteryven committed Aug 14, 2024
1 parent 97e7bbe commit 22927c2
Show file tree
Hide file tree
Showing 13 changed files with 232 additions and 64 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
**/node_modules
/tests/**/*.yaml
/npm/!depclean/**/*
/depclean-*
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bpaf = { version = "0.9.12", features = ["derive"] }
colored = "2.1.0"
colorful = "0.3.2"
compact_str = { version = "0.8.0", features = ["serde"] }
Expand All @@ -16,7 +17,7 @@ oxc_allocator = "0.24.1"
oxc_ast = "0.24.1"
oxc_parser = "0.24.1"
oxc_semantic = "0.24.1"
oxc_span = { version = "0.24.1", features = ["serialize"]}
oxc_span = { version = "0.24.1", features = ["serialize"] }
oxc_syntax = "0.24.1"
rayon = "1.10.0"
serde = { version = "1.0.205", features = ["derive"] }
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ npx depclean
## Add this to your CI

```sh
depcheck
depclean
```

## Credits

- [depcheck](https://github.com/depcheck/depcheck)
- [oxc](https://github.com/oxc-project/oxc)

## LICENSE

[MIT](./LICENSE)
Empty file modified depclean-darwin-arm64
100755 → 100644
Empty file.
4 changes: 2 additions & 2 deletions examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use depcheck::DepChecker;
use depclean::DepClean;

// Instruction:
// run `cargo run -example basic`
fn main() {
let root_path = std::env::current_dir().unwrap().join("tests/fixtures");
let project_path = root_path.join("simple");

let mut checker = DepChecker::new();
let mut checker = DepClean::new();
checker.run_with_path(&project_path);
}
3 changes: 2 additions & 1 deletion npm/depclean/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"directory": "npm"
},
"bin": {
"depclean": "bin/depclean"
"depclean": "bin/depclean",
"abc": "123"
},
"engines": {
"node": ">=14.*"
Expand Down
134 changes: 116 additions & 18 deletions src/dependencies.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path;
use std::{path, str::FromStr};

use fxhash::{FxHashMap, FxHashSet};
use oxc_span::CompactStr;
Expand All @@ -12,51 +12,149 @@ pub struct PackageJSON {
}

#[derive(Debug, Default, Deserialize)]
pub struct DependenceContainer {
/// dependencies collect from package.json
#[serde(default)]
pub struct PackageJSONContainer {
dependencies: FxHashSet<CompactStr>,
unused_dependencies: FxHashSet<CompactStr>,
}

impl DependenceContainer {
impl PackageJSONContainer {
pub fn new() -> Self {
Self {
dependencies: FxHashSet::default(),
unused_dependencies: FxHashSet::default(),
}
}
pub fn unused_dependencies<'a>(
&'a self,
used: &'a FxHashSet<CompactStr>,
) -> impl Iterator<Item = &CompactStr> {
self.dependencies.difference(used)

pub fn unused_dependencies(&self) -> &FxHashSet<CompactStr> {
&self.unused_dependencies
}

pub fn compute_unused_deps<'a>(&'a mut self, used: &'a FxHashSet<CompactStr>) {
self.unused_dependencies = self
.dependencies
.iter()
.filter_map(|dep| {
// <https://github.com/npm/npm/issues/7351#issuecomment-74307522>
// If our package.json contains a dependency named "dep"
// 1. import Dep from 'dep'
if used.contains(dep) {
return None;
}

// 2. import { dep1 } from 'dep/dep1'
for used_dep in used.iter() {
if used_dep.starts_with(&format!("{dep}/")) {
return None;
}
}

Some(dep.clone())
})
.collect();
}
}

pub struct DependenceBuilder {
pub struct PackageJSONBuilder {
package_json: Option<PackageJSON>,
/// The raw content of package.json
raw: String,
}

impl DependenceBuilder {
impl PackageJSONBuilder {
pub fn new() -> Self {
Self { package_json: None }
Self {
package_json: None,
raw: String::new(),
}
}
/// # Panics
///
/// if path is not exist or a valid package.json file
pub fn with_package_json(&mut self, path: path::PathBuf) -> &mut Self {
let content = std::fs::read_to_string(path).unwrap();
let content = serde_json::from_str::<serde_json::Value>(&content).unwrap();
pub fn with_package_json(&mut self, path: &path::Path) -> &mut Self {
let raw = std::fs::read_to_string(path).unwrap();
let content = serde_json::from_str::<serde_json::Value>(&raw).unwrap();
let content = PackageJSON::deserialize(content).unwrap();
self.package_json = Some(content);
self.raw = raw;
self
}
pub fn build(self) -> DependenceContainer {
pub fn build(self) -> PackageJSONContainer {
let mut dependencies = FxHashSet::default();
if let Some(package_json) = self.package_json {
for (k, _) in package_json.dependencies {
dependencies.insert(k);
}
}
DependenceContainer { dependencies }
PackageJSONContainer {
dependencies,
unused_dependencies: FxHashSet::default(),
}
}
}

#[derive(Default)]
pub enum PkgManager {
#[default]
Npm,
Yarn,
Pnpm,
Bun,
}

impl PkgManager {
pub fn new_from_path(path: &path::Path) -> Self {
let yarn_lock = path.join("yarn.lock");
let pnpm_lock = path.join("pnpm-lock.yaml");
let package_lock = path.join("package-lock.json");
let bun_lock = path.join("bun.lockb");

if yarn_lock.exists() {
return PkgManager::Yarn;
}

if pnpm_lock.exists() {
return PkgManager::Pnpm;
}

if package_lock.exists() {
return PkgManager::Npm;
}

if bun_lock.exists() {
return PkgManager::Bun;
}

let package_json_path = path.join("package.json");
let package_json = std::fs::read_to_string(&package_json_path).unwrap();
let package_json: serde_json::Value = serde_json::from_str(&package_json).unwrap();
let package_manager = package_json
.get("packageManager")
.and_then(|v| v.as_str())
.unwrap_or("npm");

package_manager.parse().unwrap_or_default()
}

pub fn get_uninstall_cmd(&self) -> &'static str {
match self {
PkgManager::Npm => "npm uninstall",
PkgManager::Yarn => "yarn remove",
PkgManager::Pnpm => "pnpm remove",
PkgManager::Bun => "bun remove",
}
}
}

impl FromStr for PkgManager {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"npm" => Ok(PkgManager::Npm),
"yarn" => Ok(PkgManager::Yarn),
"pnpm" => Ok(PkgManager::Pnpm),
"bun" => Ok(PkgManager::Bun),
_ => Err(()),
}
}
}
Loading

0 comments on commit 22927c2

Please sign in to comment.