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

modules modules modules #312

Merged
merged 13 commits into from
Sep 20, 2018
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
143 changes: 76 additions & 67 deletions src/manifest.rs → src/manifest/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Reading and writing Cargo.toml and package.json manifests.

mod npm;

use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

use self::npm::{repository::Repository, CommonJSPackage, ESModulesPackage, NpmPackage};
use console::style;
use emoji;
use error::Error;
Expand Down Expand Up @@ -57,6 +60,27 @@ struct CargoPackage {
repository: Option<String>,
}

impl CargoPackage {
fn check_optional_fields(&self) {
let warn_fmt = |field| {
format!(
"Field '{}' is missing from Cargo.toml. It is not necessary, but recommended",
field
)
};

if self.description.is_none() {
PBAR.warn(&warn_fmt("description"));
}
if self.repository.is_none() {
PBAR.warn(&warn_fmt("repository"));
}
if self.license.is_none() {
PBAR.warn(&warn_fmt("license"));
}
}
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum CargoDependency {
Expand All @@ -75,32 +99,6 @@ struct CargoLib {
crate_type: Option<Vec<String>>,
}

#[derive(Serialize)]
struct NpmPackage {
name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
collaborators: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
version: String,
#[serde(skip_serializing_if = "Option::is_none")]
license: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
repository: Option<Repository>,
#[serde(skip_serializing_if = "Vec::is_empty")]
files: Vec<String>,
main: String,
#[serde(skip_serializing_if = "Option::is_none")]
types: Option<String>,
}

#[derive(Serialize)]
struct Repository {
#[serde(rename = "type")]
ty: String,
url: String,
}

fn read_cargo_toml(path: &Path) -> Result<CargoManifest, Error> {
let manifest_path = path.join("Cargo.toml");
if !manifest_path.is_file() {
Expand All @@ -120,43 +118,66 @@ fn read_cargo_toml(path: &Path) -> Result<CargoManifest, Error> {
}

impl CargoManifest {
fn into_npm(mut self, scope: &Option<String>, disable_dts: bool, target: &str) -> NpmPackage {
fn into_commonjs(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
let filename = self.package.name.replace("-", "_");
let wasm_file = format!("{}_bg.wasm", filename);
let js_file = format!("{}.js", filename);
let mut files = vec![wasm_file];

let dts_file = if disable_dts == true {
None
let js_bg_file = format!("{}_bg.js", filename);
files.push(js_bg_file.to_string());

if let Some(s) = scope {
self.package.name = format!("@{}/{}", s, self.package.name);
}

let dts_file = if disable_dts == false {
let file = format!("{}.d.ts", filename);
files.push(file.to_string());
Some(file)
} else {
Some(format!("{}.d.ts", filename))
None
};

let js_bg_file = if target == "nodejs" {
Some(format!("{}_bg.js", filename))
&self.package.check_optional_fields();

NpmPackage::CommonJSPackage(CommonJSPackage {
name: self.package.name,
collaborators: self.package.authors,
description: self.package.description,
version: self.package.version,
license: self.package.license,
repository: self.package.repository.map(|repo_url| Repository {
ty: "git".to_string(),
url: repo_url,
}),
files: files,
main: js_file,
types: dts_file,
})
}

fn into_esmodules(mut self, scope: &Option<String>, disable_dts: bool) -> NpmPackage {
let filename = self.package.name.replace("-", "_");
let wasm_file = format!("{}_bg.wasm", filename);
let js_file = format!("{}.js", filename);
let mut files = vec![wasm_file, js_file.clone()];

let dts_file = if disable_dts == false {
let file = format!("{}.d.ts", filename);
files.push(file.to_string());
Some(file)
} else {
None
};

if let Some(s) = scope {
self.package.name = format!("@{}/{}", s, self.package.name);
}
let mut files = vec![wasm_file];

match dts_file {
Some(ref dts_file) => {
files.push(dts_file.to_string());
}
None => {}
}

match js_bg_file {
Some(ref js_bg_file) => {
files.push(js_bg_file.to_string());
}
None => {}
}
&self.package.check_optional_fields();

NpmPackage {
NpmPackage::ESModulesPackage(ESModulesPackage {
name: self.package.name,
collaborators: self.package.authors,
description: self.package.description,
Expand All @@ -167,9 +188,10 @@ impl CargoManifest {
url: repo_url,
}),
files: files,
main: js_file,
module: js_file,
types: dts_file,
}
side_effects: "false".to_string(),
})
}
}

Expand All @@ -184,28 +206,15 @@ pub fn write_package_json(
) -> Result<(), Error> {
let msg = format!("{}Writing a package.json...", emoji::MEMO);

let warn_fmt = |field| {
format!(
"Field '{}' is missing from Cargo.toml. It is not necessary, but recommended",
field
)
};

PBAR.step(step, &msg);
let pkg_file_path = out_dir.join("package.json");
let mut pkg_file = File::create(pkg_file_path)?;
let crate_data = read_cargo_toml(path)?;
let npm_data = crate_data.into_npm(scope, disable_dts, target);

if npm_data.description.is_none() {
PBAR.warn(&warn_fmt("description"));
}
if npm_data.repository.is_none() {
PBAR.warn(&warn_fmt("repository"));
}
if npm_data.license.is_none() {
PBAR.warn(&warn_fmt("license"));
}
let npm_data = if target == "nodejs" {
crate_data.into_commonjs(scope, disable_dts)
} else {
crate_data.into_esmodules(scope, disable_dts)
};

let npm_json = serde_json::to_string_pretty(&npm_data)?;
pkg_file.write_all(npm_json.as_bytes())?;
Expand Down
20 changes: 20 additions & 0 deletions src/manifest/npm/commonjs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use manifest::npm::repository::Repository;

#[derive(Serialize)]
pub struct CommonJSPackage {
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub collaborators: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub repository: Option<Repository>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub files: Vec<String>,
pub main: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub types: Option<String>,
}
22 changes: 22 additions & 0 deletions src/manifest/npm/esmodules.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use manifest::npm::repository::Repository;

#[derive(Serialize)]
pub struct ESModulesPackage {
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub collaborators: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
pub version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub license: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub repository: Option<Repository>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub files: Vec<String>,
pub module: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub types: Option<String>,
#[serde(rename = "sideEffects")]
pub side_effects: String,
}
13 changes: 13 additions & 0 deletions src/manifest/npm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod commonjs;
mod esmodules;
pub mod repository;

pub use self::commonjs::CommonJSPackage;
pub use self::esmodules::ESModulesPackage;

#[derive(Serialize)]
#[serde(untagged)]
pub enum NpmPackage {
CommonJSPackage(CommonJSPackage),
ESModulesPackage(ESModulesPackage),
}
6 changes: 6 additions & 0 deletions src/manifest/npm/repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[derive(Serialize)]
pub struct Repository {
#[serde(rename = "type")]
pub ty: String,
pub url: String,
}
44 changes: 19 additions & 25 deletions tests/all/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ fn it_creates_a_package_json_default_path() {
pkg.repository.url,
"https://github.com/ashleygwilliams/wasm-pack.git"
);
assert_eq!(pkg.main, "wasm_pack.js");
let types = pkg.types.unwrap_or_default();
assert_eq!(types, "wasm_pack.d.ts");
assert_eq!(pkg.module, "wasm_pack.js");
assert_eq!(pkg.types, "wasm_pack.d.ts");
assert_eq!(pkg.side_effects, "false");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> = ["wasm_pack_bg.wasm", "wasm_pack.d.ts"]
let expected_files: HashSet<String> = ["wasm_pack_bg.wasm", "wasm_pack.d.ts", "wasm_pack.js"]
.iter()
.map(|&s| String::from(s))
.collect();
Expand All @@ -92,10 +92,14 @@ fn it_creates_a_package_json_provided_path() {
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok());
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
assert_eq!(pkg.name, "js-hello-world");
assert_eq!(pkg.main, "js_hello_world.js");
assert_eq!(pkg.module, "js_hello_world.js");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> = ["js_hello_world_bg.wasm", "js_hello_world.d.ts"]
let expected_files: HashSet<String> = [
"js_hello_world_bg.wasm",
"js_hello_world.d.ts",
"js_hello_world.js",
]
.iter()
.map(|&s| String::from(s))
.collect();
Expand Down Expand Up @@ -123,10 +127,14 @@ fn it_creates_a_package_json_provided_path_with_scope() {
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok());
let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
assert_eq!(pkg.name, "@test/scopes-hello-world");
assert_eq!(pkg.main, "scopes_hello_world.js");
assert_eq!(pkg.module, "scopes_hello_world.js");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> = ["scopes_hello_world_bg.wasm", "scopes_hello_world.d.ts"]
let expected_files: HashSet<String> = [
"scopes_hello_world_bg.wasm",
"scopes_hello_world.d.ts",
"scopes_hello_world.js",
]
.iter()
.map(|&s| String::from(s))
.collect();
Expand Down Expand Up @@ -154,8 +162,7 @@ fn it_creates_a_pkg_json_with_correct_files_on_node() {
"https://github.com/ashleygwilliams/wasm-pack.git"
);
assert_eq!(pkg.main, "wasm_pack.js");
let types = pkg.types.unwrap_or_default();
assert_eq!(types, "wasm_pack.d.ts");
assert_eq!(pkg.types, "wasm_pack.d.ts");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> =
Expand All @@ -177,19 +184,6 @@ fn it_creates_a_pkg_json_in_out_dir() {
let package_json_path = &fixture.path.join(&out_dir).join("package.json");
assert!(fs::metadata(package_json_path).is_ok());
assert!(utils::manifest::read_package_json(&fixture.path, &out_dir).is_ok());

let pkg = utils::manifest::read_package_json(&fixture.path, &out_dir).unwrap();
assert_eq!(pkg.name, "js-hello-world");
assert_eq!(pkg.main, "js_hello_world.js");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();

let expected_files: HashSet<String> = ["js_hello_world_bg.wasm", "js_hello_world.d.ts"]
.iter()
.map(|&s| String::from(s))
.collect();

assert_eq!(actual_files, expected_files);
}

#[test]
Expand All @@ -209,10 +203,10 @@ fn it_creates_a_package_json_with_correct_keys_when_types_are_skipped() {
pkg.repository.url,
"https://github.com/ashleygwilliams/wasm-pack.git"
);
assert_eq!(pkg.main, "wasm_pack.js");
assert_eq!(pkg.module, "wasm_pack.js");

let actual_files: HashSet<String> = pkg.files.into_iter().collect();
let expected_files: HashSet<String> = ["wasm_pack_bg.wasm"]
let expected_files: HashSet<String> = ["wasm_pack_bg.wasm", "wasm_pack.js"]
.iter()
.map(|&s| String::from(s))
.collect();
Expand Down
12 changes: 11 additions & 1 deletion tests/all/utils/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ pub struct NpmPackage {
pub license: String,
pub repository: Repository,
pub files: Vec<String>,
#[serde(default = "default_none")]
pub main: String,
pub types: Option<String>,
#[serde(default = "default_none")]
pub module: String,
#[serde(default = "default_none")]
pub types: String,
#[serde(default = "default_none", rename = "sideEffects")]
pub side_effects: String,
}

fn default_none() -> String {
"".to_string()
}

#[derive(Deserialize)]
Expand Down