Skip to content
This repository has been archived by the owner on Jan 7, 2025. It is now read-only.

Commit

Permalink
new: Add a Nx migration extension. (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
milesj authored Feb 23, 2024
1 parent f50674c commit d48725f
Show file tree
Hide file tree
Showing 56 changed files with 2,547 additions and 647 deletions.
416 changes: 220 additions & 196 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ resolver = "2"
members = ["crates/*"]

[workspace.dependencies]
extism-pdk = "1.0.1"
moon_common = "0.0.2"
moon_config = "0.0.2"
moon_pdk = "0.0.2"
moon_pdk_test_utils = "0.0.2"
moon_target = "0.0.1"
extism-pdk = "1.1.0"
moon_common = "0.0.3"
moon_config = "0.0.4"
moon_pdk = "0.0.4"
moon_pdk_test_utils = "0.0.5"
moon_target = "0.0.2"
rustc-hash = "1.1.0"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
serde_yaml = "0.9.31"
starbase_utils = { version = "0.4.2", default-features = false }
starbase_sandbox = "0.3.0"
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"
serde_yaml = "0.9.32"
starbase_utils = { version = "0.5.0", default-features = false }
starbase_sandbox = "0.4.0"

# moon_common = { path = "../moon/nextgen/common" }
# moon_config = { path = "../moon/nextgen/config" }
Expand Down
3 changes: 3 additions & 0 deletions crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ publish = false

[dependencies]
extism-pdk = { workspace = true }
moon_common = { workspace = true }
moon_config = { workspace = true }
moon_pdk = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true }
starbase_utils = { workspace = true, features = ["yaml"] }
3 changes: 2 additions & 1 deletion crates/common/src/download.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::format_virtual_path;
use extism_pdk::debug;
use moon_pdk::{fetch_url_bytes, AnyResult, VirtualPath};
use std::fs;
Expand All @@ -24,7 +25,7 @@ pub fn download_from_url<U: AsRef<str>, P: AsRef<VirtualPath>>(
fs::create_dir_all(dir)?;
fs::write(&file, bytes)?;

debug!("Downloaded to <path>{}</path>", file.real_path().display());
debug!("Downloaded to <path>{}</path>", format_virtual_path(&file));

Ok(file)
}
14 changes: 12 additions & 2 deletions crates/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
pub mod download;
pub mod migrator;
pub mod project_graph;

pub fn map_miette_error(error: impl std::fmt::Display) -> extism_pdk::Error {
moon_pdk::anyhow!("{error}")
use moon_pdk::VirtualPath;
use std::borrow::Cow;

pub fn format_virtual_path(path: &VirtualPath) -> Cow<'_, str> {
if let Some(real) = path.real_path() {
Cow::Owned(real.to_string_lossy().into_owned())
} else if let Some(rel) = path.without_prefix() {
rel.to_string_lossy()
} else {
path.virtual_path().to_string_lossy()
}
}
140 changes: 140 additions & 0 deletions crates/common/src/migrator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
use moon_common::Id;
use moon_config::{
LanguageType, PartialInheritedTasksConfig, PartialProjectConfig, PartialWorkspaceConfig,
PlatformType,
};
use moon_pdk::{AnyResult, VirtualPath};
use rustc_hash::FxHashMap;
use starbase_utils::yaml;

pub struct Migrator {
pub platform: PlatformType,
pub project_configs: FxHashMap<VirtualPath, PartialProjectConfig>,
pub root: VirtualPath,
pub tasks_configs: FxHashMap<VirtualPath, PartialInheritedTasksConfig>,
pub workspace_config: Option<PartialWorkspaceConfig>,
pub workspace_config_path: VirtualPath,
}

impl Migrator {
pub fn new(workspace_root: &VirtualPath) -> AnyResult<Self> {
Ok(Self {
platform: PlatformType::Node,
project_configs: FxHashMap::default(),
tasks_configs: FxHashMap::default(),
workspace_config: None,
workspace_config_path: workspace_root.join(".moon/workspace.yml"),
root: workspace_root.to_owned(),
})
}

pub fn detect_package_manager(&self) -> String {
let mut package_manager = "npm";

if self.root.join("bun.lockb").exists() || matches!(self.platform, PlatformType::Bun) {
package_manager = "bun";
} else if self.root.join("pnpm-lock.yaml").exists() {
package_manager = "pnpm";
} else if self.root.join("yarn.lock").exists() {
package_manager = "yarn";
}

package_manager.to_owned()
}

pub fn load_project_config(
&mut self,
project_source: &str,
) -> AnyResult<&mut PartialProjectConfig> {
let project_config_path = self.root.join(project_source).join("moon.yml");

if !self.project_configs.contains_key(&project_config_path) {
if project_config_path.exists() {
self.project_configs.insert(
project_config_path.clone(),
yaml::read_file(&project_config_path)?,
);
} else {
self.project_configs.insert(
project_config_path.clone(),
PartialProjectConfig {
language: Some(
if self
.root
.join(project_source)
.join("tsconfig.json")
.exists()
{
LanguageType::TypeScript
} else {
LanguageType::JavaScript
},
),
platform: Some(self.platform),
..PartialProjectConfig::default()
},
);
}
}

Ok(self.project_configs.get_mut(&project_config_path).unwrap())
}

pub fn load_tasks_config(
&mut self,
scope: &str,
) -> AnyResult<&mut PartialInheritedTasksConfig> {
let tasks_config_path = self.root.join(".moon/tasks").join(format!("{scope}.yml"));

if !self.tasks_configs.contains_key(&tasks_config_path) {
self.tasks_configs.insert(
tasks_config_path.clone(),
if tasks_config_path.exists() {
yaml::read_file(&tasks_config_path)?
} else {
PartialInheritedTasksConfig::default()
},
);
}

Ok(self.tasks_configs.get_mut(&tasks_config_path).unwrap())
}

pub fn load_tasks_platform_config(&mut self) -> AnyResult<&mut PartialInheritedTasksConfig> {
let platform = self.platform.to_string();

self.load_tasks_config(&platform)
}

pub fn load_workspace_config(&mut self) -> AnyResult<&mut PartialWorkspaceConfig> {
if self.workspace_config.is_none() {
if self.workspace_config_path.exists() {
self.workspace_config = Some(yaml::read_file(&self.workspace_config_path)?);
} else {
self.workspace_config = Some(PartialWorkspaceConfig::default());
}
}

Ok(self.workspace_config.as_mut().unwrap())
}

pub fn save_configs(&self) -> AnyResult<()> {
if let Some(workspace_config) = &self.workspace_config {
yaml::write_file(&self.workspace_config_path, workspace_config)?;
}

for (tasks_config_path, tasks_config) in &self.tasks_configs {
yaml::write_file(tasks_config_path, tasks_config)?;
}

for (project_config_path, project_config) in &self.project_configs {
yaml::write_file(project_config_path, project_config)?;
}

Ok(())
}
}

pub fn create_id<T: AsRef<str>>(id: T) -> AnyResult<Id> {
Ok(Id::clean(id.as_ref().replace(':', "."))?)
}
7 changes: 4 additions & 3 deletions crates/download/src/download_ext.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use extism_pdk::*;
use moon_extension_common::download::download_from_url;
use moon_extension_common::format_virtual_path;
use moon_pdk::*;

#[host_fn]
Expand Down Expand Up @@ -41,13 +42,13 @@ pub fn execute_extension(Json(input): Json<ExecuteExtensionInput>) -> FnResult<(
if dest_dir.exists() && dest_dir.is_file() {
return Err(plugin_err!(
"Destination <path>{}</path> must be a directory, found a file.",
dest_dir.real_path().display(),
format_virtual_path(&dest_dir),
));
}

debug!(
"Destination <path>{}</path> will be used",
dest_dir.real_path().display(),
format_virtual_path(&dest_dir),
);

// Attempt to download the file
Expand All @@ -58,7 +59,7 @@ pub fn execute_extension(Json(input): Json<ExecuteExtensionInput>) -> FnResult<(
host_log!(
stdout,
"Downloaded to <path>{}</path>",
dest_file.real_path().display()
format_virtual_path(&dest_file),
);

Ok(())
Expand Down
5 changes: 5 additions & 0 deletions crates/migrate-nx/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Unreleased

#### 🚀 Updates

- Initial release!
33 changes: 33 additions & 0 deletions crates/migrate-nx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "moon_migrate_nx_extension"
version = "0.0.0"
edition = "2021"
license = "MIT"
publish = false

[lib]
crate-type = ['cdylib']

[package.metadata.release]
pre-release-replacements = [
{ file = "./CHANGELOG.md", search = "Unreleased", replace = "{{version}}" },
]

[dependencies]
moon_extension_common = { path = "../common" }
extism-pdk = { workspace = true }
moon_common = { workspace = true }
moon_config = { workspace = true }
moon_pdk = { workspace = true }
moon_target = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true }
starbase_utils = { workspace = true, features = ["json", "yaml"] }

[dev-dependencies]
moon_pdk_test_utils = { workspace = true }
starbase_sandbox = { workspace = true }

[features]
default = ["wasm"]
wasm = []
8 changes: 8 additions & 0 deletions crates/migrate-nx/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "wasm")]
mod migrate_nx;
mod nx_json;
mod nx_migrator;
mod nx_project_json;

#[cfg(feature = "wasm")]
pub use migrate_nx::*;
96 changes: 96 additions & 0 deletions crates/migrate-nx/src/migrate_nx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use crate::nx_migrator::NxMigrator;
use extism_pdk::*;
use moon_pdk::*;
use starbase_utils::{fs, glob, json};

#[host_fn]
extern "ExtismHost" {
fn host_log(input: Json<HostLogInput>);
}

#[derive(Args)]
pub struct MigrateNxExtensionArgs {
#[arg(long)]
pub bun: bool,
}

#[plugin_fn]
pub fn execute_extension(Json(input): Json<ExecuteExtensionInput>) -> FnResult<()> {
let args = parse_args::<MigrateNxExtensionArgs>(&input.args)?;
let workspace_root = &input.context.workspace_root;
let mut migrator = NxMigrator::new(&input.context, args.bun)?;

// Migrate the workspace config first, so we can handle projects
let workspace_config_path = workspace_root.join("workspace.json");

if workspace_config_path.exists() {
host_log!(
stdout,
"Migrating workspace config <file>workspace.json</file>",
);

migrator.migrate_workspace_config(json::read_file(&workspace_config_path)?)?;

fs::remove(workspace_config_path)?;
}

// Then the root nx config second, to handle project defaults
let root_config_path = workspace_root.join("nx.json");

if root_config_path.exists() {
host_log!(stdout, "Migrating root config <file>nx.json</file>",);

migrator.migrate_root_config(json::read_file(&root_config_path)?)?;

fs::remove(root_config_path)?;
}

// And lastly, all project configs (and package.json to)
for project_config_path in glob::walk_files(
workspace_root,
[
"**/*/package.json",
"**/*/project.json",
"!**/node_modules/**/*",
// The globstar above won't find the root files for some reason...
"package.json",
"project.json",
],
)? {
let rel_config_path = project_config_path.strip_prefix(workspace_root).unwrap();
let project_source = rel_config_path.parent().unwrap().to_string_lossy();

host_log!(
stdout,
"Migrating project config <file>{}</file>",
rel_config_path.display()
);

if project_config_path
.file_name()
.is_some_and(|name| name == "package.json")
{
migrator.migrate_project_package_config(
&project_source,
json::read_file(&project_config_path)?,
)?;

// Don't delete package.json
} else {
migrator
.migrate_project_config(&project_source, json::read_file(&project_config_path)?)?;

fs::remove(project_config_path)?;
}
}

// Fill in any missing but required settings
migrator.use_default_settings()?;

// Write the new config files
migrator.inner.save_configs()?;

host_log!(stdout, "Successfully migrated from Nx to moon!");

Ok(())
}
Loading

0 comments on commit d48725f

Please sign in to comment.