diff --git a/jest.config.ts b/jest.config.ts index f2efca96..95eed4fe 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -159,7 +159,7 @@ export default { // testRunner: "jasmine2", // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href - testURL: 'http://localhost:7000', + testURL: 'http://localhost:7000/?sitekey=imbatman', // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" // timers: "real", diff --git a/package.json b/package.json index 9bbe1106..66537142 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@types/jsdom": "^16.2.10", "@types/node": "^15.0.2", "@types/sinon": "^10.0.0", + "@wasm-tool/wasm-pack-plugin": "^1.4.0", "css-loader": "^5.2.4", "css-minimizer-webpack-plugin": "^2.0.0", "dart-sass": "^1.25.0", diff --git a/src/pages/panel/sitekey/view.rs b/src/pages/panel/sitekey/view.rs index 54844859..4d629bfd 100644 --- a/src/pages/panel/sitekey/view.rs +++ b/src/pages/panel/sitekey/view.rs @@ -43,15 +43,17 @@ struct Level { struct IndexPage { duration: u32, name: String, + key: String, levels: Vec, } impl IndexPage { - fn new(config: McaptchaConfig, levels: Vec) -> Self { + fn new(config: McaptchaConfig, levels: Vec, key: String) -> Self { IndexPage { duration: config.duration as u32, name: config.name, levels, + key, } } } @@ -91,7 +93,7 @@ pub async fn view_sitekey( let (stats, levels) = try_join!(Stats::new(&key, &data.db), levels_fut)?; - let body = IndexPage::new(config, levels).render_once().unwrap(); + let body = IndexPage::new(config, levels, key).render_once().unwrap(); Ok(HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(body)) diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 7b0aea0d..a7b83830 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -46,6 +46,20 @@ macro_rules! post_request { }; } +#[macro_export] +macro_rules! get_works { + ($app:expr,$route:expr ) => { + let list_sitekey_resp = test::call_service( + &mut $app, + test::TestRequest::get() + .uri($route) + .to_request(), + ) + .await; + assert_eq!(list_sitekey_resp.status(), StatusCode::OK); + }; +} + #[macro_export] macro_rules! get_app { () => { diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 3a3cdf98..64feda74 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -14,27 +14,41 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +use std::borrow::Cow; + +use actix_web::body::Body; +use actix_web::{get, http::header, web, HttpResponse, Responder}; +use mime_guess::from_path; +use rust_embed::RustEmbed; +use lazy_static::lazy_static; +use sailfish::TemplateOnce; + +use crate::errors::*; + + + pub const WIDGET_ROUTES: routes::Widget = routes::Widget::new(); pub mod routes { pub struct Widget { pub verification_widget: &'static str, + pub js: &'static str, + pub wasm: &'static str, } impl Widget { pub const fn new() -> Self { - Widget { verification_widget: "/widget" } + Widget { + verification_widget: "/widget", + js: "/widget/bundle.js", + wasm: "/widget/1476099975f2b060264c.module.wasm", + } } } } -use actix_web::{web, HttpResponse, Responder}; -use lazy_static::lazy_static; -use sailfish::TemplateOnce; - -use crate::errors::*; #[derive(TemplateOnce, Clone)] #[template(path = "widget/index.html")] @@ -60,14 +74,42 @@ async fn show_widget() -> PageResult { .body(&*INDEX_PAGE)) } +#[derive(RustEmbed)] +#[folder = "static/widget/"] +struct WidgetAssets; -pub fn services(cfg: &mut web::ServiceConfig) { - cfg.service(show_widget); +fn handle_widget_assets(path: &str) -> HttpResponse { + match WidgetAssets::get(path) { + Some(content) => { + let body: Body = match content { + Cow::Borrowed(bytes) => bytes.into(), + Cow::Owned(bytes) => bytes.into(), + }; + + HttpResponse::Ok() + .set(header::CacheControl(vec![header::CacheDirective::MaxAge( + crate::CACHE_AGE, + )])) + .content_type(from_path(path).first_or_octet_stream().as_ref()) + .body(body) + } + None => HttpResponse::NotFound().body("404 Not Found"), + } } +#[get("/widget/{_:.*}")] +pub async fn widget_assets(path: web::Path) -> impl Responder { + handle_widget_assets(&path.0) +} + +pub fn services(cfg: &mut web::ServiceConfig) { + cfg.service(show_widget); + cfg.service(widget_assets); +} + #[cfg(test)] mod test { use actix_web::http::StatusCode; @@ -77,18 +119,20 @@ mod test { #[actix_rt::test] async fn captcha_widget_route_works() { + let mut app = get_app!().await; +// let list_sitekey_resp = test::call_service( +// &mut app, +// test::TestRequest::get() +// .uri(crate::WIDGET_ROUTES.verification_widget) +// .to_request(), +// ) +// .await; +// assert_eq!(list_sitekey_resp.status(), StatusCode::OK); - - let list_sitekey_resp = test::call_service( - &mut app, - test::TestRequest::get() - .uri(crate::WIDGET_ROUTES.verification_widget) - .to_request(), - ) - .await; - - assert_eq!(list_sitekey_resp.status(), StatusCode::OK); - + get_works!(app, crate::WIDGET_ROUTES.verification_widget); + get_works!(app, crate::WIDGET_ROUTES.js); + get_works!(app, crate::WIDGET_ROUTES.wasm); + } } diff --git a/static/widget/1476099975f2b060264c.module.wasm b/static/widget/1476099975f2b060264c.module.wasm new file mode 100644 index 00000000..016d531f Binary files /dev/null and b/static/widget/1476099975f2b060264c.module.wasm differ diff --git a/static/widget/bundle.js b/static/widget/bundle.js new file mode 100644 index 00000000..4852999f --- /dev/null +++ b/static/widget/bundle.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,n,t,r,o,i={180:(e,n,t)=>{t.d(n,{Nj:()=>r,Z6:()=>o,yY:()=>i,yM:()=>a});var r=function(){var e;return function(){if(null==e&&null==(e=new URL(window.location.href).searchParams.get("sitekey")))throw console.error(window.location.href),new Error("Define sitekey in query parameter)");return e}()},o={getConfig:"/api/v1/pow/config",verififyPoW:"/api/v1/pow/verify"},i=function(){var e;return function(){if(null==e&&null==(e=document.getElementById("widget__verification-checkbox")))throw new Error("mCaptcha button not found)");return e}()},a=function(){var e,n,t,r;return{before:function(){if(null==e&&null==(e=document.querySelector(".widget__verification-text--before")))throw new Error("before element not found)");return e},after:function(){if(null==n&&null==(n=document.querySelector(".widget__verification-text--after")))throw new Error("after element not found)");return n},during:function(){if(null==t&&null==(t=document.querySelector(".widget__verification-text--during")))throw new Error("before during not found)");return t},error:function(){if(null==r&&null==(r=document.querySelector(".widget__verification-text--error")))throw new Error("before error not found)");return r}}}},731:(e,n,t)=>{t.d(n,{Z:()=>i});var r=t(525),o=t(180);const i=function(){return e=void 0,n=void 0,i=function(){var e,n,t;return function(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{t.a(e,(async e=>{var n=t(720),r=t(731),o=t(792),i=t(243),a=t(180),c=e([n]);n=(c.then?await c:c)[0];var u=function(e){return t=void 0,c=void 0,l=function(){var t,c,u;return function(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{t.a(e,(async e=>{t.d(n,{Z:()=>a});var r=t(838),o=t(180),i=e([r]);r=(i.then?await i:i)[0];const a=function(e){return n=void 0,t=void 0,a=function(){var n,t;return function(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{t.d(n,{Z:()=>r});const r=function(e){window.parent.postMessage(e,"*")}},792:(e,n,t)=>{t.d(n,{Z:()=>i});var r=t(525),o=t(180);const i=function(e){return n=void 0,t=void 0,a=function(){var n,t,i;return function(e,n){var t,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(t)throw new TypeError("Generator is already executing.");for(;a;)try{if(t=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!((o=(o=a.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{t.d(n,{Z:()=>r});const r=function(e){return{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}}},838:(e,n,t)=>{t.a(e,(async r=>{t.d(n,{I:()=>h});var o=t(716);e=t.hmd(e);var i=r([o]);o=(i.then?await i:i)[0];let a=0,c=null;function u(){return null!==c&&c.buffer===o.memory.buffer||(c=new Uint8Array(o.memory.buffer)),c}let l=new("undefined"==typeof TextEncoder?(0,e.require)("util").TextEncoder:TextEncoder)("utf-8");const f="function"==typeof l.encodeInto?function(e,n){return l.encodeInto(e,n)}:function(e,n){const t=l.encode(e);return n.set(t),{read:e.length,written:t.length}};function s(e,n,t){if(void 0===t){const t=l.encode(e),r=n(t.length);return u().subarray(r,r+t.length).set(t),a=t.length,r}let r=e.length,o=n(r);const i=u();let c=0;for(;c127)break;i[o+c]=n}if(c!==r){0!==c&&(e=e.slice(c)),o=t(o,r,r=c+3*e.length);const n=u().subarray(o+c,o+r);c+=f(e,n).written}return a=c,o}let d=null;function p(){return null!==d&&d.buffer===o.memory.buffer||(d=new Int32Array(o.memory.buffer)),d}let y=new("undefined"==typeof TextDecoder?(0,e.require)("util").TextDecoder:TextDecoder)("utf-8",{ignoreBOM:!0,fatal:!0});function h(e,n,t){try{const w=o.__wbindgen_add_to_stack_pointer(-16);var r=s(e,o.__wbindgen_malloc,o.__wbindgen_realloc),i=a,c=s(n,o.__wbindgen_malloc,o.__wbindgen_realloc),l=a;o.gen_pow(w,r,i,c,l,t);var f=p()[w/4+0],d=p()[w/4+1];return h=f,b=d,y.decode(u().subarray(h,h+b))}finally{o.__wbindgen_add_to_stack_pointer(16),o.__wbindgen_free(f,d)}var h,b}y.decode()}))},716:(e,n,t)=>{e.exports=t.v(n,e.id,"1476099975f2b060264c")}},a={};function c(e){var n=a[e];if(void 0!==n)return n.exports;var t=a[e]={id:e,loaded:!1,exports:{}};return i[e](t,t.exports,c),t.loaded=!0,t.exports}e="function"==typeof Symbol?Symbol("webpack then"):"__webpack_then__",n="function"==typeof Symbol?Symbol("webpack exports"):"__webpack_exports__",t=e=>{e&&(e.forEach((e=>e.r--)),e.forEach((e=>e.r--?e.r++:e())))},r=e=>!--e.r&&e(),o=(e,n)=>e?e.push(n):r(n),c.a=(i,a,c)=>{var u,l,f,s=c&&[],d=i.exports,p=!0,y=!1,h=(n,t,r)=>{y||(y=!0,t.r+=n.length,n.map(((n,o)=>n[e](t,r))),y=!1)},b=new Promise(((e,n)=>{f=n,l=()=>(e(d),t(s),s=0)}));b[n]=d,b[e]=(e,n)=>{if(p)return r(e);u&&h(u,e,n),o(s,e),b.catch(n)},i.exports=b,a((i=>{if(!i)return l();var a,c;u=(i=>i.map((i=>{if(null!==i&&"object"==typeof i){if(i[e])return i;if(i.then){var a=[];i.then((e=>{c[n]=e,t(a),a=0}));var c={[e]:(e,n)=>(o(a,e),i.catch(n))};return c}}return{[e]:e=>r(e),[n]:i}})))(i);var f=new Promise(((e,t)=>{(a=()=>e(c=u.map((e=>e[n])))).r=0,h(u,a,t)}));return a.r?f:c})).then(l,f),p=!1},c.d=(e,n)=>{for(var t in n)c.o(n,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),c.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:()=>{throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),c.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e;c.g.importScripts&&(e=c.g.location+"");var n=c.g.document;if(!e&&n&&(n.currentScript&&(e=n.currentScript.src),!e)){var t=n.getElementsByTagName("script");t.length&&(e=t[t.length-1].src)}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),c.p=e})(),c.v=(e,n,t,r)=>{var o=fetch(c.p+""+t+".module.wasm");return"function"==typeof WebAssembly.instantiateStreaming?WebAssembly.instantiateStreaming(o,r).then((n=>Object.assign(e,n.instance.exports))):o.then((e=>e.arrayBuffer())).then((e=>WebAssembly.instantiate(e,r))).then((n=>Object.assign(e,n.instance.exports)))},c(404)})(); \ No newline at end of file diff --git a/templates/panel/sitekey/view/index.html b/templates/panel/sitekey/view/index.html index bd5e533b..4af66a65 100644 --- a/templates/panel/sitekey/view/index.html +++ b/templates/panel/sitekey/view/index.html @@ -1,4 +1,5 @@ -<. include!("../../../components/headers/index.html"); .> +<. include!("../../../components/headers/widget-headers.html"); .> + <. include!("../../navbar/index.html"); .>
<. include!("../../header/index.html"); .> @@ -10,7 +11,11 @@

- Sitekey: <.= name .> + Sitekey: <.= name .> + Click here to see CAPTCHA widget in action + +

<. include!("../../../components/footers.html"); .> diff --git a/templates/widget/footer.html b/templates/widget/footer.html index ff0f908f..ca99118b 100644 --- a/templates/widget/footer.html +++ b/templates/widget/footer.html @@ -5,5 +5,7 @@ href="<.= &*crate::VERIFICATIN_WIDGET_CSS .>" /> + + diff --git a/templates/widget/index.ts b/templates/widget/index.ts index 61832223..d74237de 100644 --- a/templates/widget/index.ts +++ b/templates/widget/index.ts @@ -15,11 +15,41 @@ * along with this program. If not, see . */ import './main.scss'; - -const PARENT = window.parent; -const verificationContainer = ( - document.querySelector('.widget__verification-container') -); -verificationContainer.style.display = 'flex'; - -//PARENT.postMessage +//import prove from './runner/prove'; +//import fetchPoWConfig from './runner/fetchPoWConfig'; +//import sendWork from './runner/sendWork'; +//import sendToParent from './runner/sendToParent'; +//import * as CONST from './runner/const'; +// +///** add mcaptcha widget element to DOM */ +//export const register = () => { +// const verificationContainer = ( +// document.querySelector('.widget__verification-container') +// ); +// verificationContainer.style.display = 'flex'; +// +// CONST.btn().addEventListener('click', e => solveCaptchaRunner(e)); +//}; +// +//const solveCaptchaRunner = async (e: Event) => { +// e.preventDefault(); +// // steps: +// +// // 1. hide --before message +// CONST.messageText().before().style.display = 'none'; +// +// // 1. show --during +// CONST.messageText().during().style.display = 'block'; +// // 1. get config +// const config = await fetchPoWConfig(); +// // 2. prove work +// const proof = await prove(config); +// // 3. submit work +// const token = await sendWork(proof); +// // 4. send token +// sendToParent(token); +// // 5. mark checkbox checked +// CONST.btn().checked = true; +//}; +// +//register(); diff --git a/templates/widget/main.scss b/templates/widget/main.scss index 8c131bd7..e3b2bbfc 100644 --- a/templates/widget/main.scss +++ b/templates/widget/main.scss @@ -83,7 +83,7 @@ } .widget__verification-checkbox:checked ~ .widget__verification-text--during { - display: non; + display: none; } .widget__verification-checkbox:checked ~ .widget__verification-text--error { diff --git a/webpack.config.js b/webpack.config.js index 1c393c13..470c0251 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,13 +2,14 @@ const path = require('path'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +//const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin'); module.exports = { devtool: 'inline-source-map', mode: 'development', //mode: 'production', entry: { - bundle: './templates/index.ts', + bundle: './templates/index.ts', mobile: './templates/mobile.ts', verificationWidget: './templates/widget/index.ts', }, @@ -36,14 +37,19 @@ module.exports = { }, ], }, - ], }, resolve: { extensions: ['.ts', '.tsx', '.js'], }, - plugins: [new MiniCssExtractPlugin()], + plugins: [ + new MiniCssExtractPlugin(), +// new WasmPackPlugin({ +// crateDirectory: __dirname, +// outName: "pow.wasm", +// }), + ], optimization: { minimizer: [ // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line @@ -51,4 +57,13 @@ module.exports = { new CssMinimizerPlugin(), ], }, +// experiments: { +// // executeModule: true, +// // outputModule: true, +// //syncWebAssembly: true, +// // topLevelAwait: true, +// asyncWebAssembly: true, +// // layers: true, +// // lazyCompilation: true, +// }, }; diff --git a/yarn.lock b/yarn.lock index d9a9fd47..cba31c6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -696,6 +696,16 @@ dependencies: "@types/yargs-parser" "*" +"@wasm-tool/wasm-pack-plugin@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@wasm-tool/wasm-pack-plugin/-/wasm-pack-plugin-1.4.0.tgz#752e4a6d8fe35477a3c6cafd2ac6b0351f692848" + integrity sha512-zQh0gA7E73dgwhUM9sXX2rsaXsdWUIdK1kMlEhds3oi6ASn+ePxhb/quZweoeo0SjxuETVb0iu+/nxUZ5HxsUQ== + dependencies: + chalk "^2.4.1" + command-exists "^1.2.7" + watchpack "^1.6.0" + which "^2.0.2" + "@webassemblyjs/ast@1.11.0": version "1.11.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" @@ -1372,7 +1382,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1394,7 +1404,7 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -"chokidar@>=2.0.0 <4.0.0": +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -1550,6 +1560,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +command-exists@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -4140,7 +4155,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -6145,6 +6160,24 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.6.0: + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.1" + watchpack@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7"