summaryrefslogtreecommitdiff
path: root/cli/args/package_json.rs
blob: eedd0a1941949c06d8af8ef2151f67ac8cdaeb0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use std::path::PathBuf;
use std::sync::Arc;

use deno_config::workspace::Workspace;
use deno_package_json::PackageJsonDepValue;
use deno_semver::package::PackageReq;

#[derive(Debug)]
pub struct InstallNpmRemotePkg {
  pub alias: String,
  // todo(24419): use this when setting up the node_modules dir
  #[allow(dead_code)]
  pub base_dir: PathBuf,
  pub req: PackageReq,
}

#[derive(Debug)]
pub struct InstallNpmWorkspacePkg {
  pub alias: String,
  // todo(24419): use this when setting up the node_modules dir
  #[allow(dead_code)]
  pub base_dir: PathBuf,
  pub target_dir: PathBuf,
}

#[derive(Debug, Default)]
pub struct PackageJsonInstallDepsProvider {
  remote_pkgs: Vec<InstallNpmRemotePkg>,
  workspace_pkgs: Vec<InstallNpmWorkspacePkg>,
}

impl PackageJsonInstallDepsProvider {
  pub fn empty() -> Self {
    Self::default()
  }

  pub fn from_workspace(workspace: &Arc<Workspace>) -> Self {
    let mut workspace_pkgs = Vec::new();
    let mut remote_pkgs = Vec::new();
    let workspace_npm_pkgs = workspace.npm_packages();
    for pkg_json in workspace.package_jsons() {
      let deps = pkg_json.resolve_local_package_json_deps();
      let mut pkg_pkgs = Vec::with_capacity(deps.len());
      for (alias, dep) in deps {
        let Ok(dep) = dep else {
          continue;
        };
        match dep {
          PackageJsonDepValue::Req(pkg_req) => {
            let workspace_pkg = workspace_npm_pkgs.iter().find(|pkg| {
              pkg.matches_req(&pkg_req)
              // do not resolve to the current package
              && pkg.pkg_json.path != pkg_json.path
            });

            if let Some(pkg) = workspace_pkg {
              workspace_pkgs.push(InstallNpmWorkspacePkg {
                alias,
                base_dir: pkg_json.dir_path().to_path_buf(),
                target_dir: pkg.pkg_json.dir_path().to_path_buf(),
              });
            } else {
              pkg_pkgs.push(InstallNpmRemotePkg {
                alias,
                base_dir: pkg_json.dir_path().to_path_buf(),
                req: pkg_req,
              });
            }
          }
          PackageJsonDepValue::Workspace(version_req) => {
            if let Some(pkg) = workspace_npm_pkgs.iter().find(|pkg| {
              pkg.matches_name_and_version_req(&alias, &version_req)
            }) {
              workspace_pkgs.push(InstallNpmWorkspacePkg {
                alias,
                base_dir: pkg_json.dir_path().to_path_buf(),
                target_dir: pkg.pkg_json.dir_path().to_path_buf(),
              });
            }
          }
        }
      }
      // sort within each package
      pkg_pkgs.sort_by(|a, b| a.alias.cmp(&b.alias));

      remote_pkgs.extend(pkg_pkgs);
    }
    remote_pkgs.shrink_to_fit();
    workspace_pkgs.shrink_to_fit();
    Self {
      remote_pkgs,
      workspace_pkgs,
    }
  }

  pub fn remote_pkgs(&self) -> &Vec<InstallNpmRemotePkg> {
    &self.remote_pkgs
  }

  pub fn workspace_pkgs(&self) -> &Vec<InstallNpmWorkspacePkg> {
    &self.workspace_pkgs
  }
}