From 5532253744bf73c450b28954e990fda22331cbba Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 14:47:15 -0500 Subject: [PATCH 01/63] hotreload demo some refactoring/code cleanup work added session id to message --- src/commands/publish/preview/mod.rs | 123 ++++++++++++++++++++++------ src/main.rs | 16 +++- 2 files changed, 114 insertions(+), 25 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 72ec8c5dd..20c57b4d6 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -3,9 +3,11 @@ use std::process::Command; mod http_method; pub use http_method::HTTPMethod; +use crate::cache::get_wrangler_cache; +use crate::commands::build; use crate::commands::publish; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::commands; @@ -13,37 +15,23 @@ use crate::http; use crate::settings::project::Project; use crate::terminal::message; -#[derive(Debug, Deserialize)] -struct Preview { - pub id: String, -} +use notify::{RecommendedWatcher, RecursiveMode, Watcher}; +use std::sync::mpsc::channel; +use std::thread; +use std::time::Duration; +use ws::WebSocket; pub fn preview( project: &Project, method: Result, body: Option, + livereload: bool, ) -> Result<(), failure::Error> { - let create_address = "https://cloudflareworkers.com/script"; - - let client = http::client(); - - commands::build(&project)?; - - let script_upload_form = publish::build_script_upload_form(project)?; - - let res = client - .post(create_address) - .multipart(script_upload_form) - .send()? - .error_for_status(); - - let p: Preview = serde_json::from_str(&res?.text()?)?; - let session = Uuid::new_v4().to_simple(); let preview_host = "example.com"; let https = 1; - let script_id = &p.id; + let script_id = &upload_and_get_id()?; let preview_address = "https://00000000000000000000000000000000.cloudflareworkers.com"; let cookie = format!( @@ -53,15 +41,23 @@ pub fn preview( let method = method.unwrap_or_default(); + let client = http::client(); let worker_res = match method { HTTPMethod::Get => get(preview_address, cookie, client)?, HTTPMethod::Post => post(preview_address, cookie, client, body)?, }; + let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); open(preview_host, https, script_id)?; + if livereload { + watch_for_changes(session.to_string())?; + } else { + println!("👷‍♀️ Your worker responded with: {}", worker_res); + } + Ok(()) } @@ -74,7 +70,11 @@ fn open(preview_host: &str, https: u8, script_id: &str) -> Result<(), failure::E }; let browser_preview = format!( - "https://cloudflareworkers.com/#{}:{}{}", + //TODO this relies on a local version of the fiddle-ui for testing livereload + //maybe we can mock out the preview service url to a config file for when we do similar + //things like this in the future + //for now, hardcoded url :))))))) + "http://localhost:3000/src/test/manual/#{}:{}{}", script_id, https_str, preview_host ); let windows_cmd = format!("start {}", browser_preview); @@ -121,3 +121,80 @@ fn post( message::preview(&msg); Ok(res?.text()?) } + +//for now, this is only used by livereloading. +//in the future we may use this websocket for other things +//so support other message types +#[derive(Debug, Serialize)] +enum FiddleMessage { + LiveReload { session: String, id: String }, +} + +fn watch_for_changes(session: String) -> Result<(), failure::Error> { + let (tx, rx) = channel(); + + let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?; + //TODO supporting more complex setups is blocked by https://github.com/cloudflare/wrangler/issues/251 + watcher.watch("./index.js", RecursiveMode::Recursive)?; + + //start up the websocket server. + //needs a bs handler factory closure, even though we never respond + let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind("localhost:8025")?; + let broadcaster = server.broadcaster(); + thread::spawn(move || server.run()); + + while let Ok(_e) = rx.recv() { + println!("Detected a file change, building now..."); + + let cache = get_wrangler_cache()?; + match build(&cache, &get_project_config()?.project_type) { + Ok(_) => println!("Build succeded, uploading bundle..."), + Err(_) => println!("Build failed"), + } + + if let Ok(id) = upload_and_get_id() { + let msg = FiddleMessage::LiveReload { + session: session.clone(), + id, + }; + + match broadcaster.send(serde_json::to_string(&msg)?) { + Ok(_) => println!("Sent new id to preview!"), + Err(_e) => println!("communication with preview failed"), + } + } + } + + broadcaster.shutdown()?; + + Ok(()) +} + +#[derive(Debug, Deserialize)] +struct Preview { + pub id: String, +} + +fn upload_and_get_id() -> Result { + let create_address = "https://cloudflareworkers.com/script"; + let client = http::client(); + + let res = match get_project_config()?.project_type { + ProjectType::Rust => client + .post(create_address) + .multipart(publish::build_multipart_script()?) + .send(), + ProjectType::JavaScript => client + .post(create_address) + .body(publish::build_js_script()?) + .send(), + ProjectType::Webpack => client + .post(create_address) + .multipart(publish::build_webpack_form()?) + .send(), + }; + + let p: Preview = serde_json::from_str(&res?.text()?)?; + + Ok(p.id) +} diff --git a/src/main.rs b/src/main.rs index 8e0e39ce9..8b4813da0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -111,7 +111,13 @@ fn run() -> Result<(), failure::Error> { Arg::with_name("body") .help("Body string to post to your preview worker request") .index(2), - ), + ) + .arg( + Arg::with_name("livereload") + .help("watch your project for changes and update the preview automagically") + .long("livereload") + .takes_value(false), + ) ) .subcommand( SubCommand::with_name("publish").about(&*format!( @@ -201,7 +207,13 @@ fn run() -> Result<(), failure::Error> { None => None, }; - commands::preview(&project, method, body)?; + let livereload = match matches.occurrences_of("livereload") { + 1 => true, + _ => false, + }; + + commands::build(&project)?; + commands::preview(&project, method, body, livereload)?; } else if matches.subcommand_matches("whoami").is_some() { info!("Getting User settings"); let user = settings::global_user::GlobalUser::new()?; From 24104df92d475f7898d30455040719adeeb5f5a1 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 14 Jun 2019 15:07:11 -0500 Subject: [PATCH 02/63] changed to use old script id instead of sessions watch_paths added to wrangler.toml --- src/commands/publish/preview/mod.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 20c57b4d6..afb0ca468 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -127,14 +127,16 @@ fn post( //so support other message types #[derive(Debug, Serialize)] enum FiddleMessage { - LiveReload { session: String, id: String }, + LiveReload { old_id: String, new_id: String }, } -fn watch_for_changes(session: String) -> Result<(), failure::Error> { +fn watch_for_changes( + original_id: String, +) -> Result<(), failure::Error> { let (tx, rx) = channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?; - //TODO supporting more complex setups is blocked by https://github.com/cloudflare/wrangler/issues/251 + watcher.watch("./index.js", RecursiveMode::Recursive)?; //start up the websocket server. @@ -143,6 +145,8 @@ fn watch_for_changes(session: String) -> Result<(), failure::Error> { let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); + let mut old_id = original_id; + while let Ok(_e) = rx.recv() { println!("Detected a file change, building now..."); @@ -152,14 +156,17 @@ fn watch_for_changes(session: String) -> Result<(), failure::Error> { Err(_) => println!("Build failed"), } - if let Ok(id) = upload_and_get_id() { + if let Ok(new_id) = upload_and_get_id() { let msg = FiddleMessage::LiveReload { - session: session.clone(), - id, + old_id: old_id.clone(), + new_id: new_id.clone(), }; match broadcaster.send(serde_json::to_string(&msg)?) { - Ok(_) => println!("Sent new id to preview!"), + Ok(_) => { + println!("Sent new id to preview!"); + old_id = new_id; + } Err(_e) => println!("communication with preview failed"), } } From 008d5782d5ff54877cf547c7af983d417358ceb7 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 21 Jun 2019 13:30:58 -0500 Subject: [PATCH 03/63] added watch option to wranglerjs --- wranglerjs/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wranglerjs/index.js b/wranglerjs/index.js index 0a52250de..ce2877cfb 100644 --- a/wranglerjs/index.js +++ b/wranglerjs/index.js @@ -65,7 +65,7 @@ fetchCompileWasmTemplatePlugin.fn = function(compilation) { plugin.apply(mainTemplate); }; -compiler.run((err, stats) => { +const compilerCallback = (err, stats) => { if (err) { throw err; } @@ -92,4 +92,10 @@ compiler.run((err, stats) => { } writeFileSync(args["output-file"], JSON.stringify(bundle)); -}); +}; + +if (args["watch"] === "1") { + compiler.watch(fullConfig.watchOptions, compilerCallback); +} else { + compiler.run(compilerCallback); +} From 85f9f5d89d651b3f155b92d9429aacc71f50a321 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 15:40:25 -0500 Subject: [PATCH 04/63] add support for running wranglerjs in watch mode, utilizing webpack's watcher --- src/commands/build/mod.rs | 1 + src/commands/build/wranglerjs/mod.rs | 46 ++++++++++++++++++++++++++-- src/commands/publish/preview/mod.rs | 42 ++++++++++++++++--------- src/main.rs | 8 ++--- 4 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 9747c894a..788901eff 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -1,4 +1,5 @@ pub mod wranglerjs; +pub mod watch; use crate::settings::project::{Project, ProjectType}; use crate::{commands, install}; diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index d259b83ad..818562c61 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -17,9 +17,14 @@ use std::path::{Path, PathBuf}; use std::process::Command; use crate::settings::project::Project; - use crate::terminal::message; +use std::time::Duration; +use std::sync::mpsc::{channel, Sender}; +use std::thread; +use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode}; + + // Run the underlying {wranglerjs} executable. // // In Rust we create a virtual file, pass the pass to {wranglerjs}, run the @@ -62,6 +67,38 @@ pub fn run_build(project: &Project) -> Result<(), failure::Error> { } } +pub fn run_build_watch( + tx: Sender, +) -> Result<(), failure::Error> { + let (command, temp_file) = setup_command(true)?; + + info!("Running {:?}", command); + + //start wranglerjs in a new thread + let status = command.spawn()?; + + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; + + watcher.watch(temp_file, RecursiveMode::Recursive)?; + + thread::spawn(move || { + loop { + if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + println!("got new bundle from wranglerjs"); + let output = fs::read_to_string(temp_file.clone()).expect("could not retrieve ouput"); + fs::remove_file(temp_file); + + if let Ok(output) = serde_json::from_str(&output) { + tx.send(output); + } + } + } + }); + + Ok(()) +} + //setup a build to run wranglerjs, return the command, the ipc temp file, and the bundle fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure::Error> { for tool in &["node", "npm"] { @@ -86,8 +123,8 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: File::create(temp_file.clone())?; command.arg(format!( - "--output-file={}", - temp_file.clone().to_str().unwrap().to_string() + "--output-file={:?}", + ipc_temp_file_path, )); let bundle = Bundle::new(); @@ -121,9 +158,12 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: )); } + command.arg("--watch={:?}", watch); + Ok((command, temp_file, bundle)) } + // 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> { diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index afb0ca468..d3763e29f 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -30,7 +30,7 @@ pub fn preview( let session = Uuid::new_v4().to_simple(); let preview_host = "example.com"; - let https = 1; + let https = true; let script_id = &upload_and_get_id()?; let preview_address = "https://00000000000000000000000000000000.cloudflareworkers.com"; @@ -61,13 +61,8 @@ pub fn preview( Ok(()) } -fn open(preview_host: &str, https: u8, script_id: &str) -> Result<(), failure::Error> { - let https_str = match https { - 1 => "https://", - 0 => "http://", - // hrm. - _ => "", - }; +fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error> { + let https_str = if https { "https://" } else { "http://" }; let browser_preview = format!( //TODO this relies on a local version of the fiddle-ui for testing livereload @@ -134,10 +129,23 @@ fn watch_for_changes( original_id: String, ) -> Result<(), failure::Error> { let (tx, rx) = channel(); + let project_type = &get_project_config()?.project_type; let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?; - watcher.watch("./index.js", RecursiveMode::Recursive)?; + match project_type { + ProjectType::JavaScript => { + //watch entry point in package.json + }, + ProjectType::Rust => { + //watch "src/" + }, + ProjectType::Webpack => { + //watch "src/" + //watch "dist/" + //start webpack in watch mode + }, + } //start up the websocket server. //needs a bs handler factory closure, even though we never respond @@ -148,12 +156,16 @@ fn watch_for_changes( let mut old_id = original_id; while let Ok(_e) = rx.recv() { - println!("Detected a file change, building now..."); - - let cache = get_wrangler_cache()?; - match build(&cache, &get_project_config()?.project_type) { - Ok(_) => println!("Build succeded, uploading bundle..."), - Err(_) => println!("Build failed"), + match project_type { + Webpack => println!("Detected new bundle, uploading now..."), + FileNotifier => { + println!("Detected file change, building now..."); + let cache = get_wrangler_cache()?; + match build(&cache, &get_project_config()?.project_type) { + Ok(_) => println!("Build succeded, uploading bundle..."), + Err(_) => println!("Build failed"), + } + }, } if let Ok(new_id) = upload_and_get_id() { diff --git a/src/main.rs b/src/main.rs index 8b4813da0..d7d15e921 100644 --- a/src/main.rs +++ b/src/main.rs @@ -113,9 +113,9 @@ fn run() -> Result<(), failure::Error> { .index(2), ) .arg( - Arg::with_name("livereload") + Arg::with_name("watch") .help("watch your project for changes and update the preview automagically") - .long("livereload") + .long("watch") .takes_value(false), ) ) @@ -207,13 +207,13 @@ fn run() -> Result<(), failure::Error> { None => None, }; - let livereload = match matches.occurrences_of("livereload") { + let watch = match matches.occurrences_of("watch") { 1 => true, _ => false, }; commands::build(&project)?; - commands::preview(&project, method, body, livereload)?; + commands::preview(&project, method, body, watch)?; } else if matches.subcommand_matches("whoami").is_some() { info!("Getting User settings"); let user = settings::global_user::GlobalUser::new()?; From 2b630e39c91e23bbc83aa96c49b4c2c6b3908c34 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 15:41:18 -0500 Subject: [PATCH 05/63] remove watch module + refs --- src/commands/build/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 788901eff..9747c894a 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -1,5 +1,4 @@ pub mod wranglerjs; -pub mod watch; use crate::settings::project::{Project, ProjectType}; use crate::{commands, install}; From c4af49bee5905c15a11880f2c4733f37b7d760aa Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 2 Jul 2019 18:41:47 -0500 Subject: [PATCH 06/63] check for debug flag to use localhost for preview server --- src/commands/build/wranglerjs/mod.rs | 31 ++++++++++------------------ src/commands/publish/preview/mod.rs | 31 ++++++++++++++-------------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 818562c61..f827f3442 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -19,11 +19,10 @@ use std::process::Command; use crate::settings::project::Project; use crate::terminal::message; -use std::time::Duration; +use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; use std::sync::mpsc::{channel, Sender}; use std::thread; -use notify::{Watcher, watcher, DebouncedEvent, RecursiveMode}; - +use std::time::Duration; // Run the underlying {wranglerjs} executable. // @@ -67,9 +66,7 @@ pub fn run_build(project: &Project) -> Result<(), failure::Error> { } } -pub fn run_build_watch( - tx: Sender, -) -> Result<(), failure::Error> { +pub fn run_build_watch(tx: Sender) -> Result<(), failure::Error> { let (command, temp_file) = setup_command(true)?; info!("Running {:?}", command); @@ -82,16 +79,14 @@ pub fn run_build_watch( watcher.watch(temp_file, RecursiveMode::Recursive)?; - thread::spawn(move || { - loop { - if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { - println!("got new bundle from wranglerjs"); - let output = fs::read_to_string(temp_file.clone()).expect("could not retrieve ouput"); - fs::remove_file(temp_file); + thread::spawn(move || loop { + if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + println!("got new bundle from wranglerjs"); + let output = fs::read_to_string(temp_file.clone()).expect("could not retrieve ouput"); + fs::remove_file(temp_file); - if let Ok(output) = serde_json::from_str(&output) { - tx.send(output); - } + if let Ok(output) = serde_json::from_str(&output) { + tx.send(output); } } }); @@ -122,10 +117,7 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: temp_file.push(format!(".wranglerjs_output{}", random_chars(5))); File::create(temp_file.clone())?; - command.arg(format!( - "--output-file={:?}", - ipc_temp_file_path, - )); + command.arg(format!("--output-file={:?}", ipc_temp_file_path,)); let bundle = Bundle::new(); @@ -163,7 +155,6 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: Ok((command, temp_file, bundle)) } - // 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> { diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index d3763e29f..bc846ea1a 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -64,14 +64,17 @@ pub fn preview( fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error> { let https_str = if https { "https://" } else { "http://" }; - let browser_preview = format!( - //TODO this relies on a local version of the fiddle-ui for testing livereload - //maybe we can mock out the preview service url to a config file for when we do similar - //things like this in the future - //for now, hardcoded url :))))))) - "http://localhost:3000/src/test/manual/#{}:{}{}", - script_id, https_str, preview_host - ); + let browser_preview = if install::target::DEBUG { + format!( + "http://localhost:3000/src/test/manual/#{}:{}{}", + script_id, https_str, preview_host + ) + } else { + format!( + "https://cloudflareworkers.com/#{}:{}{}", + script_id, https_str, preview_host + ) + }; let windows_cmd = format!("start {}", browser_preview); let mac_cmd = format!("open {}", browser_preview); let linux_cmd = format!("xdg-open {}", browser_preview); @@ -125,9 +128,7 @@ enum FiddleMessage { LiveReload { old_id: String, new_id: String }, } -fn watch_for_changes( - original_id: String, -) -> Result<(), failure::Error> { +fn watch_for_changes(original_id: String) -> Result<(), failure::Error> { let (tx, rx) = channel(); let project_type = &get_project_config()?.project_type; @@ -136,15 +137,15 @@ fn watch_for_changes( match project_type { ProjectType::JavaScript => { //watch entry point in package.json - }, + } ProjectType::Rust => { //watch "src/" - }, + } ProjectType::Webpack => { //watch "src/" //watch "dist/" //start webpack in watch mode - }, + } } //start up the websocket server. @@ -165,7 +166,7 @@ fn watch_for_changes( Ok(_) => println!("Build succeded, uploading bundle..."), Err(_) => println!("Build failed"), } - }, + } } if let Ok(new_id) = upload_and_get_id() { From 3115f9805aa920c76a4277421b14addcb856ad2e Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 14:53:03 -0500 Subject: [PATCH 07/63] added deps --- Cargo.lock | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 + 2 files changed, 227 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9dd1c1afc..e1c997a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,7 +106,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "is_executable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -124,11 +124,35 @@ dependencies = [ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.3.2" @@ -371,6 +395,14 @@ name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dirs" version = "1.0.5" @@ -464,15 +496,19 @@ dependencies = [ "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "filetime" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -518,6 +554,23 @@ name = "fs_extra" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fsevent" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -551,6 +604,14 @@ dependencies = [ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "h2" version = "0.1.23" @@ -658,11 +719,39 @@ dependencies = [ "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "inotify" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inotify-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.2" @@ -704,6 +793,11 @@ name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazycell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.58" @@ -848,6 +942,17 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-extras" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" version = "0.2.1" @@ -900,6 +1005,24 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "notify" +version = "4.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.1.43" @@ -934,6 +1057,11 @@ name = "numtoa" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" version = "0.10.23" @@ -1032,6 +1160,11 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "percent-encoding" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "phf" version = "0.7.24" @@ -1344,6 +1477,14 @@ name = "ryu" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "same-file" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "schannel" version = "0.1.15" @@ -1464,6 +1605,17 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.2.3" @@ -1531,10 +1683,10 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.26" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "filetime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1777,6 +1929,11 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.3" @@ -1834,6 +1991,16 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "url" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "1.0.3" @@ -1862,6 +2029,16 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "walkdir" +version = "2.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "want" version = "0.0.6" @@ -1947,6 +2124,7 @@ dependencies = [ "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1957,6 +2135,24 @@ dependencies = [ "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ws" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2011,7 +2207,10 @@ dependencies = [ "checksum binary-install 0.0.3-alpha (registry+https://github.com/rust-lang/crates.io-index)" = "a81dda17f2dbba8271cf61f2ea3e48e3da8aef31665731bce48818cc07863f06" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" @@ -2037,6 +2236,7 @@ dependencies = [ "checksum curl 0.4.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f8ed9a22aa8c4e49ac0c896279ef532a43a7df2f54fcd19fa36960de029f965f" "checksum curl-sys 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "9d91a0052d5b982887d8e829bee0faffc7218ea3c6ebd3d6c2c8f678a93c9a42" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" @@ -2048,18 +2248,22 @@ dependencies = [ "checksum exitfailure 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ff5bd832af37f366c6c194d813a11cd90ac484f124f079294f28e357ae40515" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum filetime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "450537dc346f0c4d738dda31e790da1da5d4bd12145aad4da0d03d713cb3794f" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" "checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" +"checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +"checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "1e42e3daed5a7e17b12a0c23b5b2fbff23a925a570938ebee4baca1a9a1a2240" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" @@ -2069,13 +2273,17 @@ dependencies = [ "checksum hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)" = "40e7692b2009a70b1e9b362284add4d8b75880fefddb4acaa5e67194e843f219" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" +"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum is_executable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "302d553b8abc8187beb7d663e34c065ac4570b273bc9511a50e940e99409c577" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" "checksum libflate 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "76912aa0196b6f0e06d9c43ee877be45369157c06172ade12fe20ac3ee5ffa15" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" @@ -2093,16 +2301,19 @@ dependencies = [ "checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" "checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" +"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum number_prefix 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-src 111.3.0+1.1.1c (registry+https://github.com/rust-lang/crates.io-index)" = "53ed5f31d294bdf5f7a4ba0a206c2754b0f60e9a63b7e3076babc5317873c797" @@ -2113,6 +2324,7 @@ dependencies = [ "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba4f28a6faf4ffea762ba8f4baef48c61a6db348647c73095034041fc79dd954" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" @@ -2148,6 +2360,7 @@ dependencies = [ "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -2163,6 +2376,7 @@ dependencies = [ "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" @@ -2172,7 +2386,7 @@ dependencies = [ "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)" = "8b4f551a91e2e3848aeef8751d0d4eec9489b6474c720fd4c55958d8d31a430c" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum tar 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "b3196bfbffbba3e57481b6ea32249fbaf590396a52505a2615adbb79d9d826d3" +"checksum tar 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7201214ded95b34e3bc00c9557b6dcec34fd1af428d343143f5db67c661762f0" "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" @@ -2197,6 +2411,7 @@ dependencies = [ "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" @@ -2205,11 +2420,13 @@ dependencies = [ "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum url 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77ddaf52e65c6b81c56b7e957c0b1970f7937f21c5c6774c4e56fcb4e20b48c6" "checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum which 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" @@ -2219,6 +2436,7 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum ws 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6f5bb86663ff4d1639408410f50bf6050367a8525d644d49a6894cd618a631" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index 981e3ac7f..0ae24b1b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,8 @@ base64 = "0.10.1" lazy_static = "1.3.0" text_io = "0.1.7" exitfailure = "0.5.1" +notify = "4.0.12" +ws = "0.9.0" [dev-dependencies] assert_cmd = "0.11.1" From b73f85cdd23d0fb6aadc2f361a20281b372b7944 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 14:56:13 -0500 Subject: [PATCH 08/63] add build_and_watch --- src/commands/build/mod.rs | 55 ++++++++++++++++++++++++ src/commands/build/wranglerjs/mod.rs | 38 +++++++++++++---- src/commands/mod.rs | 1 + src/commands/publish/mod.rs | 2 +- src/commands/publish/preview/mod.rs | 62 ++++++++++------------------ src/main.rs | 14 +++++-- 6 files changed, 121 insertions(+), 51 deletions(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 9747c894a..9313b467a 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -1,5 +1,6 @@ pub mod wranglerjs; +use crate::commands::publish::Package; use crate::settings::project::{Project, ProjectType}; use crate::{commands, install}; use std::path::PathBuf; @@ -7,6 +8,11 @@ use std::process::Command; use crate::terminal::message; +use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; +use std::sync::mpsc::{channel, Sender}; +use std::thread; +use std::time::Duration; + pub fn build(project: &Project) -> Result<(), failure::Error> { let project_type = &project.project_type; match project_type { @@ -31,6 +37,55 @@ pub fn build(project: &Project) -> Result<(), failure::Error> { Ok(()) } +pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), failure::Error> { + let project_type = &project.project_type; + match project_type { + ProjectType::JavaScript => { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; + + let package = Package::new("./")?; + watcher.watch(package.main()?, RecursiveMode::Recursive)?; + + thread::spawn(move || loop { + if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + if let Some(tx) = tx { + tx.send(()); + } + } + }); + } + ProjectType::Rust => { + let tool_name = "wasm-pack"; + let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; + let args = ["build", "--target", "no-modules"]; + + let command = command(&args, binary_path); + let command_name = format!("{:?}", command); + + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; + + watcher.watch("./src", RecursiveMode::Recursive)?; + + thread::spawn(move || loop { + if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + if let Ok(_) = commands::run(command, &command_name) { + if let Some(tx) = tx { + tx.send(()); + } + } + } + }); + } + ProjectType::Webpack => { + wranglerjs::run_build_and_watch(project, tx)?; + } + } + + Ok(()) +} + fn command(args: &[&str], binary_path: PathBuf) -> Command { message::working("Compiling your project to WebAssembly..."); diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index f827f3442..c1b008078 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -66,8 +66,12 @@ pub fn run_build(project: &Project) -> Result<(), failure::Error> { } } -pub fn run_build_watch(tx: Sender) -> Result<(), failure::Error> { - let (command, temp_file) = setup_command(true)?; +pub fn run_build_and_watch( + project: &Project, + tx: Option>, +) -> Result<(), failure::Error> { + let (mut command, temp_file, bundle) = setup_build(project)?; + command.arg("--watch=1"); info!("Running {:?}", command); @@ -85,8 +89,27 @@ pub fn run_build_watch(tx: Sender) -> Result<(), failure::Erro let output = fs::read_to_string(temp_file.clone()).expect("could not retrieve ouput"); fs::remove_file(temp_file); - if let Ok(output) = serde_json::from_str(&output) { - tx.send(output); + let wranglerjs_output: WranglerjsOutput = + serde_json::from_str(&output).expect("could not parse wranglerjs output"); + + if wranglerjs_output.has_errors() { + message::user_error(&format!("{}", wranglerjs_output.get_errors())); + } else { + bundle + .write(&wranglerjs_output) + .expect("could not write bundle to disk"); + + let mut msg = format!( + "Built successfully, script size is {}", + wranglerjs_output.script_size() + ); + if bundle.has_wasm() { + msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); + } + + if let Some(tx) = tx { + tx.send(()); + } } } }); @@ -117,7 +140,10 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: temp_file.push(format!(".wranglerjs_output{}", random_chars(5))); File::create(temp_file.clone())?; - command.arg(format!("--output-file={:?}", ipc_temp_file_path,)); + command.arg(format!( + "--output-file={:?}", + temp_file.clone().to_str().unwrap().to_string() + )); let bundle = Bundle::new(); @@ -150,8 +176,6 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: )); } - command.arg("--watch={:?}", watch); - Ok((command, temp_file, bundle)) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index fae41f154..4f249c679 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -12,6 +12,7 @@ pub mod whoami; pub use self::config::global_config; pub use build::build; +pub use build::build_and_watch; pub use generate::generate; pub use init::init; pub use publish::preview::preview; diff --git a/src/commands/publish/mod.rs b/src/commands/publish/mod.rs index 6dab662b9..fa1023ee2 100644 --- a/src/commands/publish/mod.rs +++ b/src/commands/publish/mod.rs @@ -4,7 +4,7 @@ pub mod preview; mod route; mod upload_form; -use package::Package; +pub use package::Package; use route::Route; use upload_form::build_script_upload_form; diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index bc846ea1a..dfa920d36 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -3,8 +3,8 @@ use std::process::Command; mod http_method; pub use http_method::HTTPMethod; -use crate::cache::get_wrangler_cache; use crate::commands::build; +use crate::commands::build_and_watch; use crate::commands::publish; use serde::{Deserialize, Serialize}; @@ -12,13 +12,17 @@ use uuid::Uuid; use crate::commands; use crate::http; +<<<<<<< HEAD use crate::settings::project::Project; +======= +use crate::install; +use crate::settings::project::get_project_config; +use crate::settings::project::{Project, ProjectType}; +>>>>>>> c35288a... add build_and_watch use crate::terminal::message; -use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use std::sync::mpsc::channel; use std::thread; -use std::time::Duration; use ws::WebSocket; pub fn preview( @@ -27,6 +31,8 @@ pub fn preview( body: Option, livereload: bool, ) -> Result<(), failure::Error> { + build(&project)?; //do the initial build + let session = Uuid::new_v4().to_simple(); let preview_host = "example.com"; @@ -50,7 +56,7 @@ pub fn preview( let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); - open(preview_host, https, script_id)?; + open(preview_host, https, script_id, &session.to_string())?; if livereload { watch_for_changes(session.to_string())?; @@ -61,18 +67,23 @@ pub fn preview( Ok(()) } -fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error> { +fn open( + preview_host: &str, + https: bool, + script_id: &str, + session_id: &str, +) -> Result<(), failure::Error> { let https_str = if https { "https://" } else { "http://" }; let browser_preview = if install::target::DEBUG { format!( - "http://localhost:3000/src/test/manual/#{}:{}{}", - script_id, https_str, preview_host + "http://localhost:3000/src/test/manual/#{}:{}{}?session_id={}&noeditor=true", + script_id, https_str, preview_host, session_id ) } else { format!( - "https://cloudflareworkers.com/#{}:{}{}", - script_id, https_str, preview_host + "https://cloudflareworkers.com/#{}:{}{}?session_id={}&noeditor=true", + script_id, https_str, preview_host, session_id ) }; let windows_cmd = format!("start {}", browser_preview); @@ -129,25 +140,6 @@ enum FiddleMessage { } fn watch_for_changes(original_id: String) -> Result<(), failure::Error> { - let (tx, rx) = channel(); - let project_type = &get_project_config()?.project_type; - - let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?; - - match project_type { - ProjectType::JavaScript => { - //watch entry point in package.json - } - ProjectType::Rust => { - //watch "src/" - } - ProjectType::Webpack => { - //watch "src/" - //watch "dist/" - //start webpack in watch mode - } - } - //start up the websocket server. //needs a bs handler factory closure, even though we never respond let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind("localhost:8025")?; @@ -155,20 +147,10 @@ fn watch_for_changes(original_id: String) -> Result<(), failure::Error> { thread::spawn(move || server.run()); let mut old_id = original_id; + let (tx, rx) = channel(); + build_and_watch(&get_project_config()?, Some(tx)); while let Ok(_e) = rx.recv() { - match project_type { - Webpack => println!("Detected new bundle, uploading now..."), - FileNotifier => { - println!("Detected file change, building now..."); - let cache = get_wrangler_cache()?; - match build(&cache, &get_project_config()?.project_type) { - Ok(_) => println!("Build succeded, uploading bundle..."), - Err(_) => println!("Build failed"), - } - } - } - if let Ok(new_id) = upload_and_get_id() { let msg = FiddleMessage::LiveReload { old_id: old_id.clone(), diff --git a/src/main.rs b/src/main.rs index d7d15e921..8ebcb560b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,8 +93,13 @@ fn run() -> Result<(), failure::Error> { .about(&*format!( "{} Build your worker", emoji::CRAB - ) - ), + )) + .arg( + Arg::with_name("watch") + .help("watch your project for changes and build your worker when they happen") + .long("watch") + .takes_value(false), + ), ) .subcommand( SubCommand::with_name("preview") @@ -195,7 +200,10 @@ fn run() -> Result<(), failure::Error> { } else if matches.subcommand_matches("build").is_some() { info!("Getting project settings"); let project = settings::project::Project::new()?; - commands::build(&project)?; + match matches.occurrences_of("watch") { + 1 => commands::build(&project)?, + _ => commands::build_and_watch(&project, None)?, + }; } else if let Some(matches) = matches.subcommand_matches("preview") { info!("Getting project settings"); let project = settings::project::Project::new()?; From 994a177b8654da6bfdedb2900f85f80337b6ba9d Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 2 Jul 2019 19:47:40 -0500 Subject: [PATCH 09/63] please the borrow checker --- src/commands/build/mod.rs | 16 ++++++++-------- src/commands/build/wranglerjs/mod.rs | 9 ++++----- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 9313b467a..e35e51c92 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -24,7 +24,7 @@ pub fn build(project: &Project) -> Result<(), failure::Error> { let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; let args = ["build", "--target", "no-modules"]; - let command = command(&args, binary_path); + let command = command(&args, &binary_path); let command_name = format!("{:?}", command); commands::run(command, &command_name)?; @@ -48,8 +48,8 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), watcher.watch(package.main()?, RecursiveMode::Recursive)?; thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { - if let Some(tx) = tx { + if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { + if let Some(tx) = tx.clone() { tx.send(()); } } @@ -60,8 +60,6 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; let args = ["build", "--target", "no-modules"]; - let command = command(&args, binary_path); - let command_name = format!("{:?}", command); let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; @@ -69,9 +67,11 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), watcher.watch("./src", RecursiveMode::Recursive)?; thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { + let command = command(&args, &binary_path); + let command_name = format!("{:?}", command); if let Ok(_) = commands::run(command, &command_name) { - if let Some(tx) = tx { + if let Some(tx) = tx.clone() { tx.send(()); } } @@ -86,7 +86,7 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), Ok(()) } -fn command(args: &[&str], binary_path: PathBuf) -> Command { +fn command(args: &[&str], binary_path: &PathBuf) -> Command { message::working("Compiling your project to WebAssembly..."); let mut c = if cfg!(target_os = "windows") { diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index c1b008078..13cd5b1c9 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -76,18 +76,17 @@ pub fn run_build_and_watch( info!("Running {:?}", command); //start wranglerjs in a new thread - let status = command.spawn()?; + command.spawn()?; let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; - watcher.watch(temp_file, RecursiveMode::Recursive)?; + watcher.watch(&temp_file, RecursiveMode::Recursive)?; thread::spawn(move || loop { if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { println!("got new bundle from wranglerjs"); - let output = fs::read_to_string(temp_file.clone()).expect("could not retrieve ouput"); - fs::remove_file(temp_file); + let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); let wranglerjs_output: WranglerjsOutput = serde_json::from_str(&output).expect("could not parse wranglerjs output"); @@ -107,7 +106,7 @@ pub fn run_build_and_watch( msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); } - if let Some(tx) = tx { + if let Some(tx) = tx.clone() { tx.send(()); } } From cd9129dffff80385ab2fb12ed1feb5bc1dd109b6 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 2 Jul 2019 19:52:25 -0500 Subject: [PATCH 10/63] cleanup --- src/commands/build/mod.rs | 5 ++--- src/commands/build/wranglerjs/mod.rs | 6 ++++-- src/commands/publish/preview/mod.rs | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index e35e51c92..514d10f34 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -50,7 +50,7 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), thread::spawn(move || loop { if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { if let Some(tx) = tx.clone() { - tx.send(()); + let _ = tx.send(()); } } }); @@ -60,7 +60,6 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; let args = ["build", "--target", "no-modules"]; - let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; @@ -72,7 +71,7 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), let command_name = format!("{:?}", command); if let Ok(_) = commands::run(command, &command_name) { if let Some(tx) = tx.clone() { - tx.send(()); + let _ = tx.send(()); } } } diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 13cd5b1c9..6e4c3c9f0 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -84,7 +84,7 @@ pub fn run_build_and_watch( watcher.watch(&temp_file, RecursiveMode::Recursive)?; thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(path)) = watcher_rx.recv() { + if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { println!("got new bundle from wranglerjs"); let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); @@ -106,8 +106,10 @@ pub fn run_build_and_watch( msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); } + message::success(&msg); + if let Some(tx) = tx.clone() { - tx.send(()); + let _ = tx.send(()); } } } diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index dfa920d36..9321d9345 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -10,7 +10,6 @@ use crate::commands::publish; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::commands; use crate::http; <<<<<<< HEAD use crate::settings::project::Project; @@ -148,7 +147,7 @@ fn watch_for_changes(original_id: String) -> Result<(), failure::Error> { let mut old_id = original_id; let (tx, rx) = channel(); - build_and_watch(&get_project_config()?, Some(tx)); + build_and_watch(&get_project_config()?, Some(tx))?; while let Ok(_e) = rx.recv() { if let Ok(new_id) = upload_and_get_id() { From eb6fed671a87d9a69959109c44ac96971135f479 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 2 Jul 2019 19:54:25 -0500 Subject: [PATCH 11/63] fix temp file --- src/commands/build/wranglerjs/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 6e4c3c9f0..5fa8f9276 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -142,7 +142,7 @@ fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure: File::create(temp_file.clone())?; command.arg(format!( - "--output-file={:?}", + "--output-file={}", temp_file.clone().to_str().unwrap().to_string() )); From 5777d1a4f7334f667d68022e3bb732c7f8465038 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 14:59:27 -0500 Subject: [PATCH 12/63] webpack watching works -- code is littered with debug statements and leaves threads open, need to fix that --- src/commands/build/wranglerjs/mod.rs | 75 ++++++++++++++++------------ wranglerjs/index.js | 52 +++++++++++-------- 2 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 5fa8f9276..18d947616 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -76,44 +76,53 @@ pub fn run_build_and_watch( info!("Running {:?}", command); //start wranglerjs in a new thread - command.spawn()?; - - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; - - watcher.watch(&temp_file, RecursiveMode::Recursive)?; - - thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { - println!("got new bundle from wranglerjs"); - let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); - - let wranglerjs_output: WranglerjsOutput = - serde_json::from_str(&output).expect("could not parse wranglerjs output"); - - if wranglerjs_output.has_errors() { - message::user_error(&format!("{}", wranglerjs_output.get_errors())); - } else { - bundle - .write(&wranglerjs_output) - .expect("could not write bundle to disk"); - - let mut msg = format!( - "Built successfully, script size is {}", - wranglerjs_output.script_size() - ); - if bundle.has_wasm() { - msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); - } + let command_handle = command.spawn()?; + + println!("getting watcher ready"); + + let builder = thread::Builder::new().name("handler".into()); + + let handle = builder.spawn(move || { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + + watcher.watch(&temp_file, RecursiveMode::Recursive).unwrap(); + + println!("watching {:?}", &temp_file); + + loop { + let event = watcher_rx.recv(); + if let Ok(DebouncedEvent::Write(_)) = event { + println!("got new bundle from wranglerjs"); + let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); + + let wranglerjs_output: WranglerjsOutput = + serde_json::from_str(&output).expect("could not parse wranglerjs output"); + + if wranglerjs_output.has_errors() { + message::user_error(&format!("{}", wranglerjs_output.get_errors())); + } else { + bundle + .write(&wranglerjs_output) + .expect("could not write bundle to disk"); + + let mut msg = format!( + "Built successfully, script size is {}", + wranglerjs_output.script_size() + ); + if bundle.has_wasm() { + msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); + } - message::success(&msg); + message::success(&msg); - if let Some(tx) = tx.clone() { - let _ = tx.send(()); + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } } } } - }); + })?; Ok(()) } diff --git a/wranglerjs/index.js b/wranglerjs/index.js index ce2877cfb..457e5e3aa 100644 --- a/wranglerjs/index.js +++ b/wranglerjs/index.js @@ -1,6 +1,6 @@ const webpack = require("webpack"); const { join } = require("path"); -const { writeFileSync } = require("fs"); +const fs = require("fs"); const WasmMainTemplatePlugin = require("webpack/lib/wasm/WasmMainTemplatePlugin"); function error(msg) { @@ -65,37 +65,45 @@ fetchCompileWasmTemplatePlugin.fn = function(compilation) { plugin.apply(mainTemplate); }; +let lastHash = ""; const compilerCallback = (err, stats) => { if (err) { throw err; } - const assets = stats.compilation.assets; - const jsonStats = stats.toJson(); - const bundle = { - wasm: null, - script: "", - errors: jsonStats.errors - }; - - const wasmModuleAsset = Object.keys(assets).find(filterByExtension("wasm")); - const jsAssets = Object.keys(assets).filter(filterByExtension("js")); - const hasWasmModule = wasmModuleAsset !== undefined; - - bundle.script = jsAssets.reduce((acc, k) => { - const asset = assets[k]; - return acc + asset.source(); - }, ""); - - if (hasWasmModule === true) { - bundle.wasm = Buffer.from(assets[wasmModuleAsset].source()).toString("base64"); + console.log(lastHash + " : " + stats.hash); + if (stats.hash != lastHash) { + console.log("build done") + const assets = stats.compilation.assets; + const jsonStats = stats.toJson(); + const bundle = { + wasm: null, + script: "", + errors: jsonStats.errors + }; + + const wasmModuleAsset = Object.keys(assets).find(filterByExtension("wasm")); + const jsAssets = Object.keys(assets).filter(filterByExtension("js")); + const hasWasmModule = wasmModuleAsset !== undefined; + + bundle.script = jsAssets.reduce((acc, k) => { + const asset = assets[k]; + return acc + asset.source(); + }, ""); + + if (hasWasmModule === true) { + bundle.wasm = Buffer.from(assets[wasmModuleAsset].source()).toString("base64"); + } + + fs.writeFileSync(args["output-file"], JSON.stringify(bundle)); } - - writeFileSync(args["output-file"], JSON.stringify(bundle)); + lastHash = stats.hash; }; if (args["watch"] === "1") { + console.log("watch mode"); compiler.watch(fullConfig.watchOptions, compilerCallback); } else { + console.log("run mode"); compiler.run(compilerCallback); } From d57ca176503948bede57d36b1ad8b0c0190111d2 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 8 Jul 2019 16:05:44 -0500 Subject: [PATCH 13/63] update querystring params, use sessions instead of old_id/new_id --- src/commands/build/wranglerjs/mod.rs | 10 +++------ src/commands/publish/preview/mod.rs | 33 ++++++++++++++++------------ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 18d947616..76f03e987 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -76,13 +76,9 @@ pub fn run_build_and_watch( info!("Running {:?}", command); //start wranglerjs in a new thread - let command_handle = command.spawn()?; + let _command_handle = command.spawn()?; - println!("getting watcher ready"); - - let builder = thread::Builder::new().name("handler".into()); - - let handle = builder.spawn(move || { + let _thread_handle = thread::spawn(move || { let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); @@ -122,7 +118,7 @@ pub fn run_build_and_watch( } } } - })?; + }); Ok(()) } diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 9321d9345..746743a82 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -55,10 +55,18 @@ pub fn preview( let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); - open(preview_host, https, script_id, &session.to_string())?; + let ws_port: u16 = 8025; + + open( + preview_host, + https, + script_id, + &session.to_string(), + ws_port, + )?; if livereload { - watch_for_changes(session.to_string())?; + watch_for_changes()?; } else { println!("👷‍♀️ Your worker responded with: {}", worker_res); } @@ -71,18 +79,19 @@ fn open( https: bool, script_id: &str, session_id: &str, + ws_port: u16, ) -> Result<(), failure::Error> { let https_str = if https { "https://" } else { "http://" }; let browser_preview = if install::target::DEBUG { format!( - "http://localhost:3000/src/test/manual/#{}:{}{}?session_id={}&noeditor=true", - script_id, https_str, preview_host, session_id + "http://localhost:3000/src/test/manual/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", + session_id, ws_port, script_id, https_str, preview_host, ) } else { format!( - "https://cloudflareworkers.com/#{}:{}{}?session_id={}&noeditor=true", - script_id, https_str, preview_host, session_id + "https://cloudflareworkers.com/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", + session_id, ws_port, script_id, https_str, preview_host, ) }; let windows_cmd = format!("start {}", browser_preview); @@ -134,32 +143,28 @@ fn post( //in the future we may use this websocket for other things //so support other message types #[derive(Debug, Serialize)] +#[serde(tag = "type")] enum FiddleMessage { - LiveReload { old_id: String, new_id: String }, + LiveReload { new_id: String }, } -fn watch_for_changes(original_id: String) -> Result<(), failure::Error> { +fn watch_for_changes() -> Result<(), failure::Error> { //start up the websocket server. //needs a bs handler factory closure, even though we never respond let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind("localhost:8025")?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); - let mut old_id = original_id; let (tx, rx) = channel(); build_and_watch(&get_project_config()?, Some(tx))?; while let Ok(_e) = rx.recv() { if let Ok(new_id) = upload_and_get_id() { - let msg = FiddleMessage::LiveReload { - old_id: old_id.clone(), - new_id: new_id.clone(), - }; + let msg = FiddleMessage::LiveReload { new_id: new_id }; match broadcaster.send(serde_json::to_string(&msg)?) { Ok(_) => { println!("Sent new id to preview!"); - old_id = new_id; } Err(_e) => println!("communication with preview failed"), } From 8a1e9db07a36cca38c632e43e528354bff128099 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 8 Jul 2019 16:16:59 -0500 Subject: [PATCH 14/63] remove wranglerjs console logs --- wranglerjs/index.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wranglerjs/index.js b/wranglerjs/index.js index 457e5e3aa..34708971e 100644 --- a/wranglerjs/index.js +++ b/wranglerjs/index.js @@ -71,9 +71,7 @@ const compilerCallback = (err, stats) => { throw err; } - console.log(lastHash + " : " + stats.hash); if (stats.hash != lastHash) { - console.log("build done") const assets = stats.compilation.assets; const jsonStats = stats.toJson(); const bundle = { @@ -101,9 +99,7 @@ const compilerCallback = (err, stats) => { }; if (args["watch"] === "1") { - console.log("watch mode"); compiler.watch(fullConfig.watchOptions, compilerCallback); } else { - console.log("run mode"); compiler.run(compilerCallback); } From 6b96e9d0ee749041468730acab6bd958bf74b6ee Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 8 Jul 2019 17:33:35 -0500 Subject: [PATCH 15/63] finalize communication with the fiddle, add port + session support --- src/commands/publish/preview/mod.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 746743a82..3504cd35a 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -41,7 +41,7 @@ pub fn preview( let preview_address = "https://00000000000000000000000000000000.cloudflareworkers.com"; let cookie = format!( "__ew_fiddle_preview={}{}{}{}", - script_id, session, https, preview_host + script_id, session, https as u8, preview_host ); let method = method.unwrap_or_default(); @@ -66,7 +66,7 @@ pub fn preview( )?; if livereload { - watch_for_changes()?; + watch_for_changes(session.to_string(), ws_port)?; } else { println!("👷‍♀️ Your worker responded with: {}", worker_res); } @@ -142,16 +142,25 @@ fn post( //for now, this is only used by livereloading. //in the future we may use this websocket for other things //so support other message types +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct FiddleMessage { + session_id: String, + #[serde(flatten)] + data: FiddleMessageData, +} + #[derive(Debug, Serialize)] #[serde(tag = "type")] -enum FiddleMessage { +enum FiddleMessageData { + #[serde(rename_all = "camelCase")] LiveReload { new_id: String }, } -fn watch_for_changes() -> Result<(), failure::Error> { +fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Error> { //start up the websocket server. //needs a bs handler factory closure, even though we never respond - let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind("localhost:8025")?; + let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind(format!("localhost:{}", ws_port))?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); @@ -160,7 +169,12 @@ fn watch_for_changes() -> Result<(), failure::Error> { while let Ok(_e) = rx.recv() { if let Ok(new_id) = upload_and_get_id() { - let msg = FiddleMessage::LiveReload { new_id: new_id }; + let msg = FiddleMessage { + session_id: session_id.clone(), + data: FiddleMessageData::LiveReload { + new_id, + } + }; match broadcaster.send(serde_json::to_string(&msg)?) { Ok(_) => { @@ -178,7 +192,7 @@ fn watch_for_changes() -> Result<(), failure::Error> { #[derive(Debug, Deserialize)] struct Preview { - pub id: String, + id: String, } fn upload_and_get_id() -> Result { From d3707abd43ed800a0b79a408a9f761786e38f4c6 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 9 Jul 2019 10:01:55 -0500 Subject: [PATCH 16/63] move watcher inside thread closure to have the correct lifetime --- src/commands/build/mod.rs | 66 ++++++++++++++-------- src/commands/build/wranglerjs/mod.rs | 82 ++++++++++++---------------- 2 files changed, 79 insertions(+), 69 deletions(-) diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 514d10f34..d1479856e 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -8,11 +8,13 @@ use std::process::Command; use crate::terminal::message; -use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; +use notify::{watcher, RecursiveMode, Watcher}; use std::sync::mpsc::{channel, Sender}; use std::thread; use std::time::Duration; +use std::env; + pub fn build(project: &Project) -> Result<(), failure::Error> { let project_type = &project.project_type; match project_type { @@ -41,16 +43,24 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), let project_type = &project.project_type; match project_type { ProjectType::JavaScript => { - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; - let package = Package::new("./")?; - watcher.watch(package.main()?, RecursiveMode::Recursive)?; - - thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { - if let Some(tx) = tx.clone() { - let _ = tx.send(()); + let entry = package.main()?; + thread::spawn(move || { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + + watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); + message::info(&format!("watching {:?}", &entry)); + + loop { + match watcher_rx.recv() { + Ok(_) => { + message::working("Detected changes..."); + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } + }, + Err(_) => panic!("Something went wrong while watching.") } } }); @@ -60,19 +70,29 @@ pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; let args = ["build", "--target", "no-modules"]; - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1))?; - - watcher.watch("./src", RecursiveMode::Recursive)?; - - thread::spawn(move || loop { - if let Ok(DebouncedEvent::Write(_path)) = watcher_rx.recv() { - let command = command(&args, &binary_path); - let command_name = format!("{:?}", command); - if let Ok(_) = commands::run(command, &command_name) { - if let Some(tx) = tx.clone() { - let _ = tx.send(()); - } + thread::spawn(move || { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + + let mut path = env::current_dir().expect("current dir"); + path.push("src"); + + watcher.watch(&path, RecursiveMode::Recursive).unwrap(); + message::info(&format!("watching {:?}", &path)); + + loop { + match watcher_rx.recv() { + Ok(_) => { + message::working("Detected changes..."); + let command = command(&args, &binary_path); + let command_name = format!("{:?}", command); + if let Ok(_) = commands::run(command, &command_name) { + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } + } + }, + Err(_) => panic!("Something went wrong while watching.") } } }); diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 76f03e987..cf5195054 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -19,7 +19,7 @@ use std::process::Command; use crate::settings::project::Project; use crate::terminal::message; -use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; +use notify::{watcher, RecursiveMode, Watcher}; use std::sync::mpsc::{channel, Sender}; use std::thread; use std::time::Duration; @@ -44,22 +44,7 @@ pub fn run_build(project: &Project) -> Result<(), failure::Error> { let wranglerjs_output: WranglerjsOutput = serde_json::from_str(&output).expect("could not parse wranglerjs output"); - if wranglerjs_output.has_errors() { - message::user_error(wranglerjs_output.get_errors().as_str()); - failure::bail!("Webpack returned an error"); - } - - bundle - .write(&wranglerjs_output) - .expect("could not write bundle to disk"); - - let msg = format!( - "Built successfully, built project size is {}", - wranglerjs_output.project_size() - ); - - message::success(&msg); - Ok(()) + write_wranglerjs_output(&bundle, &wranglerjs_output) } else { fs::remove_file(temp_file)?; failure::bail!("failed to execute `{:?}`: exited with {}", command, status) @@ -84,38 +69,24 @@ pub fn run_build_and_watch( watcher.watch(&temp_file, RecursiveMode::Recursive).unwrap(); - println!("watching {:?}", &temp_file); + message::info(&format!("watching {:?}", &temp_file)); loop { - let event = watcher_rx.recv(); - if let Ok(DebouncedEvent::Write(_)) = event { - println!("got new bundle from wranglerjs"); - let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); - - let wranglerjs_output: WranglerjsOutput = - serde_json::from_str(&output).expect("could not parse wranglerjs output"); - - if wranglerjs_output.has_errors() { - message::user_error(&format!("{}", wranglerjs_output.get_errors())); - } else { - bundle - .write(&wranglerjs_output) - .expect("could not write bundle to disk"); - - let mut msg = format!( - "Built successfully, script size is {}", - wranglerjs_output.script_size() - ); - if bundle.has_wasm() { - msg = format!("{} and Wasm size is {}", msg, wranglerjs_output.wasm_size()); + match watcher_rx.recv() { + Ok(_) => { + message::working("Detected changes..."); + let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); + + let wranglerjs_output: WranglerjsOutput = + serde_json::from_str(&output).expect("could not parse wranglerjs output"); + + if write_wranglerjs_output(&bundle, &wranglerjs_output).is_ok() { + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } } - - message::success(&msg); - - if let Some(tx) = tx.clone() { - let _ = tx.send(()); - } - } + }, + Err(_) => panic!("Something went wrong while watching.") } } }); @@ -123,6 +94,25 @@ pub fn run_build_and_watch( Ok(()) } +fn write_wranglerjs_output(bundle: &Bundle, output: &WranglerjsOutput) -> Result<(), failure::Error> { + if output.has_errors() { + message::user_error(output.get_errors().as_str()); + failure::bail!("Webpack returned an error"); + } + + bundle + .write(output) + .expect("could not write bundle to disk"); + + let msg = format!( + "Built successfully, built project size is {}", + output.project_size() + ); + + message::success(&msg); + Ok(()) +} + //setup a build to run wranglerjs, return the command, the ipc temp file, and the bundle fn setup_build(project: &Project) -> Result<(Command, PathBuf, Bundle), failure::Error> { for tool in &["node", "npm"] { From 61d6b7604261fb44860946a97772656c76397971 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 9 Jul 2019 10:25:52 -0500 Subject: [PATCH 17/63] s/build_and_watch/watch_and_build, put watch_and_build inside its own module --- src/commands/build/mod.rs | 82 +++-------------------------- src/commands/build/watch/mod.rs | 80 ++++++++++++++++++++++++++++ src/commands/build/watch/watcher.rs | 0 src/commands/mod.rs | 2 +- src/commands/publish/preview/mod.rs | 4 +- src/main.rs | 2 +- 6 files changed, 90 insertions(+), 80 deletions(-) create mode 100644 src/commands/build/watch/mod.rs create mode 100644 src/commands/build/watch/watcher.rs diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index d1479856e..3feb99afd 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -1,20 +1,15 @@ pub mod wranglerjs; -use crate::commands::publish::Package; +mod watch; +pub use watch::watch_and_build; + +use crate::terminal::message; use crate::settings::project::{Project, ProjectType}; use crate::{commands, install}; + use std::path::PathBuf; use std::process::Command; -use crate::terminal::message; - -use notify::{watcher, RecursiveMode, Watcher}; -use std::sync::mpsc::{channel, Sender}; -use std::thread; -use std::time::Duration; - -use std::env; - pub fn build(project: &Project) -> Result<(), failure::Error> { let project_type = &project.project_type; match project_type { @@ -39,73 +34,8 @@ pub fn build(project: &Project) -> Result<(), failure::Error> { Ok(()) } -pub fn build_and_watch(project: &Project, tx: Option>) -> Result<(), failure::Error> { - let project_type = &project.project_type; - match project_type { - ProjectType::JavaScript => { - let package = Package::new("./")?; - let entry = package.main()?; - thread::spawn(move || { - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - - watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); - message::info(&format!("watching {:?}", &entry)); - - loop { - match watcher_rx.recv() { - Ok(_) => { - message::working("Detected changes..."); - if let Some(tx) = tx.clone() { - let _ = tx.send(()); - } - }, - Err(_) => panic!("Something went wrong while watching.") - } - } - }); - } - ProjectType::Rust => { - let tool_name = "wasm-pack"; - let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; - let args = ["build", "--target", "no-modules"]; - - thread::spawn(move || { - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - - let mut path = env::current_dir().expect("current dir"); - path.push("src"); - - watcher.watch(&path, RecursiveMode::Recursive).unwrap(); - message::info(&format!("watching {:?}", &path)); - - loop { - match watcher_rx.recv() { - Ok(_) => { - message::working("Detected changes..."); - let command = command(&args, &binary_path); - let command_name = format!("{:?}", command); - if let Ok(_) = commands::run(command, &command_name) { - if let Some(tx) = tx.clone() { - let _ = tx.send(()); - } - } - }, - Err(_) => panic!("Something went wrong while watching.") - } - } - }); - } - ProjectType::Webpack => { - wranglerjs::run_build_and_watch(project, tx)?; - } - } - - Ok(()) -} -fn command(args: &[&str], binary_path: &PathBuf) -> Command { +pub fn command(args: &[&str], binary_path: &PathBuf) -> Command { message::working("Compiling your project to WebAssembly..."); let mut c = if cfg!(target_os = "windows") { diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs new file mode 100644 index 000000000..82b318c22 --- /dev/null +++ b/src/commands/build/watch/mod.rs @@ -0,0 +1,80 @@ +use crate::terminal::message; +use crate::commands::build::{wranglerjs, command}; +use crate::commands::publish::Package; +use crate::{commands, install}; +use crate::settings::project::{Project, ProjectType}; + +use notify::{watcher, RecursiveMode, Watcher}; + +use std::sync::mpsc::{channel, Sender}; +use std::thread; +use std::time::Duration; +use std::env; + +/// watch a project for changes and re-build it when necessary, +/// outputting a build event to tx. +pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), failure::Error> { + let project_type = &project.project_type; + match project_type { + ProjectType::JavaScript => { + let package = Package::new("./")?; + let entry = package.main()?; + thread::spawn(move || { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + + watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); + message::info(&format!("watching {:?}", &entry)); + + loop { + match watcher_rx.recv() { + Ok(_) => { + message::working("Detected changes..."); + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } + }, + Err(_) => panic!("Something went wrong while watching.") + } + } + }); + } + ProjectType::Rust => { + let tool_name = "wasm-pack"; + let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; + let args = ["build", "--target", "no-modules"]; + + thread::spawn(move || { + let (watcher_tx, watcher_rx) = channel(); + let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + + let mut path = env::current_dir().expect("current dir"); + path.push("src"); + + watcher.watch(&path, RecursiveMode::Recursive).unwrap(); + message::info(&format!("watching {:?}", &path)); + + loop { + match watcher_rx.recv() { + Ok(_) => { + message::working("Detected changes..."); + let command = command(&args, &binary_path); + let command_name = format!("{:?}", command); + if let Ok(_) = commands::run(command, &command_name) { + if let Some(tx) = tx.clone() { + let _ = tx.send(()); + } + } + }, + Err(_) => panic!("Something went wrong while watching.") + } + } + }); + } + ProjectType::Webpack => { + wranglerjs::run_build_and_watch(project, tx)?; + } + } + + Ok(()) +} diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs new file mode 100644 index 000000000..e69de29bb diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 4f249c679..cc8dd7b96 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -12,7 +12,7 @@ pub mod whoami; pub use self::config::global_config; pub use build::build; -pub use build::build_and_watch; +pub use build::watch_and_build; pub use generate::generate; pub use init::init; pub use publish::preview::preview; diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 3504cd35a..571a43d0f 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -4,7 +4,7 @@ mod http_method; pub use http_method::HTTPMethod; use crate::commands::build; -use crate::commands::build_and_watch; +use crate::commands::watch_and_build; use crate::commands::publish; use serde::{Deserialize, Serialize}; @@ -165,7 +165,7 @@ fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Er thread::spawn(move || server.run()); let (tx, rx) = channel(); - build_and_watch(&get_project_config()?, Some(tx))?; + watch_and_build(&get_project_config()?, Some(tx))?; while let Ok(_e) = rx.recv() { if let Ok(new_id) = upload_and_get_id() { diff --git a/src/main.rs b/src/main.rs index 8ebcb560b..b4722c110 100644 --- a/src/main.rs +++ b/src/main.rs @@ -202,7 +202,7 @@ fn run() -> Result<(), failure::Error> { let project = settings::project::Project::new()?; match matches.occurrences_of("watch") { 1 => commands::build(&project)?, - _ => commands::build_and_watch(&project, None)?, + _ => commands::watch_and_build(&project, None)?, }; } else if let Some(matches) = matches.subcommand_matches("preview") { info!("Getting project settings"); From b89cc31b7f8e1a260cdd0c54ca4d9a7c47e573f9 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 15:00:30 -0500 Subject: [PATCH 18/63] add guardedcommand for running wranglerjs in --watch while having it die with the main thread --- src/commands/build/mod.rs | 3 +-- src/commands/build/watch/mod.rs | 19 +++++++++---------- src/commands/build/watch/watcher.rs | 3 +++ src/commands/build/wranglerjs/mod.rs | 10 +++++----- src/main.rs | 1 + src/util.rs | 21 +++++++++++++++++++++ 6 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 src/util.rs diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 3feb99afd..80c542c09 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -3,8 +3,8 @@ pub mod wranglerjs; mod watch; pub use watch::watch_and_build; -use crate::terminal::message; use crate::settings::project::{Project, ProjectType}; +use crate::terminal::message; use crate::{commands, install}; use std::path::PathBuf; @@ -34,7 +34,6 @@ pub fn build(project: &Project) -> Result<(), failure::Error> { Ok(()) } - pub fn command(args: &[&str], binary_path: &PathBuf) -> Command { message::working("Compiling your project to WebAssembly..."); diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 82b318c22..d48d6ea9f 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -1,15 +1,14 @@ -use crate::terminal::message; -use crate::commands::build::{wranglerjs, command}; +use crate::commands::build::{command, wranglerjs}; use crate::commands::publish::Package; -use crate::{commands, install}; use crate::settings::project::{Project, ProjectType}; +use crate::terminal::message; +use crate::{commands, install}; use notify::{watcher, RecursiveMode, Watcher}; - +use std::env; use std::sync::mpsc::{channel, Sender}; use std::thread; use std::time::Duration; -use std::env; /// watch a project for changes and re-build it when necessary, /// outputting a build event to tx. @@ -33,8 +32,8 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), if let Some(tx) = tx.clone() { let _ = tx.send(()); } - }, - Err(_) => panic!("Something went wrong while watching.") + } + Err(_) => message::user_error("Something went wrong while watching."), } } }); @@ -60,13 +59,13 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), message::working("Detected changes..."); let command = command(&args, &binary_path); let command_name = format!("{:?}", command); - if let Ok(_) = commands::run(command, &command_name) { + if commands::run(command, &command_name).is_ok() { if let Some(tx) = tx.clone() { let _ = tx.send(()); } } - }, - Err(_) => panic!("Something went wrong while watching.") + } + Err(_) => message::user_error("Something went wrong while watching."), } } }); diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs index e69de29bb..0698f8e10 100644 --- a/src/commands/build/watch/watcher.rs +++ b/src/commands/build/watch/watcher.rs @@ -0,0 +1,3 @@ +use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; +use std::thread; +use std::time::Duration; diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index cf5195054..f1fc9a2d6 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -3,6 +3,7 @@ pub mod output; use crate::commands::publish::package::Package; use crate::install; +use crate::util; pub use bundle::Bundle; use fs2::FileExt; use log::info; @@ -60,10 +61,9 @@ pub fn run_build_and_watch( info!("Running {:?}", command); - //start wranglerjs in a new thread - let _command_handle = command.spawn()?; + let _command_guard = util::GuardedCommand::spawn(command); - let _thread_handle = thread::spawn(move || { + let _watch_thread_handle = thread::spawn(move || { let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); @@ -85,8 +85,8 @@ pub fn run_build_and_watch( let _ = tx.send(()); } } - }, - Err(_) => panic!("Something went wrong while watching.") + } + Err(_) => message::user_error("Something went wrong while watching."), } } }); diff --git a/src/main.rs b/src/main.rs index b4722c110..b1bd30211 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,7 @@ use log::info; mod commands; mod http; +mod util; mod install; mod installer; mod settings; diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 000000000..a57d63970 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,21 @@ +use std::process::{Command,Child}; + +/// wrapper around spawning child processes such that they +/// have the same behavior as spawned threads i.e. a spawned +/// child process using GuardedChild has the same lifetime as +/// the main thread. +pub struct GuardedCommand(Child); + +impl GuardedCommand { + pub fn spawn(mut command: Command) -> GuardedCommand { + GuardedCommand(command.spawn().expect("failed to execute child command")) + } +} + +impl Drop for GuardedCommand { + fn drop(&mut self) { + if let Err(e) = self.0.kill() { + panic!("Failed to kill child process: {:?}", e); + } + } +} From f11a038f5a0a42e4c78d43c8b3aef29c65539a5f Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 9 Jul 2019 16:46:52 -0500 Subject: [PATCH 19/63] add cooldown period for fs events --- src/commands/build/watch/mod.rs | 15 +++++---- src/commands/build/watch/watcher.rs | 47 ++++++++++++++++++++++++++-- src/commands/build/wranglerjs/mod.rs | 21 ++++++++++--- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index d48d6ea9f..3b9635916 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -1,3 +1,6 @@ +mod watcher; +pub use watcher::wait_for_changes; + use crate::commands::build::{command, wranglerjs}; use crate::commands::publish::Package; use crate::settings::project::{Project, ProjectType}; @@ -10,6 +13,8 @@ use std::sync::mpsc::{channel, Sender}; use std::thread; use std::time::Duration; +pub const COOLDOWN_PERIOD: Duration = Duration::from_millis(2000); + /// watch a project for changes and re-build it when necessary, /// outputting a build event to tx. pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), failure::Error> { @@ -26,9 +31,8 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), message::info(&format!("watching {:?}", &entry)); loop { - match watcher_rx.recv() { - Ok(_) => { - message::working("Detected changes..."); + match wait_for_changes(&watcher_rx, COOLDOWN_PERIOD) { + Ok(_path) => { if let Some(tx) = tx.clone() { let _ = tx.send(()); } @@ -54,9 +58,8 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), message::info(&format!("watching {:?}", &path)); loop { - match watcher_rx.recv() { - Ok(_) => { - message::working("Detected changes..."); + match wait_for_changes(&watcher_rx, COOLDOWN_PERIOD) { + Ok(_path) => { let command = command(&args, &binary_path); let command_name = format!("{:?}", command); if commands::run(command, &command_name).is_ok() { diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs index 0698f8e10..18dee7a94 100644 --- a/src/commands/build/watch/watcher.rs +++ b/src/commands/build/watch/watcher.rs @@ -1,3 +1,46 @@ -use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; -use std::thread; +use notify::{DebouncedEvent}; +use std::sync::mpsc::{Receiver}; use std::time::Duration; +use std::path::PathBuf; + +use failure::{Error, format_err}; + +use crate::terminal::message; + +///Add cooldown for all types of events to watching logic +pub fn wait_for_changes(rx: &Receiver, cooldown: Duration) -> Result { + loop { + let event = rx.recv()?; + match get_changed_path_from_event(event) { + Ok(Some(path)) => { + message::working("Detected changes..."); + //wait for cooldown + while let Ok(_e) = rx.recv_timeout(cooldown) { + message::working("Detected change during cooldown..."); + }; + message::working("Cooldown over, propogating changes..."); + return Ok(path); + } + Ok(None) => { + continue; //was an event type we don't care about, continue + } + Err(error) => { + message::user_error(&format!("WatchError {:?}", error)); + continue; + } + }; + } +} + +fn get_changed_path_from_event(event: DebouncedEvent) -> Result, Error> { + println!("Detected Event {:?}", event); + match event { + DebouncedEvent::Error(error, _) => Err(format_err!("{:?}", error)), + DebouncedEvent::NoticeWrite(path) => Ok(Some(path)), + DebouncedEvent::Write(path) => Ok(Some(path)), + DebouncedEvent::NoticeRemove(path) => Ok(Some(path)), + DebouncedEvent::Remove(path) => Ok(Some(path)), + DebouncedEvent::Create(path) => Ok(Some(path)), + _ => Ok(None), + } +} diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index f1fc9a2d6..d68ef4ce1 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -1,6 +1,9 @@ mod bundle; pub mod output; +use crate::commands::build::watch::COOLDOWN_PERIOD; +use crate::commands::build::watch::wait_for_changes; + use crate::commands::publish::package::Package; use crate::install; use crate::util; @@ -61,9 +64,9 @@ pub fn run_build_and_watch( info!("Running {:?}", command); - let _command_guard = util::GuardedCommand::spawn(command); + thread::spawn(move || { + let _command_guard = util::GuardedCommand::spawn(command); - let _watch_thread_handle = thread::spawn(move || { let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); @@ -71,12 +74,20 @@ pub fn run_build_and_watch( message::info(&format!("watching {:?}", &temp_file)); + let mut is_first = true; + loop { - match watcher_rx.recv() { + match wait_for_changes(&watcher_rx, COOLDOWN_PERIOD) { Ok(_) => { - message::working("Detected changes..."); - let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); + if is_first { + is_first = false; + //skip the first change event + //so we don't do a refresh immediately + continue; + } + let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); + println!("{}", output); let wranglerjs_output: WranglerjsOutput = serde_json::from_str(&output).expect("could not parse wranglerjs output"); From 25107cfbcae7fb17f49c0928077d1957a68472a6 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 10 Jul 2019 10:25:22 -0500 Subject: [PATCH 20/63] don't swallow tx errors from watch_and_build --- src/commands/build/watch/mod.rs | 4 ++-- src/commands/build/wranglerjs/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 3b9635916..b804b47b5 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -34,7 +34,7 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), match wait_for_changes(&watcher_rx, COOLDOWN_PERIOD) { Ok(_path) => { if let Some(tx) = tx.clone() { - let _ = tx.send(()); + tx.send(()).expect("--watch change message failed to send"); } } Err(_) => message::user_error("Something went wrong while watching."), @@ -64,7 +64,7 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), let command_name = format!("{:?}", command); if commands::run(command, &command_name).is_ok() { if let Some(tx) = tx.clone() { - let _ = tx.send(()); + tx.send(()).expect("--watch change message failed to send"); } } } diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index d68ef4ce1..843f06323 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -93,7 +93,7 @@ pub fn run_build_and_watch( if write_wranglerjs_output(&bundle, &wranglerjs_output).is_ok() { if let Some(tx) = tx.clone() { - let _ = tx.send(()); + tx.send(()).expect("--watch change message failed to send"); } } } From 074a2a79bcda2450911856d2b1d7381e01600003 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 15 Jul 2019 09:50:51 -0500 Subject: [PATCH 21/63] fix wrangler build --watch --- src/main.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index b1bd30211..7ae8a4320 100644 --- a/src/main.rs +++ b/src/main.rs @@ -198,12 +198,20 @@ fn run() -> Result<(), failure::Error> { None => None, }; commands::init(name, project_type)?; - } else if matches.subcommand_matches("build").is_some() { + } else if let Some(matches) = matches.subcommand_matches("build") { info!("Getting project settings"); let project = settings::project::Project::new()?; + match matches.occurrences_of("watch") { - 1 => commands::build(&project)?, - _ => commands::watch_and_build(&project, None)?, + 1 => { + commands::watch_and_build(&project, None)?; + loop { + //we need to keep the main thread "alive" + //watch_and_build has all the messaging we need + //so this loop doesn't actually need to do anything + } + }, + _ => commands::build(&project)? }; } else if let Some(matches) = matches.subcommand_matches("preview") { info!("Getting project settings"); From 59055abdf0a18b87b556bef7670ff1b588a7c8ab Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 15 Jul 2019 10:06:11 -0500 Subject: [PATCH 22/63] made messaging use message crate, removed some println! --- src/commands/build/watch/watcher.rs | 3 ++- src/commands/build/wranglerjs/mod.rs | 1 - src/commands/publish/preview/mod.rs | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs index 18dee7a94..b25bde170 100644 --- a/src/commands/build/watch/watcher.rs +++ b/src/commands/build/watch/watcher.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; use failure::{Error, format_err}; use crate::terminal::message; +use log::info; ///Add cooldown for all types of events to watching logic pub fn wait_for_changes(rx: &Receiver, cooldown: Duration) -> Result { @@ -33,7 +34,7 @@ pub fn wait_for_changes(rx: &Receiver, cooldown: Duration) -> Re } fn get_changed_path_from_event(event: DebouncedEvent) -> Result, Error> { - println!("Detected Event {:?}", event); + info!("Detected Event {:?}", event); match event { DebouncedEvent::Error(error, _) => Err(format_err!("{:?}", error)), DebouncedEvent::NoticeWrite(path) => Ok(Some(path)), diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 843f06323..8d2500373 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -87,7 +87,6 @@ pub fn run_build_and_watch( } let output = fs::read_to_string(&temp_file).expect("could not retrieve ouput"); - println!("{}", output); let wranglerjs_output: WranglerjsOutput = serde_json::from_str(&output).expect("could not parse wranglerjs output"); diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 571a43d0f..2ebf2b457 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -68,7 +68,8 @@ pub fn preview( if livereload { watch_for_changes(session.to_string(), ws_port)?; } else { - println!("👷‍♀️ Your worker responded with: {}", worker_res); + let msg = format!("👷‍♀️ Your worker responded with: {}", worker_res); + message::preview(&msg); } Ok(()) @@ -178,9 +179,9 @@ fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Er match broadcaster.send(serde_json::to_string(&msg)?) { Ok(_) => { - println!("Sent new id to preview!"); + message::preview("Sent new id to preview!"); } - Err(_e) => println!("communication with preview failed"), + Err(_e) => message::user_error("communication with preview failed"), } } } From bc972d242d6c5fa8cb61923e9929a6041606f68f Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 15 Jul 2019 10:09:58 -0500 Subject: [PATCH 23/63] cargo fmt --- src/commands/build/watch/watcher.rs | 17 ++++++++++------- src/commands/build/wranglerjs/mod.rs | 2 +- src/commands/publish/preview/mod.rs | 8 +++----- src/main.rs | 6 +++--- src/util.rs | 2 +- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs index b25bde170..ad8fb5fd0 100644 --- a/src/commands/build/watch/watcher.rs +++ b/src/commands/build/watch/watcher.rs @@ -1,15 +1,18 @@ -use notify::{DebouncedEvent}; -use std::sync::mpsc::{Receiver}; -use std::time::Duration; +use notify::DebouncedEvent; use std::path::PathBuf; +use std::sync::mpsc::Receiver; +use std::time::Duration; -use failure::{Error, format_err}; +use failure::{format_err, Error}; use crate::terminal::message; use log::info; ///Add cooldown for all types of events to watching logic -pub fn wait_for_changes(rx: &Receiver, cooldown: Duration) -> Result { +pub fn wait_for_changes( + rx: &Receiver, + cooldown: Duration, +) -> Result { loop { let event = rx.recv()?; match get_changed_path_from_event(event) { @@ -18,12 +21,12 @@ pub fn wait_for_changes(rx: &Receiver, cooldown: Duration) -> Re //wait for cooldown while let Ok(_e) = rx.recv_timeout(cooldown) { message::working("Detected change during cooldown..."); - }; + } message::working("Cooldown over, propogating changes..."); return Ok(path); } Ok(None) => { - continue; //was an event type we don't care about, continue + continue; //was an event type we don't care about, continue } Err(error) => { message::user_error(&format!("WatchError {:?}", error)); diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 8d2500373..e80b95d97 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -1,8 +1,8 @@ mod bundle; pub mod output; -use crate::commands::build::watch::COOLDOWN_PERIOD; use crate::commands::build::watch::wait_for_changes; +use crate::commands::build::watch::COOLDOWN_PERIOD; use crate::commands::publish::package::Package; use crate::install; diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 2ebf2b457..9c33086b8 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -4,8 +4,8 @@ mod http_method; pub use http_method::HTTPMethod; use crate::commands::build; -use crate::commands::watch_and_build; use crate::commands::publish; +use crate::commands::watch_and_build; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -170,11 +170,9 @@ fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Er while let Ok(_e) = rx.recv() { if let Ok(new_id) = upload_and_get_id() { - let msg = FiddleMessage { + let msg = FiddleMessage { session_id: session_id.clone(), - data: FiddleMessageData::LiveReload { - new_id, - } + data: FiddleMessageData::LiveReload { new_id }, }; match broadcaster.send(serde_json::to_string(&msg)?) { diff --git a/src/main.rs b/src/main.rs index 7ae8a4320..e7b6e697b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,11 +13,11 @@ use log::info; mod commands; mod http; -mod util; mod install; mod installer; mod settings; mod terminal; +mod util; use crate::settings::project::ProjectType; use exitfailure::ExitFailure; @@ -210,8 +210,8 @@ fn run() -> Result<(), failure::Error> { //watch_and_build has all the messaging we need //so this loop doesn't actually need to do anything } - }, - _ => commands::build(&project)? + } + _ => commands::build(&project)?, }; } else if let Some(matches) = matches.subcommand_matches("preview") { info!("Getting project settings"); diff --git a/src/util.rs b/src/util.rs index a57d63970..90a2ce2a6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -use std::process::{Command,Child}; +use std::process::{Child, Command}; /// wrapper around spawning child processes such that they /// have the same behavior as spawned threads i.e. a spawned From 4d2d444e2c9272e848b35012b01ffa27533ec8dd Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 15 Jul 2019 11:01:09 -0500 Subject: [PATCH 24/63] Add message when ignoring stale first change --- src/commands/build/wranglerjs/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index e80b95d97..eb1cfd753 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -81,6 +81,7 @@ pub fn run_build_and_watch( Ok(_) => { if is_first { is_first = false; + message::info("Ignoring stale first change"); //skip the first change event //so we don't do a refresh immediately continue; From a0922a9d6a3533bed678241942e17759b5936eee Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 15 Jul 2019 16:46:05 -0500 Subject: [PATCH 25/63] Check origin header and close if invalid --- src/commands/publish/preview/mod.rs | 47 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 9c33086b8..ce03e9a41 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -22,7 +22,7 @@ use crate::terminal::message; use std::sync::mpsc::channel; use std::thread; -use ws::WebSocket; +use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender, WebSocket}; pub fn preview( project: &Project, @@ -158,10 +158,51 @@ enum FiddleMessageData { LiveReload { new_id: String }, } +struct FiddleMessageServer { + out: Sender, +} + +impl Handler for FiddleMessageServer { + fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { + #[cfg(not(debug_assertions))] + const SAFE_ORIGINS: &[&str] = &[ + "https://cloudflareworkers.com/", + ]; + + #[cfg(debug_assertions)] + const SAFE_ORIGINS: &[&str] = &[ + "https://cloudflareworkers.com/", + "https://localhost", //trailing slash ommitted to allow for any port + ]; + + let origin = handshake.request.origin()?.unwrap_or("unknown"); + + let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { + is_safe || origin.starts_with(safe_origin) + }); + + if is_safe { + message::info(&format!("Accepted connection from {}", origin)); + } else { + message::user_error(&format!( + "Denied connection from {}. This is not a trusted origin", + origin + )); + + let _ = self + .out + .close(CloseCode::Policy) + .expect("failed to close connection to unsafe origin"); + } + + Ok(()) + } +} + fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Error> { //start up the websocket server. - //needs a bs handler factory closure, even though we never respond - let server = WebSocket::new(|_out| |_msg| Ok(()))?.bind(format!("localhost:{}", ws_port))?; + let server = WebSocket::new(|out| FiddleMessageServer { out })? + .bind(format!("localhost:{}", ws_port))?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); From 88c42e20315b04ba3952eeda479911485d42ea6d Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 16 Jul 2019 10:37:34 -0500 Subject: [PATCH 26/63] separate out fiddle message server into its own module --- .../publish/preview/fiddle_messenger.rs | 62 +++++++++ src/commands/publish/preview/mod.rs | 119 ++++-------------- 2 files changed, 84 insertions(+), 97 deletions(-) create mode 100644 src/commands/publish/preview/fiddle_messenger.rs diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs new file mode 100644 index 000000000..c46e544c3 --- /dev/null +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -0,0 +1,62 @@ +use serde::Serialize; +use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender}; +use crate::terminal::message; + +//for now, this is only used by livereloading. +//in the future we may use this websocket for other things +//so support other message types +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct FiddleMessage { + pub session_id: String, + #[serde(flatten)] + pub data: FiddleMessageData, +} + +#[derive(Debug, Serialize)] +#[serde(tag = "type")] +pub enum FiddleMessageData { + #[serde(rename_all = "camelCase")] + LiveReload { new_id: String }, +} + +pub struct FiddleMessageServer { + pub out: Sender, +} + +impl Handler for FiddleMessageServer { + fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { + #[cfg(not(debug_assertions))] + const SAFE_ORIGINS: &[&str] = &[ + "https://cloudflareworkers.com/", + ]; + + #[cfg(debug_assertions)] + const SAFE_ORIGINS: &[&str] = &[ + "https://cloudflareworkers.com/", + "https://localhost", //trailing slash ommitted to allow for any port + ]; + + let origin = handshake.request.origin()?.unwrap_or("unknown"); + + let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { + is_safe || origin.starts_with(safe_origin) + }); + + if is_safe { + message::info(&format!("Accepted connection from {}", origin)); + } else { + message::user_error(&format!( + "Denied connection from {}. This is not a trusted origin", + origin + )); + + let _ = self + .out + .close(CloseCode::Policy) + .expect("failed to close connection to unsafe origin"); + } + + Ok(()) + } +} diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index ce03e9a41..95b22bdca 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -1,28 +1,27 @@ use std::process::Command; +mod fiddle_messenger; +use fiddle_messenger::*; + + mod http_method; pub use http_method::HTTPMethod; use crate::commands::build; -use crate::commands::publish; use crate::commands::watch_and_build; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use uuid::Uuid; use crate::http; -<<<<<<< HEAD -use crate::settings::project::Project; -======= use crate::install; -use crate::settings::project::get_project_config; -use crate::settings::project::{Project, ProjectType}; ->>>>>>> c35288a... add build_and_watch +use crate::settings::project::Project; use crate::terminal::message; +use super::upload_form::build_script_upload_form; use std::sync::mpsc::channel; use std::thread; -use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender, WebSocket}; +use ws::{WebSocket, Sender}; pub fn preview( project: &Project, @@ -36,7 +35,7 @@ pub fn preview( let preview_host = "example.com"; let https = true; - let script_id = &upload_and_get_id()?; + let script_id = &upload_and_get_id(project)?; let preview_address = "https://00000000000000000000000000000000.cloudflareworkers.com"; let cookie = format!( @@ -52,9 +51,6 @@ pub fn preview( HTTPMethod::Post => post(preview_address, cookie, client, body)?, }; - let msg = format!("Your worker responded with: {}", worker_res); - message::preview(&msg); - let ws_port: u16 = 8025; open( @@ -66,9 +62,13 @@ pub fn preview( )?; if livereload { - watch_for_changes(session.to_string(), ws_port)?; + let server = WebSocket::new(|out| FiddleMessageServer { out })? + .bind(format!("localhost:{}", ws_port))?; + let broadcaster = server.broadcaster(); + thread::spawn(move || server.run()); + watch_for_changes(project, session.to_string(), broadcaster)?; } else { - let msg = format!("👷‍♀️ Your worker responded with: {}", worker_res); + let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); } @@ -140,77 +140,12 @@ fn post( Ok(res?.text()?) } -//for now, this is only used by livereloading. -//in the future we may use this websocket for other things -//so support other message types -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct FiddleMessage { - session_id: String, - #[serde(flatten)] - data: FiddleMessageData, -} - -#[derive(Debug, Serialize)] -#[serde(tag = "type")] -enum FiddleMessageData { - #[serde(rename_all = "camelCase")] - LiveReload { new_id: String }, -} - -struct FiddleMessageServer { - out: Sender, -} - -impl Handler for FiddleMessageServer { - fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { - #[cfg(not(debug_assertions))] - const SAFE_ORIGINS: &[&str] = &[ - "https://cloudflareworkers.com/", - ]; - - #[cfg(debug_assertions)] - const SAFE_ORIGINS: &[&str] = &[ - "https://cloudflareworkers.com/", - "https://localhost", //trailing slash ommitted to allow for any port - ]; - - let origin = handshake.request.origin()?.unwrap_or("unknown"); - - let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { - is_safe || origin.starts_with(safe_origin) - }); - - if is_safe { - message::info(&format!("Accepted connection from {}", origin)); - } else { - message::user_error(&format!( - "Denied connection from {}. This is not a trusted origin", - origin - )); - - let _ = self - .out - .close(CloseCode::Policy) - .expect("failed to close connection to unsafe origin"); - } - - Ok(()) - } -} - -fn watch_for_changes(session_id: String, ws_port: u16) -> Result<(), failure::Error> { - //start up the websocket server. - let server = WebSocket::new(|out| FiddleMessageServer { out })? - .bind(format!("localhost:{}", ws_port))?; - let broadcaster = server.broadcaster(); - thread::spawn(move || server.run()); - +fn watch_for_changes(project: &Project, session_id: String, broadcaster: Sender) -> Result<(), failure::Error> { let (tx, rx) = channel(); - watch_and_build(&get_project_config()?, Some(tx))?; + watch_and_build(project, Some(tx))?; while let Ok(_e) = rx.recv() { - if let Ok(new_id) = upload_and_get_id() { + if let Ok(new_id) = upload_and_get_id(project) { let msg = FiddleMessage { session_id: session_id.clone(), data: FiddleMessageData::LiveReload { new_id }, @@ -235,24 +170,14 @@ struct Preview { id: String, } -fn upload_and_get_id() -> Result { +fn upload_and_get_id(project: &Project) -> Result { let create_address = "https://cloudflareworkers.com/script"; let client = http::client(); - let res = match get_project_config()?.project_type { - ProjectType::Rust => client + let res = client .post(create_address) - .multipart(publish::build_multipart_script()?) - .send(), - ProjectType::JavaScript => client - .post(create_address) - .body(publish::build_js_script()?) - .send(), - ProjectType::Webpack => client - .post(create_address) - .multipart(publish::build_webpack_form()?) - .send(), - }; + .multipart(build_script_upload_form(project)?) + .send(); let p: Preview = serde_json::from_str(&res?.text()?)?; From fed1314381f6bdaeba4081d9832f039a13be0288 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 22 Jul 2019 14:10:09 -0500 Subject: [PATCH 27/63] fixed debug save_origins, cargo_fmt, added safe_origins log message --- src/commands/publish/preview/fiddle_messenger.rs | 10 +++++----- src/commands/publish/preview/mod.rs | 7 +++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index c46e544c3..d4b5c5d9e 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -1,6 +1,6 @@ +use crate::terminal::message; use serde::Serialize; use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender}; -use crate::terminal::message; //for now, this is only used by livereloading. //in the future we may use this websocket for other things @@ -27,16 +27,16 @@ pub struct FiddleMessageServer { impl Handler for FiddleMessageServer { fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { #[cfg(not(debug_assertions))] - const SAFE_ORIGINS: &[&str] = &[ - "https://cloudflareworkers.com/", - ]; + const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com/"]; #[cfg(debug_assertions)] const SAFE_ORIGINS: &[&str] = &[ "https://cloudflareworkers.com/", - "https://localhost", //trailing slash ommitted to allow for any port + "http://localhost", //trailing slash ommitted to allow for any port ]; + message::preview(&format!("Allowing connections from {:?}", SAFE_ORIGINS)); + let origin = handshake.request.origin()?.unwrap_or("unknown"); let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 95b22bdca..680f3bcce 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -3,7 +3,6 @@ use std::process::Command; mod fiddle_messenger; use fiddle_messenger::*; - mod http_method; pub use http_method::HTTPMethod; @@ -21,7 +20,7 @@ use super::upload_form::build_script_upload_form; use std::sync::mpsc::channel; use std::thread; -use ws::{WebSocket, Sender}; +use ws::{Sender, WebSocket}; pub fn preview( project: &Project, @@ -63,7 +62,7 @@ pub fn preview( if livereload { let server = WebSocket::new(|out| FiddleMessageServer { out })? - .bind(format!("localhost:{}", ws_port))?; + .bind(format!("localhost:{}", ws_port))?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); watch_for_changes(project, session.to_string(), broadcaster)?; @@ -86,7 +85,7 @@ fn open( let browser_preview = if install::target::DEBUG { format!( - "http://localhost:3000/src/test/manual/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", + "http://localhost:3000/src/test/manual/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", session_id, ws_port, script_id, https_str, preview_host, ) } else { From 41fdab0024f0d4056babd963b32a7b663148847e Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 22 Jul 2019 16:09:59 -0500 Subject: [PATCH 28/63] updated preview url --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 680f3bcce..e450e3e86 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -85,7 +85,7 @@ fn open( let browser_preview = if install::target::DEBUG { format!( - "http://localhost:3000/src/test/manual/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", + "https://cloudflareworkers.com/ui/3.3.2-hotreload.1/index.html?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", session_id, ws_port, script_id, https_str, preview_host, ) } else { From ed5a683c5092ffa54c982a6679ad10c86d8b391c Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 23 Jul 2019 13:09:30 -0500 Subject: [PATCH 29/63] fix origins --- src/commands/publish/preview/fiddle_messenger.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index d4b5c5d9e..d5700b999 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -27,12 +27,12 @@ pub struct FiddleMessageServer { impl Handler for FiddleMessageServer { fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { #[cfg(not(debug_assertions))] - const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com/"]; + const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com"]; #[cfg(debug_assertions)] const SAFE_ORIGINS: &[&str] = &[ - "https://cloudflareworkers.com/", - "http://localhost", //trailing slash ommitted to allow for any port + "https://cloudflareworkers.com", + "http://localhost", ]; message::preview(&format!("Allowing connections from {:?}", SAFE_ORIGINS)); From 5cbbfb9918475a6a16fa135ed6603b3c0b711224 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 23 Jul 2019 14:12:45 -0500 Subject: [PATCH 30/63] don't use hotreload host for normal open command --- .../publish/preview/fiddle_messenger.rs | 5 +-- src/commands/publish/preview/mod.rs | 43 ++++++++++++++----- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index d5700b999..8d56504c1 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -30,10 +30,7 @@ impl Handler for FiddleMessageServer { const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com"]; #[cfg(debug_assertions)] - const SAFE_ORIGINS: &[&str] = &[ - "https://cloudflareworkers.com", - "http://localhost", - ]; + const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com", "http://localhost"]; message::preview(&format!("Allowing connections from {:?}", SAFE_ORIGINS)); diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index e450e3e86..fc825bd9c 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -50,23 +50,24 @@ pub fn preview( HTTPMethod::Post => post(preview_address, cookie, client, body)?, }; - let ws_port: u16 = 8025; + if livereload { + let ws_port: u16 = 8025; - open( - preview_host, - https, - script_id, - &session.to_string(), - ws_port, - )?; + open_livereload( + preview_host, + https, + script_id, + &session.to_string(), + ws_port, + )?; - if livereload { let server = WebSocket::new(|out| FiddleMessageServer { out })? .bind(format!("localhost:{}", ws_port))?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); watch_for_changes(project, session.to_string(), broadcaster)?; } else { + open(preview_host, https, script_id)?; let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); } @@ -74,7 +75,29 @@ pub fn preview( Ok(()) } -fn open( +fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error>{ + let https_str = if https { "https://" } else { "http://" }; + + let browser_preview = format!( + "https://cloudflareworkers.com/#{}:{}{}", + script_id, https_str, preview_host + ); + let windows_cmd = format!("start {}", browser_preview); + let mac_cmd = format!("open {}", browser_preview); + let linux_cmd = format!("xdg-open {}", browser_preview); + + let _output = if cfg!(target_os = "windows") { + Command::new("cmd").args(&["/C", &windows_cmd]).output()? + } else if cfg!(target_os = "linux") { + Command::new("sh").arg("-c").arg(&linux_cmd).output()? + } else { + Command::new("sh").arg("-c").arg(&mac_cmd).output()? + }; + + Ok(()) +} + +fn open_livereload( preview_host: &str, https: bool, script_id: &str, From 6af51b4e36e72146ff812b5549f9fdeaf4a9f771 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Tue, 23 Jul 2019 14:23:25 -0500 Subject: [PATCH 31/63] remove allowing connections from msg is is confusing --- src/commands/publish/preview/fiddle_messenger.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index 8d56504c1..75eaae6fc 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -32,8 +32,6 @@ impl Handler for FiddleMessageServer { #[cfg(debug_assertions)] const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com", "http://localhost"]; - message::preview(&format!("Allowing connections from {:?}", SAFE_ORIGINS)); - let origin = handshake.request.origin()?.unwrap_or("unknown"); let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { From a63715f2407025843028e840c10c4cee1e3f9871 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 29 Jul 2019 16:27:42 -0500 Subject: [PATCH 32/63] cargo fmt --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index fc825bd9c..564195e99 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -75,7 +75,7 @@ pub fn preview( Ok(()) } -fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error>{ +fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error> { let https_str = if https { "https://" } else { "http://" }; let browser_preview = format!( From 8e6ebff611068cee93874f56c59e0d3d9a845125 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 29 Jul 2019 16:28:12 -0500 Subject: [PATCH 33/63] fix origin check and add localhost check --- .../publish/preview/fiddle_messenger.rs | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index 75eaae6fc..cbf80bd0d 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -32,14 +32,36 @@ impl Handler for FiddleMessageServer { #[cfg(debug_assertions)] const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com", "http://localhost"]; - let origin = handshake.request.origin()?.unwrap_or("unknown"); + const SAFE_ADDRS: &[&str] = &["127.0.0.1", "localhost"]; - let is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, safe_origin| { - is_safe || origin.starts_with(safe_origin) + //origin() returns Result> + let origin = handshake + .request + .origin()? + .unwrap_or("unknown") + .trim_end_matches(|c: char| c == '/' || c == ':' || c.is_numeric()); + + //remote_addr returns Result> + let incoming = handshake.remote_addr()?; + let incoming = incoming.as_ref().map_or("unknown", String::as_str); + + //only allow connections from cloudflareworkers.com + let origin_is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, &safe_origin| { + //remove the port/slashes from the end so we can compare safely, instead of checking the + //prefix which is a security issue. + is_safe || origin == safe_origin }); - if is_safe { - message::info(&format!("Accepted connection from {}", origin)); + //only allow incoming websocket connections from localhost/current machine. + let addr_is_safe = SAFE_ADDRS.iter().fold(false, |is_safe, &safe_addr| { + is_safe || incoming == safe_addr + }); + + if origin_is_safe && addr_is_safe { + message::info(&format!( + "Accepted connection from site {} incoming from {}", + origin, incoming + )); } else { message::user_error(&format!( "Denied connection from {}. This is not a trusted origin", From 359f16b6bee12a5e331efa0c55522bc45030cb98 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 29 Jul 2019 16:31:33 -0500 Subject: [PATCH 34/63] better errors --- .../publish/preview/fiddle_messenger.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index cbf80bd0d..ab9edcf3a 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -32,7 +32,7 @@ impl Handler for FiddleMessageServer { #[cfg(debug_assertions)] const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com", "http://localhost"]; - const SAFE_ADDRS: &[&str] = &["127.0.0.1", "localhost"]; + const SAFE_ADDRS: &[&str] = &["127.0.0.1", "localhost", "::1"]; //origin() returns Result> let origin = handshake @@ -63,10 +63,19 @@ impl Handler for FiddleMessageServer { origin, incoming )); } else { - message::user_error(&format!( - "Denied connection from {}. This is not a trusted origin", - origin - )); + if !origin_is_safe { + message::user_error(&format!( + "Denied connection from site {}. This is not a trusted origin", + origin + )); + } + + if !addr_is_safe { + message::user_error(&format!( + "Denied connection originating from {} which is outside this machine", + incoming + )); + } let _ = self .out From f86c5a6ace75f9631f9ab8df3abcf69ab657b834 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 16:02:11 -0500 Subject: [PATCH 35/63] cargo fmt --- src/commands/build/wranglerjs/mod.rs | 5 ++++- src/commands/publish/preview/mod.rs | 14 +++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index eb1cfd753..432cb3ed4 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -105,7 +105,10 @@ pub fn run_build_and_watch( Ok(()) } -fn write_wranglerjs_output(bundle: &Bundle, output: &WranglerjsOutput) -> Result<(), failure::Error> { +fn write_wranglerjs_output( + bundle: &Bundle, + output: &WranglerjsOutput, +) -> Result<(), failure::Error> { if output.has_errors() { message::user_error(output.get_errors().as_str()); failure::bail!("Webpack returned an error"); diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 564195e99..99bd7be2f 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -12,11 +12,11 @@ use crate::commands::watch_and_build; use serde::Deserialize; use uuid::Uuid; +use super::upload_form::build_script_upload_form; use crate::http; use crate::install; use crate::settings::project::Project; use crate::terminal::message; -use super::upload_form::build_script_upload_form; use std::sync::mpsc::channel; use std::thread; @@ -162,7 +162,11 @@ fn post( Ok(res?.text()?) } -fn watch_for_changes(project: &Project, session_id: String, broadcaster: Sender) -> Result<(), failure::Error> { +fn watch_for_changes( + project: &Project, + session_id: String, + broadcaster: Sender, +) -> Result<(), failure::Error> { let (tx, rx) = channel(); watch_and_build(project, Some(tx))?; @@ -197,9 +201,9 @@ fn upload_and_get_id(project: &Project) -> Result { let client = http::client(); let res = client - .post(create_address) - .multipart(build_script_upload_form(project)?) - .send(); + .post(create_address) + .multipart(build_script_upload_form(project)?) + .send(); let p: Preview = serde_json::from_str(&res?.text()?)?; From 77d3064c712dccecbf1dc8e2c3cf416a70bb118b Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 16:25:42 -0500 Subject: [PATCH 36/63] DRY open browser function --- src/commands/publish/preview/mod.rs | 66 ++++++----------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 99bd7be2f..dd84806f3 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -34,6 +34,7 @@ pub fn preview( let preview_host = "example.com"; let https = true; + let https_str = if https { "https://" } else { "http://" }; let script_id = &upload_and_get_id(project)?; let preview_address = "https://00000000000000000000000000000000.cloudflareworkers.com"; @@ -53,13 +54,10 @@ pub fn preview( if livereload { let ws_port: u16 = 8025; - open_livereload( - preview_host, - https, - script_id, - &session.to_string(), - ws_port, - )?; + open_browser(&format!( + "https://cloudflareworkers.com/ui/staging/index.html?session_id={}\\&ws_port={}\\&hide_editor#{}:{}{}", + &session.to_string(), ws_port, script_id, https_str, preview_host, + ))?; let server = WebSocket::new(|out| FiddleMessageServer { out })? .bind(format!("localhost:{}", ws_port))?; @@ -67,7 +65,10 @@ pub fn preview( thread::spawn(move || server.run()); watch_for_changes(project, session.to_string(), broadcaster)?; } else { - open(preview_host, https, script_id)?; + open_browser(&format!( + "https://cloudflareworkers.com/#{}:{}{}", + script_id, https_str, preview_host + ))?; let msg = format!("Your worker responded with: {}", worker_res); message::preview(&msg); } @@ -75,51 +76,10 @@ pub fn preview( Ok(()) } -fn open(preview_host: &str, https: bool, script_id: &str) -> Result<(), failure::Error> { - let https_str = if https { "https://" } else { "http://" }; - - let browser_preview = format!( - "https://cloudflareworkers.com/#{}:{}{}", - script_id, https_str, preview_host - ); - let windows_cmd = format!("start {}", browser_preview); - let mac_cmd = format!("open {}", browser_preview); - let linux_cmd = format!("xdg-open {}", browser_preview); - - let _output = if cfg!(target_os = "windows") { - Command::new("cmd").args(&["/C", &windows_cmd]).output()? - } else if cfg!(target_os = "linux") { - Command::new("sh").arg("-c").arg(&linux_cmd).output()? - } else { - Command::new("sh").arg("-c").arg(&mac_cmd).output()? - }; - - Ok(()) -} - -fn open_livereload( - preview_host: &str, - https: bool, - script_id: &str, - session_id: &str, - ws_port: u16, -) -> Result<(), failure::Error> { - let https_str = if https { "https://" } else { "http://" }; - - let browser_preview = if install::target::DEBUG { - format!( - "https://cloudflareworkers.com/ui/3.3.2-hotreload.1/index.html?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", - session_id, ws_port, script_id, https_str, preview_host, - ) - } else { - format!( - "https://cloudflareworkers.com/?session_id={}\\&ws_port={}\\&hide_editor=true#{}:{}{}", - session_id, ws_port, script_id, https_str, preview_host, - ) - }; - let windows_cmd = format!("start {}", browser_preview); - let mac_cmd = format!("open {}", browser_preview); - let linux_cmd = format!("xdg-open {}", browser_preview); +fn open_browser(url: &str) -> Result<(), failure::Error>{ + let windows_cmd = format!("start {}", url); + let mac_cmd = format!("open {}", url); + let linux_cmd = format!("xdg-open {}", url); let _output = if cfg!(target_os = "windows") { Command::new("cmd").args(&["/C", &windows_cmd]).output()? From 5979c5de01df65947eb8e521dd66a4a8b915442e Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 16:40:34 -0500 Subject: [PATCH 37/63] please clippy --- .../publish/preview/fiddle_messenger.rs | 20 +++++++------------ src/commands/publish/preview/mod.rs | 1 - src/main.rs | 7 ++----- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index ab9edcf3a..188885230 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -42,25 +42,19 @@ impl Handler for FiddleMessageServer { .trim_end_matches(|c: char| c == '/' || c == ':' || c.is_numeric()); //remote_addr returns Result> - let incoming = handshake.remote_addr()?; - let incoming = incoming.as_ref().map_or("unknown", String::as_str); + let incoming_addr = handshake.remote_addr()?; + let incoming_addr = incoming_addr.as_ref().map_or("unknown", String::as_str); //only allow connections from cloudflareworkers.com - let origin_is_safe = SAFE_ORIGINS.iter().fold(false, |is_safe, &safe_origin| { - //remove the port/slashes from the end so we can compare safely, instead of checking the - //prefix which is a security issue. - is_safe || origin == safe_origin - }); + let origin_is_safe = SAFE_ORIGINS.iter().any(|safe_origin| &origin == safe_origin); //only allow incoming websocket connections from localhost/current machine. - let addr_is_safe = SAFE_ADDRS.iter().fold(false, |is_safe, &safe_addr| { - is_safe || incoming == safe_addr - }); + let addr_is_safe = SAFE_ADDRS.iter().any(|safe_addr| &incoming_addr == safe_addr); if origin_is_safe && addr_is_safe { message::info(&format!( "Accepted connection from site {} incoming from {}", - origin, incoming + origin, incoming_addr )); } else { if !origin_is_safe { @@ -73,11 +67,11 @@ impl Handler for FiddleMessageServer { if !addr_is_safe { message::user_error(&format!( "Denied connection originating from {} which is outside this machine", - incoming + incoming_addr )); } - let _ = self + self .out .close(CloseCode::Policy) .expect("failed to close connection to unsafe origin"); diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index dd84806f3..d2df6069d 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -14,7 +14,6 @@ use uuid::Uuid; use super::upload_form::build_script_upload_form; use crate::http; -use crate::install; use crate::settings::project::Project; use crate::terminal::message; diff --git a/src/main.rs b/src/main.rs index e7b6e697b..9d71355da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -205,11 +205,8 @@ fn run() -> Result<(), failure::Error> { match matches.occurrences_of("watch") { 1 => { commands::watch_and_build(&project, None)?; - loop { - //we need to keep the main thread "alive" - //watch_and_build has all the messaging we need - //so this loop doesn't actually need to do anything - } + std::thread::park(); + panic!("Wrangler exited early while watching for changes") } _ => commands::build(&project)?, }; From 410de969d642713df5b47c8f6696c10513645dbc Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 16:48:37 -0500 Subject: [PATCH 38/63] namespace query params --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index d2df6069d..27f38ad7d 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -54,7 +54,7 @@ pub fn preview( let ws_port: u16 = 8025; open_browser(&format!( - "https://cloudflareworkers.com/ui/staging/index.html?session_id={}\\&ws_port={}\\&hide_editor#{}:{}{}", + "https://cloudflareworkers.com/ui/staging/index.html?wrangler_session_id={}\\&wrangler_ws_port={}\\&hide_editor#{}:{}{}", &session.to_string(), ws_port, script_id, https_str, preview_host, ))?; From 7781e48da0f0e190ff941ebf681d605ed0d7afdf Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 31 Jul 2019 18:14:57 -0500 Subject: [PATCH 39/63] cargo fmt --- src/commands/publish/preview/fiddle_messenger.rs | 11 +++++++---- src/commands/publish/preview/mod.rs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index 188885230..40caaabee 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -46,10 +46,14 @@ impl Handler for FiddleMessageServer { let incoming_addr = incoming_addr.as_ref().map_or("unknown", String::as_str); //only allow connections from cloudflareworkers.com - let origin_is_safe = SAFE_ORIGINS.iter().any(|safe_origin| &origin == safe_origin); + let origin_is_safe = SAFE_ORIGINS + .iter() + .any(|safe_origin| &origin == safe_origin); //only allow incoming websocket connections from localhost/current machine. - let addr_is_safe = SAFE_ADDRS.iter().any(|safe_addr| &incoming_addr == safe_addr); + let addr_is_safe = SAFE_ADDRS + .iter() + .any(|safe_addr| &incoming_addr == safe_addr); if origin_is_safe && addr_is_safe { message::info(&format!( @@ -71,8 +75,7 @@ impl Handler for FiddleMessageServer { )); } - self - .out + self.out .close(CloseCode::Policy) .expect("failed to close connection to unsafe origin"); } diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 27f38ad7d..2ea2a32db 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -75,7 +75,7 @@ pub fn preview( Ok(()) } -fn open_browser(url: &str) -> Result<(), failure::Error>{ +fn open_browser(url: &str) -> Result<(), failure::Error> { let windows_cmd = format!("start {}", url); let mac_cmd = format!("open {}", url); let linux_cmd = format!("xdg-open {}", url); From 13895c5740bec70d95c984e7846a619abc65c9b8 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 12 Aug 2019 15:28:38 -0500 Subject: [PATCH 40/63] use info@ for fiddle messenger logs --- src/commands/publish/preview/fiddle_messenger.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index 40caaabee..ad5dc38b8 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -1,4 +1,5 @@ use crate::terminal::message; +use log::info; use serde::Serialize; use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender}; @@ -56,10 +57,9 @@ impl Handler for FiddleMessageServer { .any(|safe_addr| &incoming_addr == safe_addr); if origin_is_safe && addr_is_safe { - message::info(&format!( - "Accepted connection from site {} incoming from {}", + info!("Accepted connection from site {} incoming from {}", origin, incoming_addr - )); + ); } else { if !origin_is_safe { message::user_error(&format!( From 04a4f981392883f5e89efb7fbce8d218f303d997 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 12 Aug 2019 15:45:03 -0500 Subject: [PATCH 41/63] better log messages for wranglerjs + use info@ for watching temp file message as to not confuse the user --- src/commands/build/wranglerjs/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index b2997d510..45922c486 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -60,7 +60,7 @@ pub fn run_build_and_watch( let (mut command, temp_file, bundle) = setup_build(project)?; command.arg("--watch=1"); - info!("Running {:?}", command); + info!("Running {:?} in watch mode", command); thread::spawn(move || { let _command_guard = util::GuardedCommand::spawn(command); @@ -70,7 +70,7 @@ pub fn run_build_and_watch( watcher.watch(&temp_file, RecursiveMode::Recursive).unwrap(); - message::info(&format!("watching {:?}", &temp_file)); + info!("watching temp file {:?}", &temp_file); let mut is_first = true; From 0e84b598f840fcf054eadab56c9eac2fca56bf57 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Mon, 12 Aug 2019 15:45:15 -0500 Subject: [PATCH 42/63] fix double build bug --- src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 3e6e92e99..75094e0e9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -228,7 +228,6 @@ fn run() -> Result<(), failure::Error> { _ => false, }; - commands::build(&project)?; commands::preview(&project, method, body, watch)?; } else if matches.subcommand_matches("whoami").is_some() { info!("Getting User settings"); From ced45c16ab136b3048a71162d551651b7da6eefe Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 14 Aug 2019 11:13:55 -0500 Subject: [PATCH 43/63] cleanup fiddle messenger: use ws::Result instead of alias --- src/commands/publish/preview/fiddle_messenger.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/publish/preview/fiddle_messenger.rs b/src/commands/publish/preview/fiddle_messenger.rs index ad5dc38b8..952b678a9 100644 --- a/src/commands/publish/preview/fiddle_messenger.rs +++ b/src/commands/publish/preview/fiddle_messenger.rs @@ -1,7 +1,7 @@ use crate::terminal::message; use log::info; use serde::Serialize; -use ws::{CloseCode, Handler, Handshake, Result as WSResult, Sender}; +use ws::{CloseCode, Handler, Handshake, Sender}; //for now, this is only used by livereloading. //in the future we may use this websocket for other things @@ -26,7 +26,7 @@ pub struct FiddleMessageServer { } impl Handler for FiddleMessageServer { - fn on_open(&mut self, handshake: Handshake) -> WSResult<()> { + fn on_open(&mut self, handshake: Handshake) -> ws::Result<()> { #[cfg(not(debug_assertions))] const SAFE_ORIGINS: &[&str] = &["https://cloudflareworkers.com"]; From a145ce571681941cc920ce414e70b5f857d8559d Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 14 Aug 2019 11:17:49 -0500 Subject: [PATCH 44/63] Keep trying port+1 so you can have multiple previews open --- src/commands/publish/preview/mod.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 7fa6c74dc..ed8c06245 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -49,15 +49,25 @@ pub fn preview( }; if livereload { - let ws_port: u16 = 8025; + let mut ws_port: u16 = 8025; + + let server = loop { + let result = WebSocket::new(|out| FiddleMessageServer { out })? + .bind(format!("127.0.0.1:{}", ws_port)); //explicitly use 127.0.0.1, since localhost can resolve to 2 addresses + + match result { + Ok(server) => break server, + //if 65535-8025 ports are filled, this will cause a panic due to the overflow + //if you are using that many ports, i salute you + Err(_) => ws_port += 1, + } + }; open_browser(&format!( "https://cloudflareworkers.com/ui/staging/index.html?wrangler_session_id={}\\&wrangler_ws_port={}\\&hide_editor#{}:{}{}", &session.to_string(), ws_port, script_id, https_str, preview_host, ))?; - let server = WebSocket::new(|out| FiddleMessageServer { out })? - .bind(format!("localhost:{}", ws_port))?; let broadcaster = server.broadcaster(); thread::spawn(move || server.run()); watch_for_changes(project, session.to_string(), broadcaster)?; From f0a126fdb8db45e84fc6581387def7fbaf712b54 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 14 Aug 2019 11:29:33 -0500 Subject: [PATCH 45/63] also watch entry point for rust --- src/commands/build/watch/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index b804b47b5..69e7fcd61 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -47,6 +47,9 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), let binary_path = install::install(tool_name, "rustwasm")?.binary(tool_name)?; let args = ["build", "--target", "no-modules"]; + let package = Package::new("./")?; + let entry = package.main()?; + thread::spawn(move || { let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); @@ -55,7 +58,8 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), path.push("src"); watcher.watch(&path, RecursiveMode::Recursive).unwrap(); - message::info(&format!("watching {:?}", &path)); + watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); + message::info(&format!("watching {:?} and {:?}", &path, &entry)); loop { match wait_for_changes(&watcher_rx, COOLDOWN_PERIOD) { From 3db191235eba0162ee0ddd3ae86e7d7aa535a137 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Wed, 14 Aug 2019 13:49:14 -0500 Subject: [PATCH 46/63] better update message --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index ed8c06245..a86854c8b 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -146,7 +146,7 @@ fn watch_for_changes( match broadcaster.send(serde_json::to_string(&msg)?) { Ok(_) => { - message::preview("Sent new id to preview!"); + message::preview("Updating preview with changes"); } Err(_e) => message::user_error("communication with preview failed"), } From cb604483ea520253198d37559faf141dcc37ccd0 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Thu, 15 Aug 2019 14:54:11 -0500 Subject: [PATCH 47/63] update preview service url --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index a86854c8b..2294fd123 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -64,7 +64,7 @@ pub fn preview( }; open_browser(&format!( - "https://cloudflareworkers.com/ui/staging/index.html?wrangler_session_id={}\\&wrangler_ws_port={}\\&hide_editor#{}:{}{}", + "https://cloudflareworkers.com/?wrangler_session_id={}\\&wrangler_ws_port={}\\&hide_editor#{}:{}{}", &session.to_string(), ws_port, script_id, https_str, preview_host, ))?; From 930f9203c0d0112cafbe148655a121aa72ef59f3 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 16 Aug 2019 10:37:06 -0500 Subject: [PATCH 48/63] Use strict equality check in wranglerjs/index.js Co-Authored-By: Sven Sauleau --- wranglerjs/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wranglerjs/index.js b/wranglerjs/index.js index 34708971e..25e31fe56 100644 --- a/wranglerjs/index.js +++ b/wranglerjs/index.js @@ -71,7 +71,7 @@ const compilerCallback = (err, stats) => { throw err; } - if (stats.hash != lastHash) { + if (stats.hash !== lastHash) { const assets = stats.compilation.assets; const jsonStats = stats.toJson(); const bundle = { From 73933fb2c043d5d259273b2b0122d9608363ea84 Mon Sep 17 00:00:00 2001 From: Avery Harnish Date: Fri, 16 Aug 2019 10:40:22 -0500 Subject: [PATCH 49/63] Hide editor on wrangler preview without watch --- src/commands/publish/preview/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 47bd1e7cf..3195bc7e1 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -56,7 +56,7 @@ pub fn preview( }; open_browser(&format!( - "https://cloudflareworkers.com/?wrangler_session_id={}\\&wrangler_ws_port={}\\&hide_editor#{}:{}{}", + "https://cloudflareworkers.com/?wrangler_session_id={0}\\&wrangler_ws_port={1}\\&hide_editor#{2}:{3}{4}", &session.to_string(), ws_port, script_id, https_str, preview_host, ))?; @@ -67,7 +67,7 @@ pub fn preview( watch_for_changes(&project, user.as_ref(), session.to_string(), broadcaster)?; } else { open_browser(&format!( - "https://cloudflareworkers.com/#{}:{}{}", + "https://cloudflareworkers.com/?hide_editor#{0}:{1}{2}", script_id, https_str, preview_host ))?; From ae50e37ee9dbc53c485318e10a1edc24b3447db0 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 10:46:47 -0500 Subject: [PATCH 50/63] Better messaging for preview update message --- src/commands/publish/preview/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 3195bc7e1..4a62fd08e 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -148,7 +148,7 @@ fn watch_for_changes( match broadcaster.send(serde_json::to_string(&msg)?) { Ok(_) => { - message::preview("Updating preview with changes"); + message::preview("Updated preview with changes"); } Err(_e) => message::user_error("communication with preview failed"), } From 2f9d2dc79960accabd1c5d46c825dcdaac47f40d Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 10:50:30 -0500 Subject: [PATCH 51/63] use NonRecursive watcher for watch paths that always point to files --- src/commands/build/watch/mod.rs | 4 ++-- src/commands/build/wranglerjs/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 69e7fcd61..924f9b513 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -27,7 +27,7 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); + watcher.watch(&entry, RecursiveMode::NonRecursive).unwrap(); message::info(&format!("watching {:?}", &entry)); loop { @@ -58,7 +58,7 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), path.push("src"); watcher.watch(&path, RecursiveMode::Recursive).unwrap(); - watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); + watcher.watch(&entry, RecursiveMode::NonRecursive).unwrap(); message::info(&format!("watching {:?} and {:?}", &path, &entry)); loop { diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 45922c486..9fde19ba5 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -68,7 +68,7 @@ pub fn run_build_and_watch( let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - watcher.watch(&temp_file, RecursiveMode::Recursive).unwrap(); + watcher.watch(&temp_file, RecursiveMode::NonRecursive).unwrap(); info!("watching temp file {:?}", &temp_file); From ecb1ba9fb2553c86f1d483995f830ccf8544cf57 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 11:14:09 -0500 Subject: [PATCH 52/63] bind to port 0 to allow the OS to assign us a port, instead of using our own logic for picking a port --- src/commands/publish/preview/mod.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 4a62fd08e..1b94fab37 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -41,19 +41,12 @@ pub fn preview( let https_str = if https { "https://" } else { "http://" }; if livereload { - let mut ws_port: u16 = 8025; + let ws_port = WebSocket::new(|out| FiddleMessageServer { out })? + .bind("127.0.0.1:0")? //explicitly use 127.0.0.1, since localhost can resolve to 2 addresses + .local_addr()? + .port(); - let server = loop { - let result = WebSocket::new(|out| FiddleMessageServer { out })? - .bind(format!("127.0.0.1:{}", ws_port)); //explicitly use 127.0.0.1, since localhost can resolve to 2 addresses - - match result { - Ok(server) => break server, - //if 65535-8025 ports are filled, this will cause a panic due to the overflow - //if you are using that many ports, i salute you - Err(_) => ws_port += 1, - } - }; + info!("Opened websocket server on port {}", port); open_browser(&format!( "https://cloudflareworkers.com/?wrangler_session_id={0}\\&wrangler_ws_port={1}\\&hide_editor#{2}:{3}{4}", From 61ed11e3d50f36e78f7ad6e41d54eabd0fd5dd90 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 12:37:46 -0500 Subject: [PATCH 53/63] cargo fmt --- src/commands/build/wranglerjs/mod.rs | 4 +++- src/commands/publish/preview/mod.rs | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 9fde19ba5..6dcdc7948 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -68,7 +68,9 @@ pub fn run_build_and_watch( let (watcher_tx, watcher_rx) = channel(); let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - watcher.watch(&temp_file, RecursiveMode::NonRecursive).unwrap(); + watcher + .watch(&temp_file, RecursiveMode::NonRecursive) + .unwrap(); info!("watching temp file {:?}", &temp_file); diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 1b94fab37..210efaad4 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -13,6 +13,8 @@ use crate::commands; use uuid::Uuid; +use log::info; + use crate::http; use crate::settings::global_user::GlobalUser; use crate::settings::project::Project; @@ -41,12 +43,11 @@ pub fn preview( let https_str = if https { "https://" } else { "http://" }; if livereload { - let ws_port = WebSocket::new(|out| FiddleMessageServer { out })? - .bind("127.0.0.1:0")? //explicitly use 127.0.0.1, since localhost can resolve to 2 addresses - .local_addr()? - .port(); + let server = WebSocket::new(|out| FiddleMessageServer { out })?.bind("127.0.0.1:0")?; //explicitly use 127.0.0.1, since localhost can resolve to 2 addresses + + let ws_port = server.local_addr()?.port(); - info!("Opened websocket server on port {}", port); + info!("Opened websocket server on port {}", ws_port); open_browser(&format!( "https://cloudflareworkers.com/?wrangler_session_id={0}\\&wrangler_ws_port={1}\\&hide_editor#{2}:{3}{4}", From 6e19a8e3c37b24757f8c385db8088019fa9a6e5a Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 14:13:10 -0500 Subject: [PATCH 54/63] Make open_browser more robust --- src/commands/publish/preview/mod.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 210efaad4..3c7d25cf7 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -50,7 +50,7 @@ pub fn preview( info!("Opened websocket server on port {}", ws_port); open_browser(&format!( - "https://cloudflareworkers.com/?wrangler_session_id={0}\\&wrangler_ws_port={1}\\&hide_editor#{2}:{3}{4}", + "https://cloudflareworkers.com/?wrangler_session_id={0}&wrangler_ws_port={1}&hide_editor#{2}:{3}{4}", &session.to_string(), ws_port, script_id, https_str, preview_host, ))?; @@ -84,16 +84,12 @@ pub fn preview( } fn open_browser(url: &str) -> Result<(), failure::Error> { - let windows_cmd = format!("start {}", url); - let mac_cmd = format!("open {}", url); - let linux_cmd = format!("xdg-open {}", url); - let _output = if cfg!(target_os = "windows") { - Command::new("cmd").args(&["/C", &windows_cmd]).output()? + Command::new("start").arg("/B").arg("Wrangler").arg(url).output()? } else if cfg!(target_os = "linux") { - Command::new("sh").arg("-c").arg(&linux_cmd).output()? + Command::new("xdg-open").arg(url).output()? } else { - Command::new("sh").arg("-c").arg(&mac_cmd).output()? + Command::new("open").arg(url).output()? }; Ok(()) From fa4c023ce27de2226dec28dbfda0b159e4bc4cf1 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 15:11:39 -0500 Subject: [PATCH 55/63] cargo fmt --- src/commands/publish/preview/mod.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index 3c7d25cf7..f066a885f 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -85,11 +85,17 @@ pub fn preview( fn open_browser(url: &str) -> Result<(), failure::Error> { let _output = if cfg!(target_os = "windows") { - Command::new("start").arg("/B").arg("Wrangler").arg(url).output()? + Command::new("start") + .arg("/B") + .arg("Wrangler") + .arg(url) + .output()? } else if cfg!(target_os = "linux") { - Command::new("xdg-open").arg(url).output()? + let linux_cmd = format!(r#"xdg-open "{}""#, url); + Command::new("sh").arg("-c").arg(&linux_cmd).output()? } else { - Command::new("open").arg(url).output()? + let mac_cmd = format!(r#"open "{}""#, url); + Command::new("sh").arg("-c").arg(&mac_cmd).output()? }; Ok(()) From 23f1d990eef57381f0b1a2196b52be7dfd9e7860 Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 15:50:24 -0500 Subject: [PATCH 56/63] disable wrangler build --watch for now --- src/main.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/main.rs b/src/main.rs index ab55dd41d..b942c5785 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,12 +95,6 @@ fn run() -> Result<(), failure::Error> { "{} Build your worker", emoji::CRAB )) - .arg( - Arg::with_name("watch") - .help("watch your project for changes and build your worker when they happen") - .long("watch") - .takes_value(false), - ), ) .subcommand( SubCommand::with_name("preview") @@ -204,14 +198,7 @@ fn run() -> Result<(), failure::Error> { info!("Getting project settings"); let project = settings::project::Project::new()?; - match matches.occurrences_of("watch") { - 1 => { - commands::watch_and_build(&project, None)?; - std::thread::park(); - panic!("Wrangler exited early while watching for changes") - } - _ => commands::build(&project)?, - }; + commands::build(&project)?; } else if let Some(matches) = matches.subcommand_matches("preview") { info!("Getting project settings"); let project = settings::project::Project::new()?; From 22c04dfc4e77d08bc4ba815b92eff2d9bbeeb23c Mon Sep 17 00:00:00 2001 From: Matthew Alonso Date: Fri, 16 Aug 2019 15:53:02 -0500 Subject: [PATCH 57/63] PR feedback: namespacing, command matching, remove unnecessary unwraps --- src/commands/build/watch/mod.rs | 14 +++++++------- src/commands/build/watch/watcher.rs | 2 +- src/commands/build/wranglerjs/mod.rs | 14 ++++++-------- src/commands/publish/preview/upload.rs | 1 + src/main.rs | 5 +---- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 924f9b513..bb76178ac 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -7,9 +7,9 @@ use crate::settings::project::{Project, ProjectType}; use crate::terminal::message; use crate::{commands, install}; -use notify::{watcher, RecursiveMode, Watcher}; +use notify::{self, RecursiveMode, Watcher}; use std::env; -use std::sync::mpsc::{channel, Sender}; +use std::sync::mpsc; use std::thread; use std::time::Duration; @@ -17,15 +17,15 @@ pub const COOLDOWN_PERIOD: Duration = Duration::from_millis(2000); /// watch a project for changes and re-build it when necessary, /// outputting a build event to tx. -pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), failure::Error> { +pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), failure::Error> { let project_type = &project.project_type; match project_type { ProjectType::JavaScript => { let package = Package::new("./")?; let entry = package.main()?; thread::spawn(move || { - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + let (watcher_tx, watcher_rx) = mpsc::channel(); + let mut watcher = notify::watcher(watcher_tx, Duration::from_secs(1)).unwrap(); watcher.watch(&entry, RecursiveMode::NonRecursive).unwrap(); message::info(&format!("watching {:?}", &entry)); @@ -51,8 +51,8 @@ pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), let entry = package.main()?; thread::spawn(move || { - let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + let (watcher_tx, watcher_rx) = mpsc::channel(); + let mut watcher = notify::watcher(watcher_tx, Duration::from_secs(1)).unwrap(); let mut path = env::current_dir().expect("current dir"); path.push("src"); diff --git a/src/commands/build/watch/watcher.rs b/src/commands/build/watch/watcher.rs index ad8fb5fd0..cddf1fa47 100644 --- a/src/commands/build/watch/watcher.rs +++ b/src/commands/build/watch/watcher.rs @@ -19,7 +19,7 @@ pub fn wait_for_changes( Ok(Some(path)) => { message::working("Detected changes..."); //wait for cooldown - while let Ok(_e) = rx.recv_timeout(cooldown) { + while let Ok(_) = rx.recv_timeout(cooldown) { message::working("Detected change during cooldown..."); } message::working("Cooldown over, propogating changes..."); diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 6dcdc7948..5002fe882 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -23,7 +23,7 @@ use std::process::Command; use crate::settings::project::Project; use crate::terminal::message; -use notify::{watcher, RecursiveMode, Watcher}; +use notify::{self, RecursiveMode, Watcher}; use std::sync::mpsc::{channel, Sender}; use std::thread; use std::time::Duration; @@ -62,15 +62,14 @@ pub fn run_build_and_watch( info!("Running {:?} in watch mode", command); - thread::spawn(move || { + //Turbofish the result of the closure so we can use ? + thread::spawn::<_, Result<(), failure::Error>>(move || { let _command_guard = util::GuardedCommand::spawn(command); let (watcher_tx, watcher_rx) = channel(); - let mut watcher = watcher(watcher_tx, Duration::from_secs(1)).unwrap(); + let mut watcher = notify::watcher(watcher_tx, Duration::from_secs(1))?; - watcher - .watch(&temp_file, RecursiveMode::NonRecursive) - .unwrap(); + watcher.watch(&temp_file, RecursiveMode::NonRecursive)?; info!("watching temp file {:?}", &temp_file); @@ -115,8 +114,7 @@ fn write_wranglerjs_output( } bundle - .write(output) - .expect("could not write bundle to disk"); + .write(output)?; let msg = format!( "Built successfully, built project size is {}", diff --git a/src/commands/publish/preview/upload.rs b/src/commands/publish/preview/upload.rs index e9ee874d6..a9c888a9b 100644 --- a/src/commands/publish/preview/upload.rs +++ b/src/commands/publish/preview/upload.rs @@ -5,6 +5,7 @@ use crate::settings::project::Project; use crate::terminal::message; use reqwest::Client; use serde::Deserialize; + #[derive(Debug, Deserialize)] struct Preview { id: String, diff --git a/src/main.rs b/src/main.rs index b942c5785..95c6d34fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -214,10 +214,7 @@ fn run() -> Result<(), failure::Error> { None => None, }; - let watch = match matches.occurrences_of("watch") { - 1 => true, - _ => false, - }; + let watch = matches.is_present("watch"); commands::preview(project, user, method, body, watch)?; } else if matches.subcommand_matches("whoami").is_some() { From 462decb54ffde64d3e12551511b3d048856e2d79 Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:09:02 -0500 Subject: [PATCH 58/63] fix(preview): escape & in windows URL --- src/commands/publish/preview/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/commands/publish/preview/mod.rs b/src/commands/publish/preview/mod.rs index f066a885f..b8f211c60 100644 --- a/src/commands/publish/preview/mod.rs +++ b/src/commands/publish/preview/mod.rs @@ -85,11 +85,9 @@ pub fn preview( fn open_browser(url: &str) -> Result<(), failure::Error> { let _output = if cfg!(target_os = "windows") { - Command::new("start") - .arg("/B") - .arg("Wrangler") - .arg(url) - .output()? + let url_escaped = url.replace("&", "^&"); + let windows_cmd = format!("start {}", url_escaped); + Command::new("cmd").args(&["/C", &windows_cmd]).output()? } else if cfg!(target_os = "linux") { let linux_cmd = format!(r#"xdg-open "{}""#, url); Command::new("sh").arg("-c").arg(&linux_cmd).output()? From d1ab8b3750093f834a5ee08fd6e2296b115244dd Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:10:52 -0500 Subject: [PATCH 59/63] fix(style): appease cargo fmt --- src/commands/build/watch/mod.rs | 5 ++++- src/commands/build/wranglerjs/mod.rs | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index bb76178ac..03d172834 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -17,7 +17,10 @@ pub const COOLDOWN_PERIOD: Duration = Duration::from_millis(2000); /// watch a project for changes and re-build it when necessary, /// outputting a build event to tx. -pub fn watch_and_build(project: &Project, tx: Option>) -> Result<(), failure::Error> { +pub fn watch_and_build( + project: &Project, + tx: Option>, +) -> Result<(), failure::Error> { let project_type = &project.project_type; match project_type { ProjectType::JavaScript => { diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 5002fe882..7b5578e67 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -113,8 +113,7 @@ fn write_wranglerjs_output( failure::bail!("Webpack returned an error"); } - bundle - .write(output)?; + bundle.write(output)?; let msg = format!( "Built successfully, built project size is {}", From 226b21275729abfae9755c07803abbb95acbf438 Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:16:16 -0500 Subject: [PATCH 60/63] fix(clippy): unecessary if let to is_some --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 95c6d34fb..4effd21b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -194,7 +194,7 @@ fn run() -> Result<(), failure::Error> { None => None, }; commands::init(name, project_type)?; - } else if let Some(matches) = matches.subcommand_matches("build") { + } else if matches.subcommand_matches("build").is_some() { info!("Getting project settings"); let project = settings::project::Project::new()?; From 543d412f7d9e7566876477e25ce101dc3f551ec5 Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:31:45 -0500 Subject: [PATCH 61/63] fix(watch): recurisve plz k thx --- src/commands/build/watch/mod.rs | 2 +- src/commands/build/wranglerjs/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 03d172834..77f08f4b0 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -30,7 +30,7 @@ pub fn watch_and_build( let (watcher_tx, watcher_rx) = mpsc::channel(); let mut watcher = notify::watcher(watcher_tx, Duration::from_secs(1)).unwrap(); - watcher.watch(&entry, RecursiveMode::NonRecursive).unwrap(); + watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); message::info(&format!("watching {:?}", &entry)); loop { diff --git a/src/commands/build/wranglerjs/mod.rs b/src/commands/build/wranglerjs/mod.rs index 7b5578e67..c4ddc309c 100644 --- a/src/commands/build/wranglerjs/mod.rs +++ b/src/commands/build/wranglerjs/mod.rs @@ -69,7 +69,7 @@ pub fn run_build_and_watch( let (watcher_tx, watcher_rx) = channel(); let mut watcher = notify::watcher(watcher_tx, Duration::from_secs(1))?; - watcher.watch(&temp_file, RecursiveMode::NonRecursive)?; + watcher.watch(&temp_file, RecursiveMode::Recursive)?; info!("watching temp file {:?}", &temp_file); From ada6ae2d9139d6138f34e58fa950189ea8be35ff Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:46:45 -0500 Subject: [PATCH 62/63] fix(depr): ... -> ..= --- src/commands/build/wranglerjs/output.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/build/wranglerjs/output.rs b/src/commands/build/wranglerjs/output.rs index ec76c2967..5cd70de03 100644 --- a/src/commands/build/wranglerjs/output.rs +++ b/src/commands/build/wranglerjs/output.rs @@ -63,8 +63,8 @@ impl WranglerjsOutput { }; match compressed_size { - WARN_THRESHOLD...MAX_PROJECT_SIZE => format!("{}. {2} Your built project is {} away from reaching the 1MiB size limit. {2}", human_size, human_leftover.expect("failed to get leftover bytes"), emoji::WARN), - 0...MAX_BEFORE_WARN => format!("{}.", human_size), + WARN_THRESHOLD..=MAX_PROJECT_SIZE => format!("{}. {2} Your built project is {} away from reaching the 1MiB size limit. {2}", human_size, human_leftover.expect("failed to get leftover bytes"), emoji::WARN), + 0..=MAX_BEFORE_WARN => format!("{}.", human_size), _ => format!("{}. {1} Your built project has grown past the 1MiB size limit and may fail to deploy. {1}", human_size, emoji::WARN) } } From 52415ae690555f5f188e683678ec38e39293129d Mon Sep 17 00:00:00 2001 From: Ashley Williams Date: Fri, 16 Aug 2019 16:50:18 -0500 Subject: [PATCH 63/63] fix(preview): one last recursive --- src/commands/build/watch/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/build/watch/mod.rs b/src/commands/build/watch/mod.rs index 77f08f4b0..4bed4832c 100644 --- a/src/commands/build/watch/mod.rs +++ b/src/commands/build/watch/mod.rs @@ -61,7 +61,7 @@ pub fn watch_and_build( path.push("src"); watcher.watch(&path, RecursiveMode::Recursive).unwrap(); - watcher.watch(&entry, RecursiveMode::NonRecursive).unwrap(); + watcher.watch(&entry, RecursiveMode::Recursive).unwrap(); message::info(&format!("watching {:?} and {:?}", &path, &entry)); loop {