Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Add support for generating and initializing site projects #632

Merged
merged 9 commits into from
Sep 19, 2019
31 changes: 29 additions & 2 deletions src/commands/build/wranglerjs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod output;

use crate::commands::build::watch::wait_for_changes;
use crate::commands::build::watch::COOLDOWN_PERIOD;
use crate::commands::generate::run_generate;

use crate::commands::publish::package::Package;
use crate::install;
Expand Down Expand Up @@ -128,7 +129,12 @@ fn setup_build(target: &Target) -> Result<(Command, PathBuf, Bundle), failure::E
}

let build_dir = target.build_dir()?;
run_npm_install(&build_dir.to_path_buf()).expect("could not run `npm install`");

if target.site.is_some() {
scaffold_site_worker(&target)?;
}

run_npm_install(&build_dir).expect("could not run `npm install`");

let node = which::which("node").unwrap();
let mut command = Command::new(node);
Expand Down Expand Up @@ -166,7 +172,7 @@ fn setup_build(target: &Target) -> Result<(Command, PathBuf, Bundle), failure::E
if !bundle.has_webpack_config(&webpack_config_path) {
let package = Package::new(&build_dir)?;
let package_main = build_dir
.join(package.main()?)
.join(package.main(&build_dir)?)
.to_str()
.unwrap()
.to_string();
Expand All @@ -182,6 +188,27 @@ fn setup_build(target: &Target) -> Result<(Command, PathBuf, Bundle), failure::E
Ok((command, temp_file, bundle))
}

pub fn scaffold_site_worker(target: &Target) -> Result<(), failure::Error> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg this is still killing me. do we just go ahead with this?

let build_dir = target.build_dir()?;
// TODO: this is a placeholder template. Replace with The Real Thing on launch.
let template = "https://github.com/ashleymichal/glowing-palm-tree";

if !Path::new(&build_dir).exists() {
// TODO: use site.entry_point instead of build_dir explicitly.
run_generate(
build_dir.file_name().unwrap().to_str().unwrap(),
template,
&target.target_type,
)?;

// This step is to prevent having a git repo within a git repo after
// generating the scaffold into an existing project.
fs::remove_dir_all(&build_dir.join(".git"))?;
}

Ok(())
}

// Run {npm install} in the specified directory. Skips the install if a
// {node_modules} is found in the directory.
fn run_npm_install(dir: &PathBuf) -> Result<(), failure::Error> {
Expand Down
15 changes: 13 additions & 2 deletions src/commands/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,29 @@ pub fn generate(
name: &str,
template: &str,
target_type: Option<TargetType>,
site: bool,
) -> Result<(), failure::Error> {
let target_type = target_type.unwrap_or_else(|| get_target_type(template));
run_generate(name, template, &target_type)?;
let config_path = PathBuf::from("./").join(&name);
Manifest::generate(name.to_string(), target_type, config_path, site)?;
Ok(())
}

pub fn run_generate(
name: &str,
template: &str,
target_type: &TargetType,
) -> Result<(), failure::Error> {
let tool_name = "cargo-generate";
let binary_path = install::install(tool_name, "ashleygwilliams")?.binary(tool_name)?;

let args = ["generate", "--git", template, "--name", name, "--force"];

let target_type = target_type.unwrap_or_else(|| get_target_type(template));
let command = command(name, binary_path, &args, &target_type);
let command_name = format!("{:?}", command);

commands::run(command, &command_name)?;
Manifest::generate(name.to_string(), target_type, false)?;
Ok(())
}

Expand Down
19 changes: 16 additions & 3 deletions src/commands/init.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
use crate::commands;
use crate::settings::target::{Manifest, TargetType};
use crate::terminal::message;
use std::path::Path;
use std::path::{Path, PathBuf};

pub fn init(name: Option<&str>, target_type: Option<TargetType>) -> Result<(), failure::Error> {
pub fn init(
name: Option<&str>,
target_type: Option<TargetType>,
site: bool,
) -> Result<(), failure::Error> {
if Path::new("./wrangler.toml").exists() {
failure::bail!("A wrangler.toml file already exists! Please remove it before running this command again.");
}
let dirname = get_current_dirname()?;
let name = name.unwrap_or_else(|| &dirname);
let target_type = target_type.unwrap_or_default();
Manifest::generate(name.to_string(), target_type, true)?;
let config_path = PathBuf::from("./");
let manifest = Manifest::generate(name.to_string(), target_type, config_path, site)?;
message::success("Succesfully created a `wrangler.toml`");

if site {
let env = None;
let release = false;
let target = manifest.get_target(env, release)?;
commands::build::wranglerjs::scaffold_site_worker(&target)?;
}
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion src/commands/kv/bucket/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub fn upload_files(
}

// Add the popped key-value pair to the running batch of key-value pair uploads
key_count = key_count + 1;
key_count += 1;
key_pair_bytes = key_pair_bytes + pair.key.len() + pair.value.len();
key_value_batch.push(pair);
}
Expand Down
11 changes: 2 additions & 9 deletions src/commands/kv/namespace/site.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,10 @@ pub fn site(target: &Target, user: &GlobalUser) -> Result<WorkersKvNamespace, fa
});

match response {
Ok(success) => {
return Ok(success.result);
}
Ok(success) => Ok(success.result),
Err(e) => match e {
ApiFailure::Error(_status, api_errors) => {
if api_errors
.errors
.iter()
.find(|&e| e.code == 10014)
.is_some()
{
if api_errors.errors.iter().any(|e| e.code == 10014) {
log::info!("Namespace {} already exists.", title);
let response = client.request(&ListNamespaces {
account_identifier: &target.account_id,
Expand Down
15 changes: 7 additions & 8 deletions src/commands/publish/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use route::Route;

use upload_form::build_script_upload_form;

use log::info;
use std::path::Path;

use crate::commands;
Expand All @@ -29,7 +28,7 @@ pub fn publish(
push_worker: bool,
push_bucket: bool,
) -> Result<(), failure::Error> {
info!("workers_dev = {}", target.workers_dev);
log::info!("workers_dev = {}", target.workers_dev);

validate_target(target)?;

Expand Down Expand Up @@ -80,14 +79,14 @@ fn publish_script(user: &GlobalUser, target: &Target) -> Result<(), failure::Err
let pattern = if !target.workers_dev {
let route = Route::new(&target)?;
Route::publish(&user, &target, &route)?;
info!("publishing to route");
log::info!("publishing to route");
route.pattern
} else {
info!("publishing to subdomain");
log::info!("publishing to subdomain");
publish_to_subdomain(target, user)?
};

info!("{}", &pattern);
log::info!("{}", &pattern);
message::success(&format!(
"Successfully published your script to {}",
&pattern
Expand All @@ -100,7 +99,7 @@ fn upload_buckets(target: &Target, user: &GlobalUser) -> Result<(), failure::Err
for namespace in &target.kv_namespaces() {
if let Some(bucket) = &namespace.bucket {
let path = Path::new(&bucket);
kv::bucket::upload(target, user.to_owned(), &namespace.id, path, false)?;
kv::bucket::sync(target, user.to_owned(), &namespace.id, path, false)?;
}
}

Expand All @@ -112,7 +111,7 @@ fn build_subdomain_request() -> String {
}

fn publish_to_subdomain(target: &Target, user: &GlobalUser) -> Result<String, failure::Error> {
info!("checking that subdomain is registered");
log::info!("checking that subdomain is registered");
let subdomain = Subdomain::get(&target.account_id, user)?;

let sd_worker_addr = format!(
Expand All @@ -122,7 +121,7 @@ fn publish_to_subdomain(target: &Target, user: &GlobalUser) -> Result<String, fa

let client = http::auth_client(user);

info!("Making public on subdomain...");
log::info!("Making public on subdomain...");
let mut res = client
.post(&sd_worker_addr)
.header("Content-type", "application/json")
Expand Down
6 changes: 3 additions & 3 deletions src/commands/publish/package.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fs;
use std::path::{Path, PathBuf};
use std::path::PathBuf;

use serde::{self, Deserialize};

Expand All @@ -9,12 +9,12 @@ pub struct Package {
main: String,
}
impl Package {
pub fn main(&self) -> Result<String, failure::Error> {
pub fn main(&self, build_dir: &PathBuf) -> Result<String, failure::Error> {
if self.main == "" {
failure::bail!(
"The `main` key in your `package.json` file is required; please specified the entrypoint of your Worker.",
)
} else if !Path::new(&self.main).exists() {
} else if !build_dir.join(&self.main).exists() {
failure::bail!(
"The entrypoint of your Worker ({}) could not be found.",
self.main
Expand Down
2 changes: 1 addition & 1 deletion src/commands/publish/upload_form/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn build_script_upload_form(target: &Target) -> Result<Form, failure::Error>
let build_dir = target.build_dir()?;
let package = Package::new(&build_dir)?;

let script_path = package.main()?;
let script_path = package.main(&build_dir)?;

let assets = ProjectAssets::new(script_path, Vec::new(), kv_namespaces)?;

Expand Down
71 changes: 54 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ fn run() -> Result<(), failure::Error> {
.about("List all namespaces on your Cloudflare account")
)
)
.subcommand(SubCommand::with_name("kv:key")
.subcommand(
SubCommand::with_name("kv:key")
.about(&*format!(
"{} Individually manage Workers KV key-value pairs",
emoji::KEY
Expand Down Expand Up @@ -319,6 +320,13 @@ fn run() -> Result<(), failure::Error> {
.long("type")
.takes_value(true)
.help("the type of project you want generated"),
)
.arg(
Arg::with_name("site")
.short("s")
.long("site")
.takes_value(false)
.help("initializes a Workers Sites project. Overrides `type` and `template`"),
),
)
.subcommand(
Expand All @@ -338,6 +346,13 @@ fn run() -> Result<(), failure::Error> {
.long("type")
.takes_value(true)
.help("the type of project you want generated"),
)
.arg(
Arg::with_name("site")
.short("s")
.long("site")
.takes_value(false)
.help("initializes a Workers Sites project. Overrides `type` and `template`"),
),
)
.subcommand(
Expand Down Expand Up @@ -455,32 +470,54 @@ fn run() -> Result<(), failure::Error> {
commands::global_config(email, api_key)?;
} else if let Some(matches) = matches.subcommand_matches("generate") {
let name = matches.value_of("name").unwrap_or("worker");
let target_type = match matches.value_of("type") {
Some(s) => Some(TargetType::from_str(&s.to_lowercase())?),
None => None,
};
let site = matches.is_present("site");

let default_template = "https://github.com/cloudflare/worker-template";
let template = matches.value_of("template").unwrap_or(match target_type {
Some(ref pt) => match pt {
TargetType::Rust => "https://github.com/cloudflare/rustwasm-worker-template",
let (target_type, template) = if site {
// Workers Sites projects are always Webpack for now
let target_type = Some(TargetType::Webpack);
// template = "https://github.com/cloudflare/worker-sites-template";
// TODO: this is a placeholder template. Replace with The Real Thing (^) on launch.
let template = "https://github.com/ashleymichal/scaling-succotash";

(target_type, template)
} else {
let target_type = match matches.value_of("type") {
Some(s) => Some(TargetType::from_str(&s.to_lowercase())?),
None => None,
};

let default_template = "https://github.com/cloudflare/worker-template";
let template = matches.value_of("template").unwrap_or(match target_type {
Some(ref pt) => match pt {
TargetType::Rust => "https://github.com/cloudflare/rustwasm-worker-template",
_ => default_template,
},
_ => default_template,
},
_ => default_template,
});
});

(target_type, template)
};

info!(
"Generate command called with template {}, and name {}",
template, name
);
commands::generate(name, template, target_type)?;

commands::generate(name, template, target_type, site)?;
} else if let Some(matches) = matches.subcommand_matches("init") {
let name = matches.value_of("name");
let target_type = match matches.value_of("type") {
Some(s) => Some(settings::target::TargetType::from_str(&s.to_lowercase())?),
None => None,
let site = matches.is_present("site");
let target_type = if site {
// Workers Sites projects are always Webpack for now
Some(TargetType::Webpack)
} else {
match matches.value_of("type") {
Some(s) => Some(settings::target::TargetType::from_str(&s.to_lowercase())?),
None => None,
}
};
commands::init(name, target_type)?;

commands::init(name, target_type, site)?;
} else if let Some(matches) = matches.subcommand_matches("build") {
info!("Getting project settings");
let manifest = settings::target::Manifest::new(config_path)?;
Expand Down
Loading