Skip to content

Commit

Permalink
cli: Add optional package-manager flag in init command to set pac…
Browse files Browse the repository at this point in the history
…kage manager field in Anchor.toml (#3328)

Co-authored-by: acheron <[email protected]>
  • Loading branch information
arihantbansal and acheroncrypto authored Oct 27, 2024
1 parent 522b326 commit d34c04a
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 22 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ The minor version will be incremented upon a breaking change and the patch versi
- cli: Add `--program-id` option to `idl convert` command ([#3309](https://github.com/coral-xyz/anchor/pull/3309)).
- lang: Generate documentation of constants in `declare_program!` ([#3311](https://github.com/coral-xyz/anchor/pull/3311)).
- cli: Add support for fetching legacy IDLs ([#3324](https://github.com/coral-xyz/anchor/pull/3324)).
- avm: Add short alias for `install` and `list` command ([#3326])(https://github.com/coral-xyz/anchor/pull/3326).
- avm: Add short alias for `install` and `list` commands ([#3326](https://github.com/coral-xyz/anchor/pull/3326)).
- avm: Add Windows support for renaming anchor binary ([#3325](https://github.com/coral-xyz/anchor/pull/3325)).
- cli: Add optional `package-manager` flag in `init` command to set package manager field in Anchor.toml ([#3328](https://github.com/coral-xyz/anchor/pull/3328)).

### Fixes

Expand Down
13 changes: 11 additions & 2 deletions cli/src/checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use anyhow::{anyhow, Result};
use semver::{Version, VersionReq};

use crate::{
config::{Config, Manifest, WithPath},
config::{Config, Manifest, PackageManager, WithPath},
VERSION,
};

Expand Down Expand Up @@ -69,12 +69,21 @@ pub fn check_anchor_version(cfg: &WithPath<Config>) -> Result<()> {
.and_then(|ver| VersionReq::parse(ver).ok())
.filter(|ver| !ver.matches(&cli_version));

let update_cmd = match &cfg.toolchain.package_manager {
Some(pkg_manager) => match pkg_manager {
PackageManager::NPM => "npm update",
PackageManager::Yarn => "yarn upgrade",
PackageManager::PNPM => "pnpm update",
},
None => "npm update",
};

if let Some(ver) = mismatched_ts_version {
eprintln!(
"WARNING: `@coral-xyz/anchor` version({ver}) and the current CLI version\
({cli_version}) don't match.\n\n\t\
This can lead to unwanted behavior. To fix, upgrade the package by running:\n\n\t\
yarn upgrade @coral-xyz/anchor@{cli_version}\n"
{update_cmd} @coral-xyz/anchor@{cli_version}\n"
);
}

Expand Down
25 changes: 25 additions & 0 deletions cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,31 @@ pub struct Config {
pub struct ToolchainConfig {
pub anchor_version: Option<String>,
pub solana_version: Option<String>,
pub package_manager: Option<PackageManager>,
}

/// Package manager to use for the project.
#[derive(Clone, Debug, Default, Eq, PartialEq, Parser, ValueEnum, Serialize, Deserialize)]
pub enum PackageManager {
/// Use npm as the package manager.
NPM,
/// Use yarn as the package manager.
#[default]
Yarn,
/// Use pnpm as the package manager.
PNPM,
}

impl std::fmt::Display for PackageManager {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let pkg_manager_str = match self {
PackageManager::NPM => "npm",
PackageManager::Yarn => "yarn",
PackageManager::PNPM => "pnpm",
};

write!(f, "{pkg_manager_str}")
}
}

#[derive(Clone, Debug, Serialize, Deserialize)]
Expand Down
41 changes: 32 additions & 9 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::config::{
get_default_ledger_path, AnchorPackage, BootstrapMode, BuildConfig, Config, ConfigOverride,
Manifest, ProgramArch, ProgramDeployment, ProgramWorkspace, ScriptsConfig, TestValidator,
WithPath, SHUTDOWN_WAIT, STARTUP_WAIT,
Manifest, PackageManager, ProgramArch, ProgramDeployment, ProgramWorkspace, ScriptsConfig,
TestValidator, WithPath, SHUTDOWN_WAIT, STARTUP_WAIT,
};
use anchor_client::Cluster;
use anchor_lang::idl::{IdlAccount, IdlInstruction, ERASED_AUTHORITY};
Expand Down Expand Up @@ -82,6 +82,9 @@ pub enum Command {
/// Don't install JavaScript dependencies
#[clap(long)]
no_install: bool,
/// Package Manager to use
#[clap(value_enum, long, default_value = "yarn")]
package_manager: PackageManager,
/// Don't initialize git
#[clap(long)]
no_git: bool,
Expand Down Expand Up @@ -756,6 +759,7 @@ fn process_command(opts: Opts) -> Result<()> {
javascript,
solidity,
no_install,
package_manager,
no_git,
template,
test_template,
Expand All @@ -766,6 +770,7 @@ fn process_command(opts: Opts) -> Result<()> {
javascript,
solidity,
no_install,
package_manager,
no_git,
template,
test_template,
Expand Down Expand Up @@ -952,6 +957,7 @@ fn init(
javascript: bool,
solidity: bool,
no_install: bool,
package_manager: PackageManager,
no_git: bool,
template: ProgramTemplate,
test_template: TestTemplate,
Expand Down Expand Up @@ -990,9 +996,12 @@ fn init(
fs::create_dir_all("app")?;

let mut cfg = Config::default();
let test_script = test_template.get_test_script(javascript);
cfg.scripts
.insert("test".to_owned(), test_script.to_owned());

let test_script = test_template.get_test_script(javascript, &package_manager);
cfg.scripts.insert("test".to_owned(), test_script);

let package_manager_cmd = package_manager.to_string();
cfg.toolchain.package_manager = Some(package_manager);

let mut localnet = BTreeMap::new();
let program_id = rust_template::get_or_create_program_id(&rust_name);
Expand Down Expand Up @@ -1064,10 +1073,16 @@ fn init(
)?;

if !no_install {
let yarn_result = install_node_modules("yarn")?;
if !yarn_result.status.success() {
println!("Failed yarn install will attempt to npm install");
let package_manager_result = install_node_modules(&package_manager_cmd)?;

if !package_manager_result.status.success() && package_manager_cmd != "npm" {
println!(
"Failed {} install will attempt to npm install",
package_manager_cmd
);
install_node_modules("npm")?;
} else {
eprintln!("Failed to install node modules");
}
}

Expand Down Expand Up @@ -4124,7 +4139,12 @@ fn migrate(cfg_override: &ConfigOverride) -> Result<()> {
rust_template::deploy_ts_script_host(&url, &module_path.display().to_string());
fs::write(deploy_ts, deploy_script_host_str)?;

std::process::Command::new("yarn")
let pkg_manager_cmd = match &cfg.toolchain.package_manager {
Some(pkg_manager) => pkg_manager.to_string(),
None => PackageManager::default().to_string(),
};

std::process::Command::new(pkg_manager_cmd)
.args([
"run",
"ts-node",
Expand Down Expand Up @@ -4812,6 +4832,7 @@ mod tests {
true,
false,
true,
PackageManager::default(),
false,
ProgramTemplate::default(),
TestTemplate::default(),
Expand All @@ -4832,6 +4853,7 @@ mod tests {
true,
false,
true,
PackageManager::default(),
false,
ProgramTemplate::default(),
TestTemplate::default(),
Expand All @@ -4852,6 +4874,7 @@ mod tests {
true,
false,
true,
PackageManager::default(),
false,
ProgramTemplate::default(),
TestTemplate::default(),
Expand Down
26 changes: 16 additions & 10 deletions cli/src/rust_template.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
config::ProgramWorkspace, create_files, override_or_create_files, solidity_template, Files,
VERSION,
PackageManager, VERSION,
};
use anyhow::Result;
use clap::{Parser, ValueEnum};
Expand Down Expand Up @@ -401,7 +401,7 @@ pub fn ts_package_json(jest: bool, license: String) -> String {
if jest {
format!(
r#"{{
"license": "{license}",
"license": "{license}",
"scripts": {{
"lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
"lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
Expand All @@ -423,7 +423,7 @@ pub fn ts_package_json(jest: bool, license: String) -> String {
} else {
format!(
r#"{{
"license": "{license}",
"license": "{license}",
"scripts": {{
"lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
"lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
Expand Down Expand Up @@ -607,30 +607,36 @@ pub enum TestTemplate {
/// Generate template for Mocha unit-test
#[default]
Mocha,
/// Generate template for Jest unit-test
/// Generate template for Jest unit-test
Jest,
/// Generate template for Rust unit-test
Rust,
}

impl TestTemplate {
pub fn get_test_script(&self, js: bool) -> &str {
pub fn get_test_script(&self, js: bool, pkg_manager: &PackageManager) -> String {
let pkg_manager_exec_cmd = match pkg_manager {
PackageManager::Yarn => "yarn run",
PackageManager::NPM => "npx",
PackageManager::PNPM => "pnpm exec",
};

match &self {
Self::Mocha => {
if js {
"yarn run mocha -t 1000000 tests/"
format!("{pkg_manager_exec_cmd} mocha -t 1000000 tests/")
} else {
"yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
format!("{pkg_manager_exec_cmd} ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts")
}
}
Self::Jest => {
if js {
"yarn run jest"
format!("{pkg_manager_exec_cmd} jest")
} else {
"yarn run jest --preset ts-jest"
format!("{pkg_manager_exec_cmd} jest --preset ts-jest")
}
}
Self::Rust => "cargo test",
Self::Rust => "cargo test".to_owned(),
}
}

Expand Down

0 comments on commit d34c04a

Please sign in to comment.