diff --git a/Cargo.lock b/Cargo.lock index ccff2574a4f2..bb54a5ea56fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2038,6 +2038,7 @@ name = "enso-config" version = "0.1.0" dependencies = [ "config-reader", + "enso-json-to-struct", "enso-prelude", "ensogl", "semver 1.0.16", @@ -2199,6 +2200,16 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "enso-json-to-struct" +version = "0.1.0" +dependencies = [ + "enso-prelude", + "proc-macro2", + "serde", + "serde_json", +] + [[package]] name = "enso-logging" version = "0.3.1" diff --git a/app/gui/config/Cargo.toml b/app/gui/config/Cargo.toml index 72b504e4ae77..6b574e3c7dae 100644 --- a/app/gui/config/Cargo.toml +++ b/app/gui/config/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] ensogl = { path = "../../../lib/rust/ensogl" } enso-prelude = { path = "../../../lib/rust/prelude" } +enso-json-to-struct = { path = "../../../lib/rust/json-to-struct" } semver = "1.0.0" [build-dependencies] diff --git a/app/gui/config/src/lib.rs b/app/gui/config/src/lib.rs index 74910f7494c0..ca71959078b0 100644 --- a/app/gui/config/src/lib.rs +++ b/app/gui/config/src/lib.rs @@ -15,7 +15,7 @@ use enso_prelude::*; -use ensogl::system::web; +use enso_json_to_struct::json_to_struct; @@ -37,37 +37,30 @@ pub fn engine_version_requirement() -> semver::VersionReq { // === Args === // ============ -ensogl::read_args! { - application_config_url: String, - authentication_enabled: bool, - dark_theme: bool, - data_gathering: bool, - debug: bool, - email: Option, - emit_user_timing_measurements: bool, - enable_new_component_browser: bool, - enable_skip_and_freeze: bool, - enable_spector:bool, - entry: String, - frame: bool, - is_in_cloud: bool, - language_server_data: Option, - language_server_rpc: Option, - loader_download_to_init_ratio: f32, - max_before_main_entry_points_time_ms: f32, - namespace: Option, - node_labels: bool, - pkg_js_url: String, - pkg_wasm_url: String, - platform: Option, - preferred_engine_version: Option, - project: Option, - project_manager: Option, - shaders_url: String, - skip_min_version_check: bool, - /// When profiling the application (e.g. with the `./run profile` command), this argument - /// chooses what is profiled. - test_workflow: Option, - theme: String, - use_loader: bool, +json_to_struct!( + "../../../../lib/rust/ensogl/pack/js/src/runner/config.json", + "../../../../app/ide-desktop/lib/content-config/src/config.json" +); + +pub fn read_args() -> Args { + debug_span!("Reading application arguments from JS.").in_scope(|| { + let mut args = Args::default(); + if let Ok(js_app) = ensogl::system::js::app::app() { + for param in js_app.config().params() { + if let Some(value) = param.value() { + let path = format!("{}.value", param.structural_name()); + if let Some(err) = args.set(&path, value) { + error!("{}", err.display()) + } + } + } + } else { + error!("Could not connect to JS application. Using default configuration.") + } + args + }) +} + +lazy_static! { + pub static ref ARGS: Args = read_args(); } diff --git a/app/gui/language/parser-scala/src/jsclient.rs b/app/gui/language/parser-scala/src/jsclient.rs index 6e11a887fac3..f93255497384 100644 --- a/app/gui/language/parser-scala/src/jsclient.rs +++ b/app/gui/language/parser-scala/src/jsclient.rs @@ -32,7 +32,7 @@ impl From for Error { impl From for Error { fn from(jsvalue: JsValue) -> Self { - Error::ScalaException(format!("{:?}", jsvalue)) + Error::ScalaException(format!("{jsvalue:?}")) } } diff --git a/app/gui/src/config.rs b/app/gui/src/config.rs index f1f8d7c5cd24..5bd5cd4c5426 100644 --- a/app/gui/src/config.rs +++ b/app/gui/src/config.rs @@ -57,22 +57,37 @@ impl BackendService { /// Read backend configuration from the web arguments. See also [`web::Arguments`] /// documentation. pub fn from_web_arguments(args: &Args) -> FallibleResult { - if let Some(endpoint) = &args.project_manager { - if args.language_server_rpc.is_some() || args.language_server_data.is_some() { + let endpoint = args.groups.engine.options.project_manager_url.value.as_str(); + let rpc_url_option = &args.groups.engine.options.rpc_url; + let data_url_option = &args.groups.engine.options.data_url; + let rpc_url = rpc_url_option.value.as_str(); + let data_url = data_url_option.value.as_str(); + if !endpoint.is_empty() { + if !rpc_url.is_empty() || !data_url.is_empty() { Err(MutuallyExclusiveOptions.into()) } else { - let endpoint = endpoint.clone(); + let endpoint = endpoint.to_owned(); Ok(Self::ProjectManager { endpoint }) } } else { - match (&args.language_server_rpc, &args.language_server_data) { - (Some(json_endpoint), Some(binary_endpoint)) => { - let json_endpoint = json_endpoint.clone(); - let binary_endpoint = binary_endpoint.clone(); - let default_namespace = || constants::DEFAULT_PROJECT_NAMESPACE.to_owned(); - let namespace = args.namespace.clone().unwrap_or_else(default_namespace); - let missing_project_name = || MissingOption(args.names().project()); - let project_name = args.project.clone().ok_or_else(missing_project_name)?; + match (rpc_url, data_url) { + ("", "") => Ok(default()), + ("", _) => Err(MissingOption(rpc_url_option.__name__.to_owned()).into()), + (_, "") => Err(MissingOption(data_url_option.__name__.to_owned()).into()), + (json_endpoint, binary_endpoint) => { + let json_endpoint = json_endpoint.to_owned(); + let binary_endpoint = binary_endpoint.to_owned(); + let def_namespace = || constants::DEFAULT_PROJECT_NAMESPACE.to_owned(); + let namespace = args.groups.engine.options.namespace.value.clone(); + let namespace = if namespace.is_empty() { def_namespace() } else { namespace }; + let project_name_option = &args.groups.startup.options.project; + let project_name = project_name_option.value.as_str(); + let no_project_name = || MissingOption(project_name_option.__name__.to_owned()); + let project_name = if project_name.is_empty() { + Err(no_project_name()) + } else { + Ok(project_name.to_owned()) + }?; Ok(Self::LanguageServer { json_endpoint, binary_endpoint, @@ -80,9 +95,6 @@ impl BackendService { project_name, }) } - (None, None) => Ok(default()), - (None, _) => Err(MissingOption(args.names().language_server_rpc()).into()), - (_, None) => Err(MissingOption(args.names().language_server_data()).into()), } } } @@ -111,11 +123,11 @@ impl Startup { /// Read configuration from the web arguments. See also [`web::Arguments`] documentation. pub fn from_web_arguments() -> FallibleResult { let backend = BackendService::from_web_arguments(&ARGS)?; - let project_name = ARGS.project.clone().map(Into::into); - let initial_view = match ARGS.project { - Some(_) => InitialView::Project, - None => InitialView::WelcomeScreen, - }; + let project_name = ARGS.groups.startup.options.project.value.as_str(); + let no_project_name = project_name.is_empty(); + let initial_view = + if no_project_name { InitialView::WelcomeScreen } else { InitialView::Project }; + let project_name = (!no_project_name).as_some_from(|| project_name.to_owned().into()); let dom_parent_id = None; Ok(Startup { backend, project_name, initial_view, dom_parent_id }) } diff --git a/app/gui/src/controller/ide/desktop.rs b/app/gui/src/controller/ide/desktop.rs index ac41570b7b9c..cccc38ed4854 100644 --- a/app/gui/src/controller/ide/desktop.rs +++ b/app/gui/src/controller/ide/desktop.rs @@ -120,8 +120,8 @@ impl ManagingProjectAPI for Handle { let name = make_project_name(&template); let name = choose_unique_project_name(&existing_names, &name); let name = ProjectName::new_unchecked(name); - let version = - enso_config::ARGS.preferred_engine_version.as_ref().map(ToString::to_string); + let version = &enso_config::ARGS.groups.engine.options.preferred_version.value; + let version = (!version.is_empty()).as_some_from(|| version.clone()); let action = MissingComponentAction::Install; let create_result = self diff --git a/app/gui/src/ide/initializer.rs b/app/gui/src/ide/initializer.rs index 3f2c08ee449a..f86348a2da77 100644 --- a/app/gui/src/ide/initializer.rs +++ b/app/gui/src/ide/initializer.rs @@ -73,7 +73,7 @@ impl Initializer { config::InitialView::Project => view.switch_view_to_project(), } - if enso_config::ARGS.emit_user_timing_measurements { + if enso_config::ARGS.groups.profile.options.emit_user_timing_measurements.value { ensogl_app.display.connect_profiler_to_user_timing(); } let status_bar = view.status_bar().clone_ref(); @@ -185,7 +185,8 @@ impl WithProjectManager { pub async fn create_project(&self) -> FallibleResult { use project_manager::MissingComponentAction::Install; info!("Creating a new project named '{}'.", self.project_name); - let version = enso_config::ARGS.preferred_engine_version.as_ref().map(ToString::to_string); + let version = &enso_config::ARGS.groups.engine.options.preferred_version.value; + let version = (!version.is_empty()).as_some_from(|| version.clone()); let name = &self.project_name; let response = self.project_manager.create_project(name, &None, &version, &Install); Ok(response.await?.project_id) @@ -244,7 +245,7 @@ pub fn register_views(app: &Application) { type PlaceholderEntryType = ensogl_component::list_view::entry::Label; app.views.register::>(); - if enso_config::ARGS.is_in_cloud { + if enso_config::ARGS.groups.startup.options.platform.value == "web" { app.views.register::(); } } diff --git a/app/gui/src/profile_workflow.rs b/app/gui/src/profile_workflow.rs index d1991efe268a..dd335530f489 100644 --- a/app/gui/src/profile_workflow.rs +++ b/app/gui/src/profile_workflow.rs @@ -17,7 +17,10 @@ pub async fn main() { // Run selected workflow. let need_workflow = "`profile` entry point requires --workflow argument. \ Try --workflow=help to see a list of options."; - let selected = enso_config::ARGS.test_workflow.as_ref().expect(need_workflow); + let selected = &enso_config::ARGS.groups.profile.options.workflow.value; + if selected.is_empty() { + panic!("{need_workflow}"); + } reflect_match!(match selected as options { "collapse_nodes" => profile_collapse_nodes().await, "create_node" => profile_create_node().await, diff --git a/app/gui/view/graph-editor/src/component/node/action_bar.rs b/app/gui/view/graph-editor/src/component/node/action_bar.rs index a793f2c8391c..a3ab453851b8 100644 --- a/app/gui/view/graph-editor/src/component/node/action_bar.rs +++ b/app/gui/view/graph-editor/src/component/node/action_bar.rs @@ -95,7 +95,7 @@ impl Icons { let visibility = ToggleButton::new(); let skip = ToggleButton::new(); display_object.add_child(&visibility); - if ARGS.enable_skip_and_freeze { + if ARGS.groups.feature_preview.options.skip_and_freeze.value { display_object.add_child(&freeze); display_object.add_child(&skip); } @@ -198,12 +198,12 @@ impl Model { self.icons.set_x(-size.x / 2.0); self.place_button_in_slot(&self.icons.visibility, 0); - if ARGS.enable_skip_and_freeze { + if ARGS.groups.feature_preview.options.skip_and_freeze.value { self.place_button_in_slot(&self.icons.skip, 1); self.place_button_in_slot(&self.icons.freeze, 2); } - let buttons_count = if ARGS.enable_skip_and_freeze { + let buttons_count = if ARGS.groups.feature_preview.options.skip_and_freeze.value { // Toggle visualization, skip and freeze buttons. 3 } else { diff --git a/app/gui/view/graph-editor/src/component/node/output/area.rs b/app/gui/view/graph-editor/src/component/node/output/area.rs index fcf974d946fa..910f39a7be17 100644 --- a/app/gui/view/graph-editor/src/component/node/output/area.rs +++ b/app/gui/view/graph-editor/src/component/node/output/area.rs @@ -238,7 +238,8 @@ impl Model { #[profile(Debug)] fn set_label(&self, content: impl Into) { - let str = if ARGS.node_labels { content.into() } else { default() }; + let node_labels = ARGS.groups.style.options.node_labels.value; + let str = if node_labels { content.into() } else { default() }; self.label.set_content(str); } diff --git a/app/gui/view/graph-editor/src/lib.rs b/app/gui/view/graph-editor/src/lib.rs index 2d7f4105864a..f49b16cc91bf 100644 --- a/app/gui/view/graph-editor/src/lib.rs +++ b/app/gui/view/graph-editor/src/lib.rs @@ -109,8 +109,10 @@ const MACOS_TRAFFIC_LIGHTS_VERTICAL_CENTER: f32 = const MAX_ZOOM: f32 = 1.0; fn traffic_lights_gap_width() -> f32 { - let is_macos = ARGS.platform.map(|p| p.is_macos()) == Some(true); - if is_macos && !ARGS.frame { + let platform_str = ARGS.groups.startup.options.platform.value.as_str(); + let platform = web::platform::Platform::try_from(platform_str); + let is_macos = platform.map(|p| p.is_macos()).ok() == Some(true); + if is_macos && !ARGS.groups.window.options.frame.value { MACOS_TRAFFIC_LIGHTS_CONTENT_WIDTH + MACOS_TRAFFIC_LIGHTS_SIDE_OFFSET } else { 0.0 diff --git a/app/gui/view/src/project.rs b/app/gui/view/src/project.rs index 894eacaac773..9c3a4400ace8 100644 --- a/app/gui/view/src/project.rs +++ b/app/gui/view/src/project.rs @@ -148,7 +148,7 @@ pub enum SearcherVariant { impl SearcherVariant { fn new(app: &Application) -> Self { - if ARGS.enable_new_component_browser { + if ARGS.groups.feature_preview.options.new_component_browser.value { Self::ComponentBrowser(app.new_view::()) } else { Self::OldNodeSearcher(Rc::new(app.new_view::())) @@ -261,7 +261,8 @@ impl Model { let code_editor = app.new_view::(); let fullscreen_vis = default(); let debug_mode_popup = debug_mode_popup::View::new(app); - let window_control_buttons = ARGS.is_in_cloud.as_some_from(|| { + let runs_in_web = ARGS.groups.startup.options.platform.value == "web"; + let window_control_buttons = runs_in_web.as_some_from(|| { let window_control_buttons = app.new_view::(); display_object.add_child(&window_control_buttons); scene.layers.panel.add(&window_control_buttons); @@ -446,7 +447,7 @@ impl Deref for View { impl View { /// Constructor. pub fn new(app: &Application) -> Self { - let theme = match ARGS.theme.as_ref() { + let theme = match ARGS.groups.feature_preview.options.theme.value.as_ref() { "dark" => Theme::Dark, _ => Theme::Light, }; diff --git a/app/gui/view/welcome-screen/src/side_menu.rs b/app/gui/view/welcome-screen/src/side_menu.rs index 0c8ceda556c2..7608c847dce7 100644 --- a/app/gui/view/welcome-screen/src/side_menu.rs +++ b/app/gui/view/welcome-screen/src/side_menu.rs @@ -66,7 +66,7 @@ impl Model { fn create_new_project_button(projects_list: &web::Element) -> ClickableElement { let element = web::document.create_element_or_panic("li"); element.set_id(crate::css_id::NEW_PROJECT); - element.set_inner_html(r#"Create a new project"#); + element.set_inner_html(r#"Create a new project"#); projects_list.append_or_warn(&element); ClickableElement::new(element) } @@ -83,7 +83,7 @@ impl Model { fn create_project_list_entry(project_name: &str) -> ClickableElement { let element = web::document.create_element_or_panic("li"); - element.set_inner_html(&format!(r#" {project_name}"#)); + element.set_inner_html(&format!(r#" {project_name}"#)); ClickableElement::new(element) } } diff --git a/app/gui/view/welcome-screen/src/template_cards.rs b/app/gui/view/welcome-screen/src/template_cards.rs index 9fa35039b6a9..c71010dc1f6c 100644 --- a/app/gui/view/welcome-screen/src/template_cards.rs +++ b/app/gui/view/welcome-screen/src/template_cards.rs @@ -36,7 +36,7 @@ struct CardDefinition { const CARD_SPREADSHEETS: CardDefinition = CardDefinition { class: crate::css_class::CARD_SPREADSHEETS, - background_image_url: Some("/assets/spreadsheets.png"), + background_image_url: Some("/spreadsheets.png"), header: "Combine spreadsheets", content: "Glue multiple spreadsheets together to analyse all your data at once.", template: "orders", diff --git a/app/gui/view/welcome-screen/style.css b/app/gui/view/welcome-screen/style.css index e0d172b09dba..437e873f04b7 100644 --- a/app/gui/view/welcome-screen/style.css +++ b/app/gui/view/welcome-screen/style.css @@ -110,7 +110,7 @@ .enso-internal-templates-view .enso-internal-card-geo { flex: 0 0 530px; - background-image: url("/assets/geo.png"); + background-image: url("/geo.png"); background-size: 100%; } @@ -131,6 +131,6 @@ .enso-internal-templates-view .enso-internal-card-visualize { flex: 0 0 820px; - background-image: url("/assets/visualize.png"); + background-image: url("/visualize.png"); background-size: 100% 100%; } diff --git a/app/ide-desktop/lib/client/.eslintrc.cjs b/app/ide-desktop/lib/client/.eslintrc.cjs new file mode 100644 index 000000000000..959c2237639c --- /dev/null +++ b/app/ide-desktop/lib/client/.eslintrc.cjs @@ -0,0 +1,74 @@ +// TODO: Some of the config options are commented out because eslint is not configured properly. +// This will be fixed in the future. +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // 'plugin:@typescript-eslint/recommended-requiring-type-checking', + // 'plugin:@typescript-eslint/strict', + ], + parser: '@typescript-eslint/parser', + plugins: ['jsdoc', '@typescript-eslint'], + root: true, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-this-alias': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/naming-convention': 'error', + // '@typescript-eslint/no-unnecessary-condition': 'error', + // '@typescript-eslint/restrict-template-expressions': [ + // 'error', + // { + // allowAny: true, + // allowBoolean: true, + // }, + // ], + 'jsdoc/check-access': 'warn', + 'jsdoc/check-alignment': 'warn', + 'jsdoc/check-indentation': 'warn', + 'jsdoc/check-line-alignment': 'warn', + 'jsdoc/check-param-names': 'warn', + 'jsdoc/check-property-names': 'warn', + 'jsdoc/check-syntax': 'warn', + 'jsdoc/check-tag-names': 'warn', + 'jsdoc/check-types': 'warn', + 'jsdoc/check-values': 'warn', + 'jsdoc/empty-tags': 'warn', + 'jsdoc/implements-on-classes': 'warn', + 'jsdoc/no-bad-blocks': 'warn', + 'jsdoc/no-defaults': 'warn', + 'jsdoc/no-multi-asterisks': 'warn', + 'jsdoc/no-types': 'warn', + 'jsdoc/no-undefined-types': 'warn', + 'jsdoc/require-asterisk-prefix': 'warn', + 'jsdoc/require-description': 'warn', + // 'jsdoc/require-description-complete-sentence': 'warn, + 'jsdoc/require-file-overview': 'warn', + 'jsdoc/require-hyphen-before-param-description': 'warn', + 'jsdoc/require-jsdoc': 'warn', + 'jsdoc/require-param-description': 'warn', + 'jsdoc/require-param-name': 'warn', + 'jsdoc/require-param-type': 'warn', + 'jsdoc/require-property': 'warn', + 'jsdoc/require-property-description': 'warn', + 'jsdoc/require-property-name': 'warn', + 'jsdoc/require-property-type': 'warn', + 'jsdoc/require-returns-check': 'warn', + 'jsdoc/require-returns-description': 'warn', + 'jsdoc/require-throws': 'warn', + 'jsdoc/require-yields': 'warn', + 'jsdoc/require-yields-check': 'warn', + 'jsdoc/tag-lines': 'warn', + 'jsdoc/valid-types': 'warn', + }, + overrides: [ + { + files: ['*.ts', '*.tsx'], + parserOptions: { + project: ['./tsconfig.json'], + }, + }, + ], +} diff --git a/app/ide-desktop/lib/client/bundle.ts b/app/ide-desktop/lib/client/bundle.ts index 9ab8b75c7118..ee77308038f4 100644 --- a/app/ide-desktop/lib/client/bundle.ts +++ b/app/ide-desktop/lib/client/bundle.ts @@ -1,8 +1,9 @@ /** Script that bundles JS client code. */ -import path from 'node:path' +import path, { dirname } from 'node:path' import esbuild from 'esbuild' import { require_env, require_env_resolved_path } from '../../utils.js' +import { fileURLToPath } from 'node:url' // =================================================== // === Constants provided through the environment. === @@ -17,6 +18,8 @@ const projectManagerInBundlePath = require_env('ENSO_BUILD_PROJECT_MANAGER_IN_BU /** Version of the Engine (backend) that is bundled along with this client build. */ const bundledEngineVersion = require_env('ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION') +export const thisPath = path.resolve(dirname(fileURLToPath(import.meta.url))) + // ================ // === Bundling === // ================ @@ -24,7 +27,7 @@ const bundledEngineVersion = require_env('ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION' const bundlerOptions: esbuild.BuildOptions = { bundle: true, outdir, - entryPoints: ['src/index.js', 'src/preload.cjs'], + entryPoints: ['src/index.ts', 'src/preload.ts'], outbase: 'src', format: 'cjs', outExtension: { '.js': '.cjs' }, diff --git a/app/ide-desktop/lib/client/electron-builder-config.ts b/app/ide-desktop/lib/client/electron-builder-config.ts index 1129b8c17f8a..065b4cd5804d 100644 --- a/app/ide-desktop/lib/client/electron-builder-config.ts +++ b/app/ide-desktop/lib/client/electron-builder-config.ts @@ -168,6 +168,7 @@ const config: Configuration = { await signArchivesMacOs({ appOutDir: appOutDir, productFilename: appName, + // @ts-ignore entitlements: context.packager.config.mac.entitlements, identity: 'Developer ID Application: New Byte Order Sp. z o. o. (NM77WTZJFQ)', }) @@ -176,7 +177,9 @@ const config: Configuration = { notarize({ appBundleId: packager.platformSpecificBuildOptions.appId, appPath: `${appOutDir}/${appName}.app`, + // @ts-ignore appleId: process.env.APPLEID, + // @ts-ignore appleIdPassword: process.env.APPLEIDPASS, }) } diff --git a/app/ide-desktop/lib/client/package.json b/app/ide-desktop/lib/client/package.json index 00b998a1d316..888961ff572f 100644 --- a/app/ide-desktop/lib/client/package.json +++ b/app/ide-desktop/lib/client/package.json @@ -17,24 +17,31 @@ "description": "Enso Data Processing Environment.", "main": "index.cjs", "dependencies": { + "@types/mime-types": "^2.1.1", + "chalk": "^5.2.0", "create-servers": "^3.2.0", + "electron-is-dev": "^2.0.0", "enso-gui-server": "^1.0.0", "mime-types": "^2.1.35", - "@electron/remote": "^2.0.8", - "electron-is-dev": "^2.0.0", + "string-length": "^5.0.1", "yargs": "17.6.2" }, + "comments": { + "electron-builder": "We cannot update it to never version because of NSIS installer issue: https://github.com/enso-org/enso/issues/5169" + }, "devDependencies": { - "electron": "21.3.0", - "electron-builder": "^22.14.13", - "esbuild": "^0.15.14", "crypto-js": "4.1.1", + "electron": "23.0.0", + "electron-builder": "^22.14.13", "electron-notarize": "1.2.2", "enso-copy-plugin": "^1.0.0", - "ts-node": "^10.9.1", - "fast-glob": "^3.2.12" + "esbuild": "^0.15.14", + "fast-glob": "^3.2.12", + "ts-node": "^10.9.1" }, "scripts": { + "typecheck": "npx tsc --noEmit", + "lint": "npx --yes eslint src", "start": "electron ../../../../dist/content -- ", "build": "ts-node bundle.ts", "dist": "ts-node electron-builder-config.ts" diff --git a/app/ide-desktop/lib/client/src/bin/project-manager.ts b/app/ide-desktop/lib/client/src/bin/project-manager.ts new file mode 100644 index 000000000000..8d547671b5b0 --- /dev/null +++ b/app/ide-desktop/lib/client/src/bin/project-manager.ts @@ -0,0 +1,56 @@ +import child_process, { SpawnOptions } from 'child_process' +import * as config from 'config' +import fss from 'node:fs' +import { logger } from 'enso-content-config' +import util from 'node:util' +const execFile = util.promisify(child_process.execFile) + +// ======================= +// === Project Manager === +// ======================= + +/** Return the Project Manager path if it is valid. Otherwise, throw an error. */ +export function pathOrPanic(args: config.Args): string { + let binPath = args.groups.engine.options.projectManagerPath.value + let binExists = fss.existsSync(binPath) + if (!binExists) { + throw new Error(`Could not find the project manager binary at ${binPath}.`) + } + return binPath +} + +/** Executes the Project Manager with given arguments. */ +async function exec(args: config.Args, processArgs: string[]) { + let binPath = pathOrPanic(args) + return await execFile(binPath, processArgs).catch(function (err) { + throw err + }) +} + +/** Spawn Project Manager process. + * + * The standard output and error handles will be redirected to the electron's app output and error + * handles. Input is piped to this process, so it will not be closed, until this process + * finished. */ +export function spawn(args: config.Args, processArgs: string[]): child_process.ChildProcess { + return logger.groupMeasured( + `Starting the backend process with the following options: ${processArgs}`, + () => { + const binPath = pathOrPanic(args) + const stdin = 'pipe' as const + const stdout = 'inherit' as const + const stderr = 'inherit' as const + const stdio = [stdin, stdout, stderr] + const process = child_process.spawn(binPath, processArgs, { stdio }) + logger.log(`Backend has been spawned (pid = ${process.pid}).`) + process.on('exit', code => logger.log(`Backend exited with code ${code}.`)) + return process + } + ) +} + +export async function version(args: config.Args) { + if (args.options.engine.value) { + return await exec(args, ['--version']).then(t => t.stdout) + } +} diff --git a/app/ide-desktop/lib/client/src/bin/server.ts b/app/ide-desktop/lib/client/src/bin/server.ts new file mode 100644 index 000000000000..df5ad46f8eeb --- /dev/null +++ b/app/ide-desktop/lib/client/src/bin/server.ts @@ -0,0 +1,118 @@ +/** @file A simple HTTP server which serves application data to the Electron web-view. */ + +// @ts-expect-error +import createServer from 'create-servers' +import * as fs from 'fs' +import * as mime from 'mime-types' +import * as path from 'path' +import * as portfinder from 'portfinder' +import { logger } from 'enso-content-config' + +// ================= +// === Constants === +// ================= + +const responses = { + ok: 200, +} + +// ====================== +// === URL Parameters === +// ====================== + +/** Construct URL query with the given parameters. For each `key` - `value` pair, + * `key=value` will be added to the query. */ +export function urlParamsFromObject(obj: { [key: string]: string }) { + let params = [] + for (const [key, value] of Object.entries(obj)) { + params.push(`${key}=${encodeURIComponent(value)}`) + } + return params.length == 0 ? '' : '?' + params.join('&') +} + +// ============== +// === Config === +// ============== + +/** Server configuration. */ +export class Config { + dir: string + port: number + constructor(cfg: { dir: string; port: number }) { + this.dir = cfg.dir + this.port = cfg.port + } +} + +// =================== +// === Port Finder === +// =================== + +/** Determines the initial available communication endpoint, starting from the specified port, to + * provide file hosting services. */ +async function findPort(port: number): Promise { + return await portfinder.getPortPromise({ port, startPort: port }) +} + +// ============== +// === Server === +// ============== + +/// A simple server implementation. +/// +/// Initially it was based on `union`, but later we migrated to `create-servers`. Read this topic to +/// learn why: https://github.com/http-party/http-server/issues/483 +export class Server { + config: Config + server: any + constructor(config: Config) { + this.config = config + } + + /** Server constructor. */ + static async create(config: Config): Promise { + let local_config = Object.assign({}, config) + local_config.port = await findPort(local_config.port) + const server = new Server(local_config) + await server.run() + return server + } + + run(): Promise { + return new Promise((resolve, reject) => { + this.server = createServer( + { + http: this.config.port, + handler: this.process.bind(this), + }, + (err: any) => { + if (err) { + logger.error(`Error creating server:`, err.http) + reject(err) + } + logger.log(`Server started on port ${this.config.port}.`) + logger.log(`Serving files from '${process.cwd()}/${this.config.dir}'.`) + resolve() + } + ) + }) + } + + process(request: { url: string }, response: any) { + const url = request.url.split('?')[0] + const resource = url == '/' ? '/index.html' : request.url + let resource_file = `${this.config.dir}${resource}` + fs.readFile(resource_file, (err: any, data: any) => { + if (err) { + logger.error(`Resource '${resource}' not found.`) + } else { + let contentType = mime.contentType(path.extname(resource_file)) + let contentLength = data.length + response.setHeader('Content-Type', contentType) + response.setHeader('Content-Length', contentLength) + response.writeHead(responses.ok) + response.end(data) + } + }) + } +} diff --git a/app/ide-desktop/lib/client/src/config.ts b/app/ide-desktop/lib/client/src/config.ts new file mode 100644 index 000000000000..89ac5936a058 --- /dev/null +++ b/app/ide-desktop/lib/client/src/config.ts @@ -0,0 +1,583 @@ +/** @file Configuration of the application. It extends the web application configuration with + * Electron-specific options. */ + +import chalk from 'chalk' +import * as content from 'enso-content-config' +import * as naming from 'naming' +import * as paths from 'paths' + +// ================= +// === Constants === +// ================= + +export const helpExtendedName = 'helpExtended' +export const helpExtendedOptionName = naming.camelToKebabCase(helpExtendedName) + +// ================== +// === WindowSize === +// ================== + +/** Window size (width and height). */ +export class WindowSize { + static separator = 'x' + constructor(public width: number, public height: number) {} + + /** Constructor of the default window size. */ + static default(): WindowSize { + return new WindowSize(1380, 900) + } + + /** Parses the input text in form of `x`. */ + static parse(arg: string): Error | WindowSize { + const size = arg.split(WindowSize.separator) + const widthStr = size[0] + const heightStr = size[1] + const width = widthStr ? parseInt(widthStr) : NaN + const height = heightStr ? parseInt(heightStr) : NaN + if (isNaN(width) || isNaN(height)) { + return new Error(`Incorrect window size provided '${arg}'.`) + } else { + return new WindowSize(width, height) + } + } + + /** Returns window size in a form of `x`. */ + pretty(): string { + return `${this.width}${WindowSize.separator}${this.height}` + } +} + +// ============== +// === Config === +// ============== + +export const config = content.options.merge( + new content.Group({ + options: { + window: new content.Option({ + passToWebApplication: false, + value: true, + description: + `Display the window. When set to false, only the server runs. An ` + + `alternative client or browser can connect to it.`, + }), + server: new content.Option({ + passToWebApplication: false, + value: true, + description: + `Run the server. When set to false, connect to an existing server on the ` + + `provided port.`, + }), + version: new content.Option({ + passToWebApplication: false, + value: false, + description: `Print the version.`, + }), + help: new content.Option({ + passToWebApplication: false, + value: false, + description: + `Display the common configuration options help page. Use ` + + `'${helpExtendedOptionName}' to see all options.`, + }), + [helpExtendedName]: new content.Option({ + passToWebApplication: false, + value: false, + description: + 'Show all the configuration options help page, including the less-common ' + + 'options.', + }), + engine: new content.Option({ + passToWebApplication: false, + value: true, + description: 'Start the engine process.', + }), + }, + groups: { + window: new content.Group({ + options: { + size: new content.Option({ + passToWebApplication: false, + value: WindowSize.default().pretty(), + description: `Set the initial window size.`, + }), + vibrancy: new content.Option({ + passToWebApplication: false, + value: false, + description: `Enable the vibrancy effect.`, + primary: false, + }), + closeToQuit: new content.Option({ + passToWebApplication: false, + value: process.platform !== 'darwin', + defaultDescription: 'false on MacOS, true otherwise', + description: + `Determine whether the app should quit when the window is closed. ` + + `If set to false, the window will be hidden after pressing the close ` + + `button. You can bring the window back by pressing the app dock icon.`, + primary: false, + }), + }, + }), + server: new content.Group({ + description: + `The configuration settings for the server utilized in delivering web ` + + `application to either Electron or a browser window.`, + options: { + port: new content.Option({ + passToWebApplication: false, + value: 8080, + description: + `Port to use. If the port is unavailable, the next available port is ` + + `used.`, + }), + }, + }), + + performance: new content.Group({ + description: `Performance-related configuration options.`, + options: { + backgroundThrottling: new content.Option({ + passToWebApplication: true, + value: true, + description: 'Throttle animations when run in background.', + }), + + forceHighPerformanceGpu: new content.Option({ + passToWebApplication: false, + value: true, + description: + 'Force using discrete GPU when there are multiple GPUs available.', + }), + + angleBackend: new content.Option({ + passToWebApplication: false, + value: 'default', + description: + `Choose the graphics backend for ANGLE (graphics engine abstraction ` + + `layer). The OpenGL backend is soon to be deprecated on Mac, and may ` + + `contain driver bugs that are not planned to be fixed. The Metal ` + + `backend is still experimental, and may contain bugs that are still ` + + `being worked on. However, the 'metal' backend is less performant ` + + `than the 'default' one on M1 and M2 Macs, so it is disabled for now.`, + }), + ignoreGpuBlocklist: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: + `Override the list of blocked GPU hardware, allowing for ` + + `GPU acceleration on system configurations that do not inherently ` + + `support it. It should be noted that some hardware configurations ` + + `may have driver issues that could result in rendering ` + + `discrepancies. Despite this, the utilization of GPU acceleration ` + + `has the potential to significantly enhance the performance of the ` + + `application in our specific use cases. This behavior can be ` + + `observed in the following example: ` + + `https://groups.google.com/a/chromium.org/g/chromium-dev/c/09NnO6jYT6o.`, + }), + disableSandbox: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: + `Disable the sandbox feature for all process types that are ` + + `typically subjected to sandboxing. This option serves as a ` + + `browser-level switch solely for testing purposes. Although Google ` + + `discourages the use of this option, it is deemed safe for use in ` + + `this particular instance as the browser is exclusively designed to ` + + `display Enso, which already has unrestricted access to all files ` + + `and system settings on the user's machine. This modification has ` + + `been known to result in correct app behavior on certain systems, ` + + `as demonstrated in this example: ` + + `https://github.com/enso-org/enso/issues/3801.`, + }), + disableGpuSandbox: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: + `Disable the GPU process sandbox. It should be noted that on ` + + `certain hardware configurations, the utilization of GPU sandboxing ` + + `may result in WebGL crashes. Despite Google's discouragement of ` + + `this option, it is considered safe for use in this specific ` + + `instance, as the browser is dedicated solely to the display of ` + + `Enso, which has unrestricted access to all files and system ` + + `settings on the user's machine. For a detailed explanation of ` + + `instances where such crashes may occur, please refer to this ` + + `document: https://wiki.archlinux.org/title/chromium.`, + }), + disableGpuVsync: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: + `Disable the GPU Vertical Synchronization (VSync). This feature ` + + `synchronizes the refresh rate and frame rate of the monitor to ` + + `ensure optimal picture quality, particularly in gaming scenarios. ` + + `However, in applications that heavily rely on a graphical user ` + + `interface, the utilization of VSync is not deemed essential. By ` + + `disabling this feature, performance may be improved on hardware ` + + `configurations with limited capabilities. In addition, disabling ` + + `VSync also has the potential to reduce rendering latency. For a ` + + `comprehensive understanding of this aspect, please refer to this ` + + `thread: https://bugs.chromium.org/p/chromium/issues/detail?id=460919.`, + }), + disableSmoothScrolling: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: + `Disable smooth scrolling feature. This modification has the ` + + `potential to reduce latency experienced with input devices. For ` + + `further elaboration, please refer to this thread: ` + + `https://news.ycombinator.com/item?id=28782493.`, + }), + enableNativeGpuMemoryBuffers: new content.Option({ + passToWebApplication: false, + primary: false, + value: true, + description: `Enable native CPU-mappable GPU memory buffer support on Linux.`, + }), + }, + }), + + profile: new content.Group({ + options: { + loadProfile: new content.Option({ + passToWebApplication: false, + value: [] as string[], + description: + `Load a performance profile. For use with developer tools such as ` + + `the 'profiling-run-graph' entry point.`, + primary: false, + }), + saveProfile: new content.Option({ + passToWebApplication: false, + value: '', + description: + `Record a performance profile and save it to a file. To view the ` + + `results, use the 'profiling-run-graph' entry point, such as ` + + `'enso -startup.entry=profiling-run-graph -profile.load-profile=profile.json'.`, + primary: false, + }), + }, + }), + + engine: new content.Group({ + options: { + projectManagerPath: new content.Option({ + passToWebApplication: false, + value: paths.projectManager, + description: + 'Set the path of a local project manager executable to use for ' + + 'running projects.', + primary: false, + }), + }, + }), + + debug: new content.Group({ + options: { + info: new content.Option({ + passToWebApplication: false, + value: false, + description: + `Print the system debug information. It is recommended to copy the ` + + `output of this command when submitting a report regarding any bugs ` + + `encountered.`, + }), + verbose: new content.Option({ + passToWebApplication: false, + value: false, + description: `Increase logs verbosity. Affects both IDE and the backend.`, + }), + devTools: new content.Option({ + passToWebApplication: false, + value: false, + description: 'Run the application in development mode.', + }), + }, + }), + chrome: new content.Group({ + description: + `Chrome and Electron command line options. Please be advised that the ` + + `provided list contains both Electron-specific options as well as a ` + + `selection of Chrome command line options that are officially supported ` + + `by Electron ` + + `(https://www.electronjs.org/docs/latest/api/command-line-switches). It is ` + + `important to note that not all Chrome switches may be compatible with ` + + `Electron. For example, the switch '-chrome.crash-test' is not functional in ` + + `the Electron environment. For a comprehensive collection of Chrome options, ` + + `you may refer to ` + + `https://peter.sh/experiments/chromium-command-line-switches.` + + `\n\n` + + chalk.red(`WARNING: `) + + `Neither the option names nor values undergo validation by ` + + `Chrome due to the lack of an option validation API. This may result in the ` + + `acceptance of invalid options, which will be silently ignored. To verify ` + + `the successful passing of options to Chrome, the use of ` + + `'-chrome.disable-gpu' can be employed as a diagnostic measure, ` + + `effectively preventing the display of WebGL canvas.`, + options: { + // === Electron Options === + // https://www.electronjs.org/docs/latest/api/command-line-switches + + authServerWhitelist: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `A comma-separated list of servers for which integrated ` + + `authentication is enabled.`, + }), + authNegotiateDelegateWhitelist: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `A comma-separated list of servers for which delegation of user ` + + `credentials is required. Without '*' prefix the URL has to match ` + + `exactly.`, + }), + disableNtlmV2: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: 'Disables NTLM v2 for posix platforms, no effect elsewhere.', + }), + disableHttpCache: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: 'Disables the disk cache for HTTP requests.', + }), + disableHttp2: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: 'Disable HTTP/2 and SPDY/3.1 protocols.', + }), + disableRendererBackgrounding: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: + `Prevents Chrome from lowering the priority of invisible pages' ` + + `renderer processes.`, + }), + diskCacheSize: new content.Option({ + passToWebApplication: false, + primary: false, + value: 0, + description: + `Forces the maximum disk space to be used by the disk cache, ` + + `in bytes.`, + }), + enableLogging: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Prints Chrome's logging to stderr (or a log file, if provided as` + + ` argument).`, + }), + forceFieldtrials: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + 'Field trials to be forcefully enabled or disabled. For example, ' + + "'WebRTC-Audio-Red-For-Opus/Enabled/'.", + }), + hostRules: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `A comma-separated list of rules that control how hostnames are ` + + `mapped. For example, 'MAP * 127.0.0.1'.`, + }), + hostResolverRules: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Like '-chrome.host-rules' but these rules only apply to the host ` + + `resolver.`, + }), + ignoreCertificateErrors: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: `Ignores certificate related errors.`, + }), + ignoreConnectionsLimit: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: `Ignore the connections limit for domains list separated by ','.`, + }), + jsFlags: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Specifies the flags passed to the Node.js engine. For example, ` + + `'-chrome.js-flags="--harmony_proxies --harmony_collections"'.`, + }), + lang: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: 'Set a custom locale.', + }), + logFile: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `If '-chrome.enable-logging' is specified, logs will be written to ` + + `the given path. The parent directory must exist.`, + }), + logNetLog: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + 'Enable net log events to be saved and writes them to the provided path.', + }), + logLevel: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Set the verbosity of logging when used together with ` + + `'-chrome.enable-logging'. The argument should be one of Chrome's` + + ` LogSeverities.`, + }), + noProxyServer: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: + `Don't use a proxy server and always make direct connections. ` + + `Overrides any other proxy server flags that are passed.`, + }), + noSandbox: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: + `Disable the Chrome sandbox. Forces renderer process and Chrome ` + + `helper processes to run un-sandboxed. Should only be used for testing.`, + }), + proxyBypassList: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Instruct Electron to bypass the proxy server for the given ` + + `semi-colon-separated list of hosts. This flag has an effect only if ` + + `used in tandem with '-chrome.proxy-server'. For example, ` + + `'-chrome.proxy-bypass-list ";*.google.com;*foo.com;1.2.3.4:5678"'.`, + }), + proxyPacUrl: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: `Use the PAC script at the specified url.`, + }), + proxyServer: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Use a specified proxy server ('address:port'), which overrides the` + + `system setting. This switch only affects requests with HTTP ` + + `protocol, including HTTPS and WebSocket requests. It is also ` + + `noteworthy that not all proxy servers support HTTPS and WebSocket ` + + `requests. The proxy URL does not support username and password ` + + `authentication per ` + + `[Chrome issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).`, + }), + remoteDebuggingPort: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: 'Enables remote debugging over HTTP on the specified port.', + }), + v: new content.Option({ + passToWebApplication: false, + primary: false, + value: 0, + description: + `Gives the default maximal active V-logging level; 0 is the default. ` + + `Normally positive values are used for V-logging levels. This switch ` + + `only works when '-chrome.enable-logging' is also passed.`, + }), + vmodule: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `Gives the per-module maximal V-logging levels to override the value ` + + `given by '-chrome.v'. E.g. 'my_module=2,foo*=3' would change the ` + + `logging level for all code in source files 'my_module.*' and ` + + `'foo*.*'. Any pattern containing a forward or backward slash will ` + + `be tested against the whole pathname and not only the module. ` + + `This switch only works when '-chrome.enable-logging' is also passed.`, + }), + // Please note that this option uses the snake-case naming convention because + // Chrome defines it so. + force_high_performance_gpu: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: + 'Force using discrete GPU when there are multiple GPUs available.', + }), + // Please note that this option uses the snake-case naming convention because + // Chrome defines it so. + force_low_power_gpu: new content.Option({ + passToWebApplication: false, + primary: false, + value: false, + description: + 'Force using integrated GPU when there are multiple GPUs available.', + }), + + enableBlinkFeatures: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `A list of Blink (Chrome's rendering engine) features separated ` + + `by ',' like 'CSSVariables,KeyboardEventKey' to enable. The full ` + + `list of supported feature strings can be found in the ` + + `[RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) ` + + `file.`, + }), + + disableBlinkFeatures: new content.Option({ + passToWebApplication: false, + primary: false, + value: '', + description: + `A list of Blink (Chrome's rendering engine) features separated ` + + `by ',' like 'CSSVariables,KeyboardEventKey' to disable. The full ` + + `list of supported feature strings can be found in the ` + + `[RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) ` + + `file.`, + }), + }, + }), + }, + }) +) +config.groups.window.options.frame.value = process.platform !== 'darwin' +config.groups.startup.options.platform.value = process.platform +// @ts-expect-error +config.groups.engine.options.preferredVersion.value = BUNDLED_ENGINE_VERSION + +export type Args = typeof config diff --git a/app/ide-desktop/lib/client/src/config/parser.ts b/app/ide-desktop/lib/client/src/config/parser.ts new file mode 100644 index 000000000000..0422b48c4fb6 --- /dev/null +++ b/app/ide-desktop/lib/client/src/config/parser.ts @@ -0,0 +1,347 @@ +/** @file Command line options parser. */ + +import chalk from 'chalk' +import buildCfg from '../../../../build.json' +import * as config from 'config' +import yargs from 'yargs/yargs' +import * as naming from 'naming' +import stringLength from 'string-length' +import { hideBin } from 'yargs/helpers' +import { logger } from 'enso-content-config' +import Electron from 'electron' + +// ============ +// === Help === +// ============ + +let usage = + chalk.bold(`\nEnso ${buildCfg.version} command line interface.` + `Usage: enso [options]`) + + `\n\nBoth single-dash and double-dash prefixes are accepted for all options. For ` + + `instance, the help message can be displayed by entering either '--help' or '-help'. The ` + + `'-no-' prefix may be utilized to disable a specific option. For example, to connect to ` + + `the application from a web-browser, the creation of a window can be suppressed by ` + + `entering either '-window=false' or '-no-window'.` + +class Section { + entries: any[] = [] + description = '' + constructor(entries: any[] = []) { + this.entries = entries + } +} + +/** Command line help printer. The `groupsOrdering` parameter specifies the order in which the + * option groups should be printed. Groups not specified will be printed in the definition order. + * + * We use custom help printer because Yargs has several issues: + * 1. The option ordering is random and there is no way to enforce it. + * 2. The option groups ordering is random and there is no way to enforce it. + * 3. Every option has a `[type`] annotation and there is no API to disable it. + * 4. There is no option to print commands with single dash instead of double-dash. + * 5. Help coloring is not supported, and they do not want to support it: + * https://github.com/yargs/yargs/issues/251 + */ +function printHelp(cfg: { args: config.Args; groupsOrdering: string[]; helpExtended: boolean }) { + console.log(usage) + const totalWidth = logger.terminalWidth() ?? 80 + const indentSize = 0 + const optionPrefix = '-' + const spacing = 2 + const sections: { [key: string]: Section } = {} + const topLevelSection = new Section() + topLevelSection.description = + 'General application switches. For fine-grained control, see the available option groups.' + sections['topLevel'] = topLevelSection + for (const groupName of cfg.groupsOrdering) { + sections[groupName] = new Section() + } + let maxOptionLength = 0 + + for (const [groupName, group] of Object.entries(cfg.args.groups)) { + let section = sections[groupName] + if (section == null) { + section = new Section() + sections[groupName] = section + } + section.description = group.description + for (const option of group.optionsRecursive()) { + if (option.primary || cfg.helpExtended) { + const cmdOption = naming.camelToKebabCase(option.qualifiedName()) + maxOptionLength = Math.max(maxOptionLength, stringLength(cmdOption)) + const entry = [cmdOption, option] + section.entries.push(entry) + } + } + } + + for (const [optionName, option] of Object.entries(cfg.args.options)) { + if (option.primary || cfg.helpExtended) { + const cmdOption = naming.camelToKebabCase(optionName) + maxOptionLength = Math.max(maxOptionLength, stringLength(cmdOption)) + const entry = [cmdOption, option] + const section = sections[option.name] + if (section != null) { + section.entries.unshift(entry) + } else { + topLevelSection.entries.push(entry) + } + } + } + + const leftWidth = maxOptionLength + indentSize + stringLength(optionPrefix) + spacing + const rightWidth = totalWidth - leftWidth + + for (const [groupName, section] of Object.entries(sections)) { + if (section.entries.length > 0) { + console.log('\n\n') + const groupTitle = chalk.bold(`${naming.camelCaseToTitle(groupName)} Options `) + console.log(groupTitle) + const description = wordWrap(section.description, totalWidth).join('\n') + console.log(description) + console.log() + section.entries.sort() + for (const [cmdOption, option] of section.entries) { + const indent = ' '.repeat(indentSize) + let left = indent + chalk.bold(chalk.green(optionPrefix + cmdOption)) + const spaces = ' '.repeat(leftWidth - stringLength(left)) + left = left + spaces + + let firstSentenceSplit = option.description.indexOf('. ') + let firstSentence = + firstSentenceSplit == -1 + ? option.description + : option.description.slice(0, firstSentenceSplit + 1) + let otherSentences = option.description.slice(firstSentence.length) + + const def = option.defaultDescription ?? option.default + const defIsEmptyArray = Array.isArray(def) && def.length === 0 + let defaults = '' + if (def != null && def !== '' && !defIsEmptyArray) { + defaults = ` Defaults to ${chalk.green(def)}.` + } + let description = firstSentence + defaults + chalk.gray(otherSentences) + const lines = wordWrap(description, rightWidth).map( + line => line + ' '.repeat(rightWidth - stringLength(line)) + ) + const right = lines.join('\n' + ' '.repeat(leftWidth)) + console.log(left + right) + } + } + } +} + +/** Wraps the text to a specific output width. If a word is longer than the output width, it will be + * split. */ +function wordWrap(str: string, width: number): string[] { + if (width <= 0) { + logger.error(`Cannot perform word wrap. The output width is set to '${width}'.`) + return [] + } + let firstLine = true + let line = '' + const lines = [] + const inputLines = str.split('\n') + for (const inputLine of inputLines) { + if (!firstLine) { + lines.push(line) + line = '' + } + firstLine = false + for (let word of inputLine.split(' ')) { + if (stringLength(word) > width) { + if (line.length > 0) { + lines.push(line) + line = '' + } + const wordChunks = [] + while (stringLength(word) > width) { + wordChunks.push(word.slice(0, width)) + word = word.slice(width) + } + wordChunks.push(word) + for (const wordChunk of wordChunks) { + lines.push(wordChunk) + } + } else { + if (stringLength(line) + stringLength(word) >= width) { + lines.push(line) + line = '' + } + if (line.length != 0) { + line += ' ' + } + line += word + } + } + } + if (line) { + lines.push(line) + } + return lines +} + +// ====================== +// === Chrome Options === +// ====================== + +export class ChromeOption { + constructor(public name: string, public value?: string) {} + + display(): string { + const value = this.value == null ? '' : `=${this.value}` + return `--${this.name}${value}` + } +} + +/** Replaces `-no-...` with `--no-...`. This is a hotfix for Yargs bug: + * https://github.com/yargs/yargs-parser/issues/468 */ +function fixArgvNoPrefix(argv: string[]): string[] { + const singleDashPrefix = '-no-' + const doubleDashPrefix = '--no-' + return argv.map(arg => { + if (arg.startsWith(singleDashPrefix)) { + return doubleDashPrefix + arg.slice(singleDashPrefix.length) + } else { + return arg + } + }) +} + +/** Parse the given list of arguments into two distinct sets: regular arguments and those specific + * to Chrome. */ +function argvAndChromeOptions(processArgs: string[]): { + argv: string[] + chromeOptions: ChromeOption[] +} { + const chromeOptionRegex = /--?chrome.([^=]*)(=(.*))?/ + const argv = [] + const chromeOptions: ChromeOption[] = [] + for (let i = 0; i < processArgs.length; i++) { + const processArg = processArgs[i] + if (processArg != null) { + const match = processArg.match(chromeOptionRegex) + if (match != null) { + const optionName = match[1] as string + const optionValue = match[3] + if (optionValue != null) { + chromeOptions.push(new ChromeOption(optionName, optionValue)) + } else { + const nextArgValue = processArgs[i + 1] + if (nextArgValue != null && !nextArgValue.startsWith('-')) { + chromeOptions.push(new ChromeOption(optionName, nextArgValue)) + i++ + } else { + chromeOptions.push(new ChromeOption(optionName, undefined)) + } + } + } else { + argv.push(processArg) + } + } + } + return { argv, chromeOptions } +} + +// ===================== +// === Option Parser === +// ===================== + +export function parseArgs() { + const args = config.config + const { argv, chromeOptions } = argvAndChromeOptions(fixArgvNoPrefix(hideBin(process.argv))) + + const yargsOptions = args.optionsRecursive().reduce((opts: { [key: string]: any }, option) => { + const yargsParam = Object.assign({}, option) + // @ts-ignore + yargsParam.requiresArg = ['string', 'array'].includes(yargsParam.type) + // @ts-ignore + yargsParam.default = undefined + // @ts-ignore + opts[naming.camelToKebabCase(option.qualifiedName())] = yargsParam + return opts + }, {}) + + let optParser = yargs() + .version(false) + .parserConfiguration({ + // Allow single-dash arguments, like `-help`. + 'short-option-groups': false, + // Treat dot-arguments as string keys, like `foo.bar`. + 'dot-notation': false, + // Makes all flags passed after '--' be one string. + 'populate--': true, + // Do not expand `--foo-bar` to `--fooBar`. This prevents an error when both the former + // and later argument are reported as invalid at the same time. + 'camel-case-expansion': false, + }) + .help(false) + .strict() + .options(yargsOptions) + + // === Parsing === + + let parseError = null as null | Error + let parsedArgs = optParser.parse(argv, {}, (err: Error | undefined) => { + if (err != null) { + parseError = err + } + }) as { [key: string]: any } + const unexpectedArgs = parsedArgs['--'] + + for (const option of args.optionsRecursive()) { + const arg = parsedArgs[naming.camelToKebabCase(option.qualifiedName())] + const isArray = Array.isArray(arg) + // Yargs parses missing array options as `[undefined]`. + const isInvalidArray = isArray && arg.length == 1 && arg[0] == null + if (arg != null && !isInvalidArray) { + option.value = arg + option.setByUser = true + } + } + + let windowSize = config.WindowSize.default() + const providedWindowSize = args.groups.window.options.size.value + const parsedWindowSize = config.WindowSize.parse(providedWindowSize) + + if (parsedWindowSize instanceof Error) { + throw new Error(`Wrong window size provided: '${providedWindowSize}'.`) + } else { + windowSize = parsedWindowSize + } + + const printHelpAndExit = (exitCode?: number) => { + printHelp({ + args, + groupsOrdering: [ + args.groups.loader.name, + args.groups.startup.name, + args.groups.style.name, + args.groups.featurePreview.name, + args.groups.window.name, + args.groups.server.name, + args.groups.engine.name, + args.groups.performance.name, + args.groups.debug.name, + args.groups.profile.name, + args.groups.authentication.name, + args.groups.dataCollection.name, + args.groups.chrome.name, + ], + helpExtended: args.options.helpExtended.value, + }) + process.exit(exitCode) + } + + const helpRequested = args.options.help.value || args.options.helpExtended.value + if (helpRequested) { + printHelpAndExit() + } else if (parseError != null) { + logger.error(parseError.message) + printHelpAndExit(1) + } else if (unexpectedArgs != null) { + logger.error(`Unexpected arguments found: '${unexpectedArgs}'.`) + printHelpAndExit(1) + } + + return { args, windowSize, chromeOptions } +} diff --git a/app/ide-desktop/lib/client/src/debug.ts b/app/ide-desktop/lib/client/src/debug.ts new file mode 100644 index 000000000000..af9d1740bc72 --- /dev/null +++ b/app/ide-desktop/lib/client/src/debug.ts @@ -0,0 +1,47 @@ +/** @file Application debug information. */ + +import buildCfg from '../../../build.json' + +// ================== +// === Debug Info === +// ================== + +/** Information about versions of different application components. */ +export const versionInfo = { + version: buildCfg.version, + build: buildCfg.commit, + electron: process.versions.electron, + chrome: process.versions.chrome, +} + +async function getInfo() { + let procMemInfo = await process.getProcessMemoryInfo() + return { + version: versionInfo, + time: { + current: Date.now(), + creation: process.getCreationTime(), + }, + perf: { + cpu: process.getCPUUsage(), + }, + memory: { + heap: process.getHeapStatistics(), + blink: process.getBlinkMemoryInfo(), + process: procMemInfo, + system: process.getSystemMemoryInfo(), + }, + system: { + platform: process.platform, + arch: process.arch, + version: process.getSystemVersion(), + uptime: process.uptime(), + }, + } +} + +export async function printInfoAndExit() { + let info = await getInfo() + console.log(JSON.stringify(info, undefined, 4)) + process.exit() +} diff --git a/app/ide-desktop/lib/client/src/index.js b/app/ide-desktop/lib/client/src/index.js deleted file mode 100644 index 963328f3be1d..000000000000 --- a/app/ide-desktop/lib/client/src/index.js +++ /dev/null @@ -1,738 +0,0 @@ -'use strict' - -import assert from 'node:assert' -import buildCfg from '../../../build.json' -import Electron from 'electron' -import isDev from 'electron-is-dev' -import path from 'node:path' -import * as Server from './server.js' -import util from 'node:util' -import yargs from 'yargs' -import { hideBin } from 'yargs/helpers' -import remoteMain from '@electron/remote/main/index.js' - -import { project_manager_bundle } from '../paths.js' - -import child_process from 'child_process' -import fss from 'node:fs' -import fsp from 'node:fs/promises' - -// ============= -// === Paths === -// ============= - -const root = Electron.app.getAppPath() -const resources = path.join(root, '..') -const project_manager_executable = path.join( - resources, - project_manager_bundle, - PROJECT_MANAGER_IN_BUNDLE_PATH // Placeholder for a bundler-provided define. -) - -// FIXME default options parsed wrong -// https://github.com/yargs/yargs/issues/1590 - -// ================ -// === Defaults === -// ================ - -let windowCfg = { - width: 1380, - height: 900, -} - -// ============= -// === Utils === -// ============= - -function capitalizeFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1) -} - -const execFile = util.promisify(child_process.execFile) - -// The list of hosts that the app can access. They are required for -// user authentication to work. -const trustedHosts = [ - 'enso-org.firebaseapp.com', - 'accounts.google.com', - 'accounts.youtube.com', - 'github.com', -] - -// ===================== -// === Option Parser === -// ===================== - -let usage = ` -${buildCfg.name} ${buildCfg.version} command line interface. - -Usage: ${buildCfg.name} [options] [--] [backend args]... -` - -let epilogue = ` -Arguments that follow the two dashes (\`--\`) will be passed to the backend process. They are used\ - if IDE spawns backend, i.e. if '--backend false' has not been set.` - -let argv = hideBin(process.argv) -let optParser = yargs(argv) - .scriptName('') - .usage(usage) - .epilogue(epilogue) - .help() - .version(false) - .parserConfiguration({ 'populate--': true }) - .strict() - -// === Config Options === - -let configOptionsGroup = 'Config Options:' - -optParser.options('port', { - group: configOptionsGroup, - describe: `Port to use [${Server.DEFAULT_PORT}]`, -}) - -optParser.options('project', { - group: configOptionsGroup, - describe: 'Open the specified project on startup', -}) - -optParser.options('server', { - group: configOptionsGroup, - describe: 'Run the server [true]', - type: 'boolean', -}) - -optParser.options('window', { - group: configOptionsGroup, - describe: 'Show the window [true]', - type: 'boolean', -}) - -optParser.options('background-throttling', { - group: configOptionsGroup, - describe: 'Throttle animations when run in background [false]', - type: 'boolean', -}) - -optParser.options('backend', { - group: configOptionsGroup, - describe: 'Start the backend process automatically [true]', - type: 'boolean', -}) - -optParser.options('backend-path', { - group: configOptionsGroup, - describe: 'Set the path of a local project manager to use for running projects', -}) - -// === Debug Options === - -let debugOptionsGroup = 'Debug Options:' - -optParser.options('verbose', { - group: debugOptionsGroup, - describe: `Increase logs verbosity. Affects both IDE and the backend.`, - default: false, - type: `boolean`, -}) - -optParser.options('entry-point', { - group: debugOptionsGroup, - describe: 'Run an alternative entry point (e.g. one of the debug scenes)', - // requiresArg : true -}) - -optParser.options('dev', { - group: debugOptionsGroup, - describe: 'Run the application in development mode', -}) - -optParser.options('devtron', { - group: debugOptionsGroup, - describe: 'Install the Devtron Developer Tools extension', -}) - -optParser.options('load-profile', { - group: debugOptionsGroup, - describe: - 'Load a performance profile. For use with developer tools such as the `profiling-run-graph` entry point.', - requiresArg: true, - type: `array`, -}) - -optParser.options('save-profile', { - group: debugOptionsGroup, - describe: 'Record a performance profile and write to a file.', - requiresArg: true, - type: `string`, -}) - -optParser.options('workflow', { - group: debugOptionsGroup, - describe: 'Specify a workflow for profiling. Must be used with --entry-point=profile.', - requiresArg: true, - type: `string`, -}) - -// === Style Options === - -let styleOptionsGroup = 'Style Options:' - -optParser.options('frame', { - group: styleOptionsGroup, - describe: 'Draw window frame. Defaults to `false` on MacOS and `true` otherwise.', - type: `boolean`, -}) - -optParser.options('vibrancy', { - group: styleOptionsGroup, - describe: 'Use the vibrancy effect', - default: false, - type: `boolean`, -}) - -optParser.options('window-size', { - group: styleOptionsGroup, - describe: `Set the window size [${windowCfg.width}x${windowCfg.height}]`, - requiresArg: true, -}) - -optParser.options('theme', { - group: styleOptionsGroup, - describe: 'Use the provided theme. Defaults to `light`.', - type: `string`, -}) - -optParser.options('node-labels', { - group: styleOptionsGroup, - describe: 'Show node labels. Defaults to `true`.', - default: true, - type: `boolean`, -}) - -// === Other Options === - -optParser.options('info', { - describe: `Print the system debug info`, -}) - -optParser.options('version', { - describe: `Print the version`, -}) - -optParser.options('data-gathering', { - describe: 'Enable the sharing of any usage data', - type: 'boolean', - default: true, -}) - -optParser.options('preferred-engine-version', { - describe: 'The Engine version that IDE will try to use for newly created projects', - type: 'string', - default: BUNDLED_ENGINE_VERSION, -}) - -optParser.options('enable-new-component-browser', { - describe: - 'Enable to have new Component Browser panel in place of old Node Searcher. A temporary feature flag, ' + - 'until the Component Browser is unstable', - type: 'boolean', - default: true, -}) - -optParser.options('skip-min-version-check', { - describe: 'Disables the check whether this IDE version is still supported', - type: 'boolean', -}) - -optParser.options('emit-user-timing-measurements', { - describe: 'Forward profiler data to the User Timing web API.', - type: 'boolean', -}) - -optParser.options('enable-skip-and-freeze', { - describe: 'Enable experimental support for skipping and freezing nodes.', - type: 'boolean', - default: false, -}) - -// === Parsing === - -let args = optParser.parse() - -// Note: this is a conditional default to avoid issues with some window managers affecting -// interactions at the top of a borderless window. Thus, we want borders on Win/Linux and -// borderless on Mac. See https://github.com/enso-org/ide/issues/1101 and -// https://github.com/electron/electron/issues/3647 for details. -if (args.frame === undefined) { - args.frame = process.platform !== 'darwin' -} - -if (args.theme === undefined) { - args.theme = 'light' -} - -if (args.windowSize) { - let size = args.windowSize.split('x') - let width = parseInt(size[0]) - let height = parseInt(size[1]) - if (isNaN(width) || isNaN(height)) { - console.error(`Incorrect window size provided '${args.windowSize}'.`) - } else { - windowCfg.width = width - windowCfg.height = height - } -} - -// ================== -// === Debug Info === -// ================== - -let versionInfo = { - version: buildCfg.version, - build: buildCfg.commit, - electron: process.versions.electron, - chrome: process.versions.chrome, -} - -async function getDebugInfo() { - let procMemInfo = await process.getProcessMemoryInfo() - return { - version: versionInfo, - creation: process.getCreationTime(), - perf: { - cpu: process.getCPUUsage(), - }, - memory: { - heap: process.getHeapStatistics(), - blink: process.getBlinkMemoryInfo(), - process: procMemInfo, - system: process.getSystemMemoryInfo(), - }, - system: { - platform: process.platform, - arch: process.arch, - version: process.getSystemVersion(), - }, - } -} - -async function printDebugInfo() { - let info = await getDebugInfo() - console.log(JSON.stringify(info, undefined, 4)) - process.exit() -} - -// ================ -// === Security === -// ================ - -// === WebView Security === - -/// A WebView created in a renderer process that does not have Node.js integration enabled will not -/// be able to enable integration itself. However, a WebView will always create an independent -/// renderer process with its own webPreferences. It is a good idea to control the creation of new -/// tags from the main process and to verify that their webPreferences do not disable -/// security features. Follow the link to learn more: -/// https://www.electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation -function secureWebPreferences(webPreferences) { - if (!webPreferences) { - webPreferences = {} - } - delete webPreferences.preload - delete webPreferences.preloadURL - delete webPreferences.nodeIntegration - delete webPreferences.nodeIntegrationInWorker - delete webPreferences.webSecurity - delete webPreferences.allowRunningInsecureContent - delete webPreferences.experimentalFeatures - delete webPreferences.enableBlinkFeatures - delete webPreferences.allowpopups - delete webPreferences.contextIsolation - return webPreferences -} - -let urlWhitelist = [] -Electron.app.on('web-contents-created', (event, contents) => { - contents.on('will-attach-webview', (event, webPreferences, params) => { - secureWebPreferences(webPreferences) - if (!urlWhitelist.includes(params.src)) { - console.error(`Blocked the creation of WebView pointing to '${params.src}'`) - event.preventDefault() - } - }) -}) - -// === Prevent Navigation === - -/// Navigation is a common attack vector. If an attacker can convince your app to navigate away from -/// its current page, they can possibly force your app to open web sites on the Internet. Follow the -/// link to learn more: -/// https://www.electronjs.org/docs/tutorial/security#12-disable-or-limit-navigation -Electron.app.on('web-contents-created', (event, contents) => { - contents.on('will-navigate', (event, navigationUrl) => { - const parsedUrl = new URL(navigationUrl) - if (parsedUrl.origin !== origin && !trustedHosts.includes(parsedUrl.host)) { - event.preventDefault() - console.error(`Prevented navigation to '${navigationUrl}'.`) - } - }) -}) - -// === Disable New Windows Creation === - -/// Much like navigation, the creation of new webContents is a common attack vector. Attackers -/// attempt to convince your app to create new windows, frames, or other renderer processes with -/// more privileges than they had before or with pages opened that they couldn't open before. -/// Follow the link to learn more: -/// https://www.electronjs.org/docs/tutorial/security#13-disable-or-limit-creation-of-new-windows -Electron.app.on('web-contents-created', (event, contents) => { - contents.on('new-window', async (event, navigationUrl) => { - event.preventDefault() - console.error(`Blocking new window creation request to '${navigationUrl}'`) - }) -}) - -// ======================= -// === Project Manager === -// ======================= - -function projectManagerPath() { - let binPath = args['backend-path'] ?? project_manager_executable - let binExists = fss.existsSync(binPath) - assert(binExists, `Could not find the project manager binary at ${binPath}.`) - return binPath -} -/** - * Executes the Project Manager with given arguments. - * - * Note that this function captures all the Project Manager output into a fixed - * size buffer. If too much output is produced, it will fail and Project - * Manager process will prematurely close. - * - * @param {string[]} args Project Manager command line arguments. - * @returns Promise with captured standard output and error contents. - */ -async function execProjectManager(args) { - let binPath = projectManagerPath() - return await execFile(binPath, args).catch(function (err) { - throw err - }) -} - -/** - * Spawn process with Project Manager, - * - * The standard output and error handles will be inherited, i.e. will be - * redirected to the electron's app output and error handles. Input is piped - * to this process, so it will not be closed, until this process finished. - * - * @param {string[]} args - * @returns Handle to the spawned process. - */ -function spawnProjectManager(args) { - let binPath = projectManagerPath() - let stdin = 'pipe' - let stdout = 'inherit' - let stderr = 'inherit' - let opts = { - stdio: [stdin, stdout, stderr], - } - let out = child_process.spawn(binPath, args, opts) - console.log(`Project Manager has been spawned, pid = ${out.pid}.`) - out.on('exit', code => { - console.log(`Project Manager exited with code ${code}.`) - }) - return out -} - -function runBackend() { - if (args.backend !== false) { - let opts = args['--'] ? args['--'] : [] - if (args.verbose === true) { - opts.push('-vv') - } - console.log('Starting the backend process with the following options:', opts) - return spawnProjectManager(opts) - } -} - -async function backendVersion() { - if (args.backend !== false) { - return await execProjectManager(['--version']).then(t => t.stdout) - } -} - -// ============ -// === Main === -// ============ - -let hideInsteadOfQuit = false - -let server = null -let mainWindow = null -let origin = null - -async function main(args) { - // Note [Main error handling] - try { - runBackend() - - console.log('Starting the IDE service.') - if (args.server !== false) { - let serverCfg = Object.assign({}, args) - serverCfg.dir = root - serverCfg.fallback = '/assets/index.html' - server = await Server.create(serverCfg) - origin = `http://localhost:${server.port}` - } - if (args.window !== false) { - console.log('Starting the IDE client.') - mainWindow = createWindow() - mainWindow.on('close', evt => { - if (hideInsteadOfQuit) { - evt.preventDefault() - mainWindow.hide() - } - }) - } - } catch (err) { - // Note [Main error handling] - console.error('Failed to setup IDE. Error:', err) - Electron.app.quit() - } -} - -// Note [Main error handling] -// ========================== -// It is critical that the main function runs in its entirety. Otherwise, IDE enters a "zombie -// process" state, where Electron processes have been spawned, but there is no window and the user -// can't observe anything. Usually they will try to spawn another instance of the IDE, but this can -// fail because of these zombie process presence. -// -// The solution is to catch all errors and exit the process if any part of the initial setup fails. -// If it succeeds, at least the window will be shown, allowing the user to observe the error and -// close it. - -function urlParamsFromObject(obj) { - let params = [] - for (let key in obj) { - let val = obj[key] - params.push(`${key}=${val}`) - } - return params.join('&') -} - -function createWindow() { - let webPreferences = secureWebPreferences() - webPreferences.preload = path.join(root, 'preload.cjs') - - let windowPreferences = { - webPreferences: webPreferences, - width: windowCfg.width, - height: windowCfg.height, - frame: args.frame, - devTools: false, - sandbox: true, - backgroundThrottling: false, - transparent: false, - titleBarStyle: 'default', - } - - if (args.dev) { - windowPreferences.devTools = true - } - - if (args.frame === false && process.platform === 'darwin') { - windowPreferences.titleBarStyle = 'hiddenInset' - } - - if (args['background-throttling']) { - windowPreferences.backgroundThrottling = true - } - - if (args.vibrancy === true) { - windowPreferences.vibrancy = 'fullscreen-ui' - } - - remoteMain.initialize() - const window = new Electron.BrowserWindow(windowPreferences) - remoteMain.enable(window.webContents) - window.setMenuBarVisibility(false) - - if (args.dev) { - window.webContents.openDevTools() - } - - let urlCfg = { - platform: process.platform, - frame: args.frame, - theme: args.theme, - darkTheme: Electron.nativeTheme.shouldUseDarkColors, - // high_contrast: Electron.nativeTheme.shouldUseHighContrastColors, - // crash_report_host: args.crashReportHost, - dataGathering: args.dataGathering, - preferredEngineVersion: args.preferredEngineVersion, - enableNewComponentBrowser: args.enableNewComponentBrowser, - enableSkipAndFreeze: args.enableSkipAndFreeze, - emitUserTimingMeasurements: args.emitUserTimingMeasurements, - nodeLabels: args.nodeLabels, - debug: args.verbose, - } - - Electron.ipcMain.on('error', (event, data) => console.error(data)) - - // We want to pass this argument only if explicitly passed. Otherwise we allow contents to select default behavior. - if (typeof args.skipMinVersionCheck !== 'undefined') { - urlCfg.skip_min_version_check = args.skipMinVersionCheck - } - if (args.project) { - urlCfg.project = args.project - } - if (args.entryPoint) { - urlCfg.entry = args.entryPoint - } - let profilePromises = [] - if (args.loadProfile) { - profilePromises = args.loadProfile.map(path => fsp.readFile(path, 'utf8')) - } - const profiles = Promise.all(profilePromises) - Electron.ipcMain.on('load-profiles', event => { - profiles.then(profiles => { - event.reply('profiles-loaded', profiles) - }) - }) - if (args.saveProfile) { - Electron.ipcMain.on('save-profile', (event, data) => { - fss.writeFileSync(args.saveProfile, data) - }) - } - if (args.workflow) { - urlCfg.test_workflow = args.workflow - } - - Electron.ipcMain.on('quit-ide', () => { - Electron.app.quit() - }) - - let params = urlParamsFromObject(urlCfg) - let address = `${origin}?${params}` - - console.log(`Loading the window address ${address}`) - window.loadURL(address) - return window -} - -/// By default, Electron will automatically approve all permission requests unless the developer has -/// manually configured a custom handler. While a solid default, security-conscious developers might -/// want to assume the very opposite. Follow the link to learn more: -// https://www.electronjs.org/docs/tutorial/security#4-handle-session-permission-requests-from-remote-content -function setupPermissions() { - Electron.session.defaultSession.setPermissionRequestHandler( - (webContents, permission, callback) => { - const url = webContents.getURL() - console.error(`Unhandled permission request '${permission}'.`) - } - ) -} - -// ============== -// === Events === -// ============== - -Electron.app.on('activate', () => { - if (process.platform === 'darwin') { - mainWindow.show() - } -}) - -Electron.app.on('ready', () => { - if (args.version) { - let indent = ' '.repeat(4) - let maxNameLen = 0 - for (let name in versionInfo) { - if (name.length > maxNameLen) { - maxNameLen = name.length - } - } - - console.log('Frontend:') - for (let name in versionInfo) { - let label = capitalizeFirstLetter(name) - let spacing = ' '.repeat(maxNameLen - name.length) - console.log(`${indent}${label}:${spacing} ${versionInfo[name]}`) - } - - console.log('') - console.log('Backend:') - backendVersion().then(backend => { - if (!backend) { - console.log(`${indent}No backend available.`) - } else { - let lines = backend.split(/\r?\n/) - for (let line of lines) { - console.log(`${indent}${line}`) - } - } - process.exit() - }) - } else if (args.info) { - printDebugInfo() - } else { - main(args) - } -}) - -if (process.platform === 'darwin') { - hideInsteadOfQuit = true - Electron.app.on('before-quit', function () { - hideInsteadOfQuit = false - }) -} - -// ================= -// === Shortcuts === -// ================= - -Electron.app.on('web-contents-created', (webContentsCreatedEvent, webContents) => { - webContents.on('before-input-event', (beforeInputEvent, input) => { - const { code, alt, control, shift, meta, type } = input - if (type !== 'keyDown') { - return - } - if (control && alt && shift && !meta && code === 'KeyI') { - Electron.BrowserWindow.getFocusedWindow().webContents.toggleDevTools() - } - if (control && alt && shift && !meta && code === 'KeyR') { - Electron.BrowserWindow.getFocusedWindow().reload() - } - - let cmd_q = meta && !control && !alt && !shift && code === 'KeyQ' - let ctrl_q = !meta && control && !alt && !shift && code === 'KeyQ' - let alt_f4 = !meta && !control && alt && !shift && code === 'F4' - let ctrl_w = !meta && control && !alt && !shift && code === 'KeyW' - let quit_on_mac = process.platform === 'darwin' && (cmd_q || alt_f4) - let quit_on_win = process.platform === 'win32' && (alt_f4 || ctrl_w) - let quit_on_lin = process.platform === 'linux' && (alt_f4 || ctrl_q || ctrl_w) - let quit = quit_on_mac || quit_on_win || quit_on_lin - if (quit) { - Electron.app.quit() - } - }) -}) - -// ============================= -// === Deprecations & Fixmes === -// ============================= - -// FIXME Enable Metal backend on MacOS https://github.com/electron/electron/issues/22465 - -// TODO[WD] Windows vibrancy -// https://github.com/fstudio/clangbuilder/issues/39 -// https://github.com/Microsoft/vscode/issues/32257 -// https://github.com/arkenthera/electron-vibrancy/issues/21 - -// TODO[WD] Window corner radius -// https://github.com/electron/electron/issues/22542 diff --git a/app/ide-desktop/lib/client/src/index.ts b/app/ide-desktop/lib/client/src/index.ts new file mode 100644 index 000000000000..4f5d8a8a1493 --- /dev/null +++ b/app/ide-desktop/lib/client/src/index.ts @@ -0,0 +1,302 @@ +/** @file Definition of an Electron application, which entails the creation of a rudimentary HTTP + * server and the presentation of a Chrome web view, designed for optimal performance and + * compatibility across a wide range of hardware configurations. The application's web component + * is then served and showcased within the web view, complemented by the establishment of an + * Inter-Process Communication channel, which enables seamless communication between the served web + * application and the Electron process. */ + +import * as config from 'config' +import * as configParser from 'config/parser' +import * as content from 'enso-content-config' +import * as debug from 'debug' +import * as electron from 'electron' +import * as fs from 'node:fs/promises' +import * as fss from 'node:fs' +import * as ipc from 'ipc' +import * as naming from 'naming' +import * as path from 'node:path' +import * as paths from 'paths' +import * as projectManager from 'bin/project-manager' +import * as security from 'security' +import * as server from 'bin/server' +const logger = content.logger + +// =========== +// === App === +// =========== + +/** The Electron application. It is responsible for starting all the required services, and + * displaying and managing the app window. */ +class App { + window: null | electron.BrowserWindow = null + server: null | server.Server = null + args: config.Args + isQuitting = false + constructor() { + const { args, windowSize, chromeOptions } = configParser.parseArgs() + this.args = args + this.setChromeOptions(chromeOptions) + security.enableAll() + electron.app.on('before-quit', () => (this.isQuitting = true)) + electron.app.whenReady().then(() => this.main(windowSize)) + this.registerShortcuts() + } + + /** Set Chrome options based on the app configuration. For comprehensive list of available + * Chrome options refer to: https://peter.sh/experiments/chromium-command-line-switches. */ + setChromeOptions(chromeOptions: configParser.ChromeOption[]) { + const addIf = (opt: content.Option, chromeOptName: string, value?: string) => { + if (opt.value) { + const chromeOption = new configParser.ChromeOption(chromeOptName, value) + const chromeOptionStr = chromeOption.display() + const optionName = opt.qualifiedName() + logger.log(`Setting '${chromeOptionStr}' because '${optionName}' was enabled.`) + chromeOptions.push(chromeOption) + } + } + const add = (option: string, value?: string) => + chromeOptions.push(new configParser.ChromeOption(option, value)) + logger.groupMeasured('Setting Chrome options', () => { + const perfOpts = this.args.groups.performance.options + addIf(perfOpts.disableGpuSandbox, 'disable-gpu-sandbox') + addIf(perfOpts.disableGpuVsync, 'disable-gpu-vsync') + addIf(perfOpts.disableSandbox, 'no-sandbox') + addIf(perfOpts.disableSmoothScrolling, 'disable-smooth-scrolling') + addIf(perfOpts.enableNativeGpuMemoryBuffers, 'enable-native-gpu-memory-buffers') + addIf(perfOpts.forceHighPerformanceGpu, 'force_high_performance_gpu') + addIf(perfOpts.ignoreGpuBlocklist, 'ignore-gpu-blocklist') + add('use-angle', perfOpts.angleBackend.value) + chromeOptions.sort() + if (chromeOptions.length > 0) { + for (const chromeOption of chromeOptions) { + electron.app.commandLine.appendSwitch(chromeOption.name, chromeOption.value) + } + const cfgName = config.helpExtendedOptionName + logger.log(`See '-${cfgName}' to learn why these options were enabled.`) + } + }) + } + + /** Main app entry point. */ + async main(windowSize: config.WindowSize) { + // We catch all errors here. Otherwise, it might be possible that the app will run partially + // and and enter a "zombie mode", where user is not aware of the app still running. + try { + if (this.args.options.version.value) { + this.printVersionAndExit() + } else if (this.args.groups.debug.options.info.value) { + debug.printInfoAndExit() + } + await logger.asyncGroupMeasured('Starting the application', async () => { + // Note that we want to do all the actions synchronously, so when the window + // appears, it serves the website immediately. + await this.startBackendIfEnabled() + await this.startContentServerIfEnabled() + await this.createWindowIfEnabled(windowSize) + this.initIpc() + this.loadWindowContent() + }) + } catch (err) { + console.error('Failed to initialize the application, shutting down. Error:', err) + electron.app.quit() + } + } + + /** Run the provided function if the provided option was enabled. Log a message otherwise. */ + async runIfEnabled(option: content.Option, fn: () => Promise) { + option.value ? await fn() : logger.log(`The app is configured not to use ${option.name}.`) + } + + /** Start the backend processes. */ + async startBackendIfEnabled() { + await this.runIfEnabled(this.args.options.engine, async () => { + const backendOpts = this.args.groups.debug.options.verbose.value ? ['-vv'] : [] + projectManager.spawn(this.args, backendOpts) + }) + } + + /** Start the content server, which will serve the application content (HTML) to the window. */ + async startContentServerIfEnabled() { + await this.runIfEnabled(this.args.options.server, async () => { + await logger.asyncGroupMeasured('Starting the content server.', async () => { + let serverCfg = new server.Config({ + dir: paths.assets, + port: this.args.groups.server.options.port.value, + }) + this.server = await server.Server.create(serverCfg) + }) + }) + } + + /** Create the Electron window and display it on the screen. */ + async createWindowIfEnabled(windowSize: config.WindowSize) { + await this.runIfEnabled(this.args.options.window, async () => { + logger.groupMeasured('Creating the window.', () => { + const argGroups = this.args.groups + const useFrame = this.args.groups.window.options.frame.value + const macOS = process.platform === 'darwin' + const useHiddenInsetTitleBar = !useFrame && macOS + const useVibrancy = this.args.groups.window.options.vibrancy.value + const webPreferences: electron.WebPreferences = { + preload: path.join(paths.app, 'preload.cjs'), + sandbox: true, + backgroundThrottling: argGroups.performance.options.backgroundThrottling.value, + devTools: argGroups.debug.options.devTools.value, + enableBlinkFeatures: argGroups.chrome.options.enableBlinkFeatures.value, + disableBlinkFeatures: argGroups.chrome.options.disableBlinkFeatures.value, + spellcheck: false, + } + let windowPreferences: electron.BrowserWindowConstructorOptions = { + webPreferences, + width: windowSize.width, + height: windowSize.height, + frame: useFrame, + transparent: false, + titleBarStyle: useHiddenInsetTitleBar ? 'hiddenInset' : 'default', + vibrancy: useVibrancy ? 'fullscreen-ui' : undefined, + } + const window = new electron.BrowserWindow(windowPreferences) + window.setMenuBarVisibility(false) + if (this.args.groups.debug.options.devTools.value) { + window.webContents.openDevTools() + } + + window.on('close', evt => { + if (!this.isQuitting && !this.args.groups.window.options.closeToQuit.value) { + evt.preventDefault() + window.hide() + } + }) + + electron.app.on('activate', () => { + if (!this.args.groups.window.options.closeToQuit.value) { + window.show() + } + }) + + window.webContents.on('render-process-gone', (event, details) => { + logger.error('Error, the render process crashed.', details) + }) + + this.window = window + }) + }) + } + + /** Initialize Inter-Process Communication between the Electron application and the served + * website. */ + initIpc() { + electron.ipcMain.on(ipc.channel.error, (event, data) => logger.error(`IPC error: ${data}`)) + let profilePromises: Promise[] = [] + const argProfiles = this.args.groups.profile.options.loadProfile.value + if (argProfiles) { + profilePromises = argProfiles.map((path: string) => fs.readFile(path, 'utf8')) + } + const profiles = Promise.all(profilePromises) + electron.ipcMain.on(ipc.channel.loadProfiles, event => { + profiles.then(profiles => { + event.reply('profiles-loaded', profiles) + }) + }) + const profileOutPath = this.args.groups.profile.options.saveProfile.value + if (profileOutPath) { + electron.ipcMain.on(ipc.channel.saveProfile, (event, data) => { + fss.writeFileSync(profileOutPath, data) + }) + } + electron.ipcMain.on(ipc.channel.quit, () => electron.app.quit()) + } + + /** The server port. In case the server was not started, the port specified in the configuration + * is returned. This might be used to connect this application window to another, existing + * application server. */ + serverPort(): number { + if (this.server != null) { + return this.server.config.port + } else { + return this.args.groups.server.options.port.value + } + } + + /** Redirect the web view to `localhost:` to see the served website. */ + loadWindowContent() { + const window = this.window + if (window != null) { + const urlCfg: { [key: string]: string } = {} + for (const option of this.args.optionsRecursive()) { + if (option.value != option.default && option.passToWebApplication) { + urlCfg[option.qualifiedName()] = String(option.value) + } + } + const params = server.urlParamsFromObject(urlCfg) + const address = `http://localhost:${this.serverPort()}${params}` + logger.log(`Loading the window address '${address}'.`) + window.loadURL(address) + } + } + + printVersionAndExit() { + let indent = ' '.repeat(4) + let maxNameLen = 0 + for (let name in debug.versionInfo) { + maxNameLen = Math.max(maxNameLen, name.length) + } + console.log('Frontend:') + for (let [name, value] of Object.entries(debug.versionInfo)) { + let label = naming.capitalizeFirstLetter(name) + let spacing = ' '.repeat(maxNameLen - name.length) + console.log(`${indent}${label}:${spacing} ${value}`) + } + + console.log('') + console.log('Backend:') + projectManager.version(this.args).then(backend => { + if (!backend) { + console.log(`${indent}No backend available.`) + } else { + let lines = backend.split(/\r?\n/).filter(line => line.length > 0) + for (let line of lines) { + console.log(`${indent}${line}`) + } + } + process.exit() + }) + } + + registerShortcuts() { + electron.app.on('web-contents-created', (webContentsCreatedEvent, webContents) => { + webContents.on('before-input-event', (beforeInputEvent, input) => { + const { code, alt, control, shift, meta, type } = input + if (type === 'keyDown') { + const focusedWindow = electron.BrowserWindow.getFocusedWindow() + if (focusedWindow) { + if (control && alt && shift && !meta && code === 'KeyI') { + focusedWindow.webContents.toggleDevTools() + } + if (control && alt && shift && !meta && code === 'KeyR') { + focusedWindow.reload() + } + } + + let cmd_q = meta && !control && !alt && !shift && code === 'KeyQ' + let ctrl_q = !meta && control && !alt && !shift && code === 'KeyQ' + let alt_f4 = !meta && !control && alt && !shift && code === 'F4' + let ctrl_w = !meta && control && !alt && !shift && code === 'KeyW' + let quit_on_mac = process.platform === 'darwin' && (cmd_q || alt_f4) + let quit_on_win = process.platform === 'win32' && (alt_f4 || ctrl_w) + let quit_on_lin = process.platform === 'linux' && (alt_f4 || ctrl_q || ctrl_w) + let quit = quit_on_mac || quit_on_win || quit_on_lin + if (quit) { + electron.app.quit() + } + } + }) + }) + } +} + +// =================== +// === App startup === +// =================== + +new App() diff --git a/app/ide-desktop/lib/client/src/ipc.ts b/app/ide-desktop/lib/client/src/ipc.ts new file mode 100644 index 000000000000..3bbe87cdfc1e --- /dev/null +++ b/app/ide-desktop/lib/client/src/ipc.ts @@ -0,0 +1,15 @@ +/** @file Inter-Process communication configuration of the application. IPC allows the web-view + * content to exchange information with the Electron application. */ + +// =============== +// === Channel === +// =============== + +/** Channel names used by the IPC protocol. */ +export const channel = { + error: 'error', + loadProfiles: 'load-profiles', + profilesLoaded: 'profiles-loaded', + saveProfile: 'save-profile', + quit: 'quit-ide', +} diff --git a/app/ide-desktop/lib/client/src/naming.ts b/app/ide-desktop/lib/client/src/naming.ts new file mode 100644 index 000000000000..5fd056e6f57f --- /dev/null +++ b/app/ide-desktop/lib/client/src/naming.ts @@ -0,0 +1,20 @@ +/** @file Naming utilities. */ + +// ============== +// === Naming === +// ============== + +/** Capitalizes first letter of the provided string. */ +export function capitalizeFirstLetter(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1) +} + +/** Converts the camel case name to kebab case one. For example, converts `myName` to `my-name`. */ +export function camelToKebabCase(str: string) { + return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() +} + +/** Converts the camel case name to kebab case one. For example, converts `myName` to `My Name`. */ +export function camelCaseToTitle(str: string) { + return capitalizeFirstLetter(str.replace(/([a-z])([A-Z])/g, '$1 $2')) +} diff --git a/app/ide-desktop/lib/client/src/paths.ts b/app/ide-desktop/lib/client/src/paths.ts new file mode 100644 index 000000000000..21593b354bb5 --- /dev/null +++ b/app/ide-desktop/lib/client/src/paths.ts @@ -0,0 +1,27 @@ +/** @file File system paths used by the application. */ + +import path from 'node:path' +import { project_manager_bundle } from '../paths' +import Electron from 'electron' + +// ============= +// === Paths === +// ============= + +/** The root of the application bundle. */ +export const app = Electron.app.getAppPath() + +/** The application assets, all files bundled with it. */ +export const assets = path.join(app, 'assets') + +/** Other app resources, including binaries, such a project manager. */ +export const resources = path.join(app, '..') + +/** Project manager binary path. */ +export const projectManager = path.join( + resources, + project_manager_bundle, + // @ts-ignore + // Placeholder for a bundler-provided define. + PROJECT_MANAGER_IN_BUNDLE_PATH +) diff --git a/app/ide-desktop/lib/client/src/preload.cjs b/app/ide-desktop/lib/client/src/preload.cjs deleted file mode 100644 index da9236976897..000000000000 --- a/app/ide-desktop/lib/client/src/preload.cjs +++ /dev/null @@ -1,53 +0,0 @@ -const { contextBridge, ipcRenderer } = require('electron') - -// =================== -// === Debug Tools === -// =================== - -// TODO[WD] Enable after making preload configurable (we do not want to load it always) -// require('devtron').install() - -// ================== -// === Debug APIs === -// ================== - -// These APIs expose functionality for use from Rust; see the bindings in the `debug_api` module for -// the primary documentation. - -// Shutdown-related commands and events. -contextBridge.exposeInMainWorld('enso_lifecycle', { - // Allows application-exit to be initiated from WASM code. - // - // This is used, for example, in a key binding (Ctrl+Alt+Q) that saves a performance profile and exits. - quit: data => ipcRenderer.send('quit-ide'), -}) - -// Save and load profile data. -let onProfiles = [] -let profilesLoaded -ipcRenderer.on('profiles-loaded', (event, profiles) => { - for (const callback of onProfiles) { - callback(profiles) - } - onProfiles = [] - profilesLoaded = profiles -}) -contextBridge.exposeInMainWorld('enso_profiling_data', { - // Delivers profiling log. - saveProfile: data => ipcRenderer.send('save-profile', data), - // Requests any loaded profiling logs. - loadProfiles: callback => { - if (profilesLoaded === undefined) { - ipcRenderer.send('load-profiles') - onProfiles.push(callback) - } else { - callback(profilesLoaded) - } - }, -}) - -// Access to the system console that Electron was run from. -contextBridge.exposeInMainWorld('enso_console', { - // Print an error message with `console.error`. - error: data => ipcRenderer.send('error', data), -}) diff --git a/app/ide-desktop/lib/client/src/preload.ts b/app/ide-desktop/lib/client/src/preload.ts new file mode 100644 index 000000000000..0511975e9d3f --- /dev/null +++ b/app/ide-desktop/lib/client/src/preload.ts @@ -0,0 +1,52 @@ +/** @file Preload script containing code that runs before web page is loaded into the browser + * window. It has access to both DOM APIs and Node environment, and is used to expose privileged + * APIs to the renderer via the contextBridge API. To learn more, visit: + * https://www.electronjs.org/docs/latest/tutorial/tutorial-preload. */ + +const { contextBridge, ipcRenderer } = require('electron') +import * as ipc from 'ipc' + +// ====================== +// === Profiling APIs === +// ====================== + +// These APIs expose functionality for use from Rust. See the bindings in the `debug_api` module for +// the primary documentation. + +/** Shutdown-related commands and events. */ +contextBridge.exposeInMainWorld('enso_lifecycle', { + /** Allows application-exit to be initiated from WASM code. + * This is used, for example, in a key binding (Ctrl+Alt+Q) that saves a performance profile and + * exits. */ + quit: () => ipcRenderer.send(ipc.channel.quit), +}) + +// Save and load profile data. +let onProfiles: ((profiles: string[]) => void)[] = [] +let profilesLoaded: string[] +ipcRenderer.on(ipc.channel.profilesLoaded, (event, profiles: string[]) => { + for (const callback of onProfiles) { + callback(profiles) + } + onProfiles = [] + profilesLoaded = profiles +}) +contextBridge.exposeInMainWorld('enso_profiling_data', { + // Delivers profiling log. + saveProfile: (data: any) => ipcRenderer.send(ipc.channel.saveProfile, data), + // Requests any loaded profiling logs. + loadProfiles: (callback: (profiles: string[]) => void) => { + if (profilesLoaded === undefined) { + ipcRenderer.send('load-profiles') + onProfiles.push(callback) + } else { + callback(profilesLoaded) + } + }, +}) + +// Access to the system console that Electron was run from. +contextBridge.exposeInMainWorld('enso_console', { + // Print an error message with `console.error`. + error: (data: any) => ipcRenderer.send('error', data), +}) diff --git a/app/ide-desktop/lib/client/src/security.ts b/app/ide-desktop/lib/client/src/security.ts new file mode 100644 index 000000000000..7f4c17303e57 --- /dev/null +++ b/app/ide-desktop/lib/client/src/security.ts @@ -0,0 +1,113 @@ +/** @file Security configuration of Electron. Most of the options are based on the official security + * guide: https://www.electronjs.org/docs/latest/tutorial/security */ + +import Electron from 'electron' + +// ================= +// === Constants === +// ================= + +/** The list of hosts that the app can access. They are required for user authentication to work. */ +const trustedHosts = ['accounts.google.com', 'accounts.youtube.com', 'github.com'] + +/** The list of URLs a new WebView can be pointed to. */ +const webViewUrlWhitelist: string[] = [] + +// ============= +// === Utils === +// ============= + +/** Secure the web preferences of a new window. It deletes potentially unsecure options, making them + * revert to secure defaults. */ +export function secureWebPreferences(webPreferences: Electron.WebPreferences) { + delete webPreferences.preload + delete webPreferences.nodeIntegration + delete webPreferences.nodeIntegrationInWorker + delete webPreferences.webSecurity + delete webPreferences.allowRunningInsecureContent + delete webPreferences.experimentalFeatures + delete webPreferences.enableBlinkFeatures + delete webPreferences.contextIsolation + return webPreferences +} + +// ================ +// === Security === +// ================ + +/** Enabling sandbox globally. Follow the link to learn more: + * https://www.electronjs.org/docs/latest/tutorial/sandbox */ +function enableGlobalSandbox() { + Electron.app.enableSandbox() +} + +/** By default, Electron will automatically approve all permission requests unless the developer has + * manually configured a custom handler. While a solid default, security-conscious developers might + * want to assume the very opposite. Follow the link to learn more: + * https://www.electronjs.org/docs/latest/tutorial/security#5-handle-session-permission-requests-from-remote-content */ +function rejectPermissionRequests() { + Electron.app.whenReady().then(() => { + Electron.session.defaultSession.setPermissionRequestHandler( + (webContents, permission, callback) => { + console.error(`Unhandled permission request '${permission}'.`) + } + ) + }) +} + +/** A WebView created in a renderer process that does not have Node.js integration enabled will not + * be able to enable integration itself. However, a WebView will always create an independent + * renderer process with its own webPreferences. It is a good idea to control the creation of new + * tags from the main process and to verify that their webPreferences do not disable + * security features. Follow the link to learn more: + * https://www.electronjs.org/docs/tutorial/security#11-verify-webview-options-before-creation */ +function limitWebViewCreation() { + Electron.app.on('web-contents-created', (event, contents) => { + contents.on('will-attach-webview', (event, webPreferences, params) => { + secureWebPreferences(webPreferences) + if (params.src && !webViewUrlWhitelist.includes(params.src)) { + console.error(`Blocked the creation of WebView pointing to '${params.src}'`) + event.preventDefault() + } + }) + }) +} + +/** Navigation is a common attack vector. If an attacker can convince your app to navigate away from + * its current page, they can possibly force your app to open web sites on the Internet. Follow the + * link to learn more: + * https://www.electronjs.org/docs/tutorial/security#12-disable-or-limit-navigation */ +function preventNavigation() { + Electron.app.on('web-contents-created', (event, contents) => { + contents.on('will-navigate', (event, navigationUrl) => { + const parsedUrl = new URL(navigationUrl) + if (parsedUrl.origin !== origin && !trustedHosts.includes(parsedUrl.host)) { + event.preventDefault() + console.error(`Prevented navigation to '${navigationUrl}'.`) + } + }) + }) +} + +/** Much like navigation, the creation of new webContents is a common attack vector. Attackers + * attempt to convince your app to create new windows, frames, or other renderer processes with + * more privileges than they had before or with pages opened that they couldn't open before. + * Follow the link to learn more: + * https://www.electronjs.org/docs/tutorial/security#13-disable-or-limit-creation-of-new-windows */ +function disableNewWindowsCreation() { + Electron.app.on('web-contents-created', (event, contents) => { + contents.setWindowOpenHandler(({ url }) => { + console.error(`Blocking new window creation request to '${url}'.`) + return { action: 'deny' } + }) + }) +} + +/** Enable all security settings. */ +export function enableAll() { + enableGlobalSandbox() + rejectPermissionRequests() + limitWebViewCreation() + preventNavigation() + disableNewWindowsCreation() +} diff --git a/app/ide-desktop/lib/client/src/server.js b/app/ide-desktop/lib/client/src/server.js deleted file mode 100644 index f710a7d558be..000000000000 --- a/app/ide-desktop/lib/client/src/server.js +++ /dev/null @@ -1,84 +0,0 @@ -import createServer from 'create-servers' -import * as fs from 'fs' -import * as mime from 'mime-types' -import * as path from 'path' -import * as portfinder from 'portfinder' - -// ============ -// === Port === -// ============ - -export const DEFAULT_PORT = 8080 - -async function findPort(cfg) { - if (!cfg.port) { - cfg.port = await portfinder.getPortPromise({ port: DEFAULT_PORT, startPort: DEFAULT_PORT }) - } -} - -// ============== -// === Server === -// ============== - -/// A simple server implementation. -/// -/// Initially it was based on `union`, but later we migrated to `create-servers`. Read this topic to -/// learn why: https://github.com/http-party/http-server/issues/483 -class Server { - constructor(cfg) { - let self = this - this.dir = cfg.dir - this.port = cfg.port - this.fallback = cfg.fallback - console.log('f', createServer) - this.server = createServer( - { - http: this.port, - handler: function (request, response) { - self.process(request.url, response) - }, - }, - function (errs) { - if (errs) { - return console.log(errs.http) - } - console.log(`Server started on port ${this.port}.`) - console.log(`Serving files from '${process.cwd()}/${this.dir}'.`) - }.bind(this) - ) - } - - process(resource, response) { - let resource_file = `${this.dir}${resource}` - fs.readFile( - resource_file, - function (err, data) { - if (err) { - let fallback = this.fallback - if (fallback) { - if (resource === fallback) { - console.error(`Fallback resource '${resource}' not found.`) - } else { - this.process(fallback, response) - } - } else { - console.error(`Resource '${resource}' not found.`) - } - } else { - let contentType = mime.contentType(path.extname(resource_file)) - let contentLength = data.length - response.setHeader('Content-Type', contentType) - response.setHeader('Content-Length', contentLength) - response.writeHead(200) - response.end(data) - } - }.bind(this) - ) - } -} - -export async function create(cfg) { - let local_cfg = Object.assign({}, cfg) - await findPort(local_cfg) - return new Server(local_cfg) -} diff --git a/app/ide-desktop/lib/client/tsconfig.json b/app/ide-desktop/lib/client/tsconfig.json index 4082f16a5d91..7d63d011e607 100644 --- a/app/ide-desktop/lib/client/tsconfig.json +++ b/app/ide-desktop/lib/client/tsconfig.json @@ -1,3 +1,11 @@ { - "extends": "../../tsconfig.json" + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "./src", + "esModuleInterop": true, + "paths": { + "@ensogl-app": ["../../../../target/ensogl-pack/dist/index"], + "@build-cfg": ["../../build.json"] + } + } } diff --git a/app/ide-desktop/lib/content-config/package.json b/app/ide-desktop/lib/content-config/package.json new file mode 100644 index 000000000000..2aac1507a118 --- /dev/null +++ b/app/ide-desktop/lib/content-config/package.json @@ -0,0 +1,18 @@ +{ + "name": "enso-content-config", + "version": "1.0.0", + "type": "module", + "main": "src/index.ts", + "author": { + "name": "Enso Team", + "email": "contact@enso.org" + }, + "homepage": "https://github.com/enso-org/enso", + "repository": { + "type": "git", + "url": "git@github.com:enso-org/enso.git" + }, + "bugs": { + "url": "https://github.com/enso-org/enso/issues" + } +} diff --git a/app/ide-desktop/lib/content-config/src/config.json b/app/ide-desktop/lib/content-config/src/config.json new file mode 100644 index 000000000000..0a9ad320777e --- /dev/null +++ b/app/ide-desktop/lib/content-config/src/config.json @@ -0,0 +1,157 @@ +{ + "options": { + "authentication": { + "value": true, + "description": "Determines whether user authentication is enabled. This option is disregarded if the application is executed in the cloud." + }, + + "dataCollection": { + "value": true, + "description": "Determines whether anonymous usage data is to be collected.", + "primary": false + } + }, + "groups": { + "dataCollection": { + "description": "Controls the collection of anonymous usage data.", + "options": { + "usageStatistics": { + "value": "", + "description": "Determines whether anonymous usage statistics are to be collected.", + "primary": false + }, + "crashReports": { + "value": "", + "description": "Determines whether anonymous crash reports are to be collected.", + "primary": false + } + } + }, + "window": { + "description": "The visual and tactile configurations of the application window.", + "options": { + "frame": { + "value": true, + "defaultDescription": "false on MacOS, true otherwise", + "description": "Draw window frame." + } + } + }, + "startup": { + "options": { + "project": { + "value": "", + "description": "The name of the project to open at startup. If the project does not exist, it will be created." + }, + "platform": { + "value": "web", + "defaultDescription": "'web' if run in the browser, operating system name otherwise`", + "description": "The host platform on which the application is running. This is used to adjust some user interface elements. For example, on macOS, the window close buttons are integrated into the top application panel.", + "primary": false + } + } + }, + + "engine": { + "description": "Options that control the Enso Engine, the data processing backend.", + "options": { + "projectManagerUrl": { + "value": "", + "description": "The address of the Project Manager service.", + "primary": false + }, + "rpcUrl": { + "value": "", + "description": "The address of the Language Server RPC endpoint. This argument should be provided together with `dataUrl`, `namespace`, and `project` options. They enable Enso to connect directly to an already-spawned Language Server of some project.", + "primary": false + }, + "dataUrl": { + "value": "", + "description": "The address of the Language Server Data endpoint. This argument should be provided together with `rpcUrl`, `namespace`, and `project` options. They enable Enso to connect directly to an already-spawned Language Server of some project.", + "primary": false + }, + "namespace": { + "value": "local", + "description": "The namespace of the opened project. It can be used when connecting to an existing Language Server process.", + "primary": false + }, + "configUrl": { + "value": "https://raw.githubusercontent.com/enso-org/ide/develop/config.json", + "description": "The URL of the application configuration. Used to check for available updates.", + "primary": false + }, + "skipMinVersionCheck": { + "value": false, + "valueEval": "scope.Version.isDev()", + "defaultDescription": "true in local builds, false otherwise.", + "description": "Determines whether the minimum engine version check should be performed.", + "primary": false + }, + "preferredVersion": { + "value": "", + "valueEval": "String(scope.Version.ide)", + "description": "The preferred engine version.", + "primary": false + } + } + }, + + "style": { + "description": "The available visual and tactile configurations of the application.", + "options": { + "nodeLabels": { + "value": true, + "description": "Determines whether node labels should be visible." + } + } + }, + + "featurePreview": { + "description": "Options that enable experimental features that are not yet stable.", + "options": { + "newComponentBrowser": { + "value": true, + "description": "Indicates whether the new component browser should be enabled." + }, + "skipAndFreeze": { + "value": false, + "description": "Enable possibility to skip and freeze nodes.", + "primary": false + }, + "theme": { + "value": "light", + "description": "Color theme.", + "primary": false + } + } + }, + + "authentication": { + "description": "Options to manage application authentication properties.", + "options": { + "email": { + "value": "", + "description": "The user email, if any.", + "primary": false + } + }, + "primary": false + }, + + "profile": { + "description": "Options for diagnosing application performance problems.", + "options": { + "workflow": { + "value": "", + "description": "Specify a workflow for profiling. A workflow is a script of automated actions, such as adding nodes or opening visualizations. To view the list of available workflows, use '-profile.workflow=help'. This option must be used with '-startup.entry=profile'.", + "primary": false + }, + "emitUserTimingMeasurements": { + "value": false, + "description": "When enabled, profiling measurements will be submitted continuously to the User Timing Web API, which can be viewed using standard developer tools. Note that this mode significantly affects performance.", + "primary": false + } + } + } + } +} diff --git a/app/ide-desktop/lib/content-config/src/index.ts b/app/ide-desktop/lib/content-config/src/index.ts new file mode 100644 index 000000000000..311352a05458 --- /dev/null +++ b/app/ide-desktop/lib/content-config/src/index.ts @@ -0,0 +1,38 @@ +/** @file Configuration options of the application content (the web part). */ + +import * as semver from 'semver' +import { log, config, App } from '../../../../../target/ensogl-pack/linked-dist/index' +import buildCfg from '../../../build.json' + +const Option = config.Option +const Group = config.Group +const logger = log.logger +export { Option, Group, logger } +export type Option = config.Option + +// =============== +// === Version === +// ===============s + +export class Version { + /// Development version. + static dev = new semver.SemVer('0.0.0') + static devPrerelease = 'dev' + + /// Version of the `client` js package. + static ide = new semver.SemVer(buildCfg.version, { loose: true }) + + static isDev(): boolean { + const clientVersion = Version.ide + const releaseDev = clientVersion.compareMain(Version.dev) === 0 + const prereleaseDev = clientVersion.prerelease.toString().includes(Version.devPrerelease) + return releaseDev || prereleaseDev + } +} + +// =============== +// === Options === +// =============== + +import * as jsonCfg from './config.json' +export const options = config.options.merge(config.objectToGroup(jsonCfg, { Version })) diff --git a/app/ide-desktop/lib/content-config/tsconfig.json b/app/ide-desktop/lib/content-config/tsconfig.json new file mode 100644 index 000000000000..3041c599789f --- /dev/null +++ b/app/ide-desktop/lib/content-config/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "paths": { + "@ensogl-app": ["../../../../target/ensogl-pack/linked-dist/index"], + "@build-cfg": ["../../build.json"] + } + } +} diff --git a/app/ide-desktop/lib/content/.eslintrc.cjs b/app/ide-desktop/lib/content/.eslintrc.cjs new file mode 100644 index 000000000000..959c2237639c --- /dev/null +++ b/app/ide-desktop/lib/content/.eslintrc.cjs @@ -0,0 +1,74 @@ +// TODO: Some of the config options are commented out because eslint is not configured properly. +// This will be fixed in the future. +module.exports = { + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + // 'plugin:@typescript-eslint/recommended-requiring-type-checking', + // 'plugin:@typescript-eslint/strict', + ], + parser: '@typescript-eslint/parser', + plugins: ['jsdoc', '@typescript-eslint'], + root: true, + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-this-alias': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/naming-convention': 'error', + // '@typescript-eslint/no-unnecessary-condition': 'error', + // '@typescript-eslint/restrict-template-expressions': [ + // 'error', + // { + // allowAny: true, + // allowBoolean: true, + // }, + // ], + 'jsdoc/check-access': 'warn', + 'jsdoc/check-alignment': 'warn', + 'jsdoc/check-indentation': 'warn', + 'jsdoc/check-line-alignment': 'warn', + 'jsdoc/check-param-names': 'warn', + 'jsdoc/check-property-names': 'warn', + 'jsdoc/check-syntax': 'warn', + 'jsdoc/check-tag-names': 'warn', + 'jsdoc/check-types': 'warn', + 'jsdoc/check-values': 'warn', + 'jsdoc/empty-tags': 'warn', + 'jsdoc/implements-on-classes': 'warn', + 'jsdoc/no-bad-blocks': 'warn', + 'jsdoc/no-defaults': 'warn', + 'jsdoc/no-multi-asterisks': 'warn', + 'jsdoc/no-types': 'warn', + 'jsdoc/no-undefined-types': 'warn', + 'jsdoc/require-asterisk-prefix': 'warn', + 'jsdoc/require-description': 'warn', + // 'jsdoc/require-description-complete-sentence': 'warn, + 'jsdoc/require-file-overview': 'warn', + 'jsdoc/require-hyphen-before-param-description': 'warn', + 'jsdoc/require-jsdoc': 'warn', + 'jsdoc/require-param-description': 'warn', + 'jsdoc/require-param-name': 'warn', + 'jsdoc/require-param-type': 'warn', + 'jsdoc/require-property': 'warn', + 'jsdoc/require-property-description': 'warn', + 'jsdoc/require-property-name': 'warn', + 'jsdoc/require-property-type': 'warn', + 'jsdoc/require-returns-check': 'warn', + 'jsdoc/require-returns-description': 'warn', + 'jsdoc/require-throws': 'warn', + 'jsdoc/require-yields': 'warn', + 'jsdoc/require-yields-check': 'warn', + 'jsdoc/tag-lines': 'warn', + 'jsdoc/valid-types': 'warn', + }, + overrides: [ + { + files: ['*.ts', '*.tsx'], + parserOptions: { + project: ['./tsconfig.json'], + }, + }, + ], +} diff --git a/app/ide-desktop/lib/content/esbuild-config.ts b/app/ide-desktop/lib/content/esbuild-config.ts index dbd074fa9631..4583000d059f 100644 --- a/app/ide-desktop/lib/content/esbuild-config.ts +++ b/app/ide-desktop/lib/content/esbuild-config.ts @@ -112,8 +112,9 @@ const config: esbuild.BuildOptions = { sourcemap: true, minify: true, metafile: true, + format: 'esm', publicPath: '/assets', - platform: 'node', + platform: 'browser', incremental: true, color: true, logOverride: { @@ -152,7 +153,12 @@ export async function watch(onRebuild?: () => void, inject?: esbuild.BuildOption * Bundles the package. */ export async function bundle() { - return esbuild.build({ ...config, watch: false, incremental: false }) + try { + return esbuild.build({ ...config, watch: false, incremental: false }) + } catch (error) { + console.error(error) + throw error + } } export default { watch, bundle, output_path } diff --git a/app/ide-desktop/lib/content/package.json b/app/ide-desktop/lib/content/package.json index b45cd6848ca3..28563c759238 100644 --- a/app/ide-desktop/lib/content/package.json +++ b/app/ide-desktop/lib/content/package.json @@ -15,33 +15,40 @@ "url": "https://github.com/enso-org/ide/issues" }, "scripts": { + "typecheck": "npx tsc --noEmit", + "lint": "npx --yes eslint src", "build": "ts-node bundle.ts", "watch": "ts-node watch.ts", "start": "ts-node start.ts" }, "dependencies": { + "@types/mixpanel-browser": "^2.38.0", "@types/semver": "^7.3.9", - "html-loader": "^4.2.0", - "mixpanel-browser": "2.45.0", + "enso-content-config": "^1.0.0", "enso-gui-server": "^1.0.0", - "@types/mixpanel-browser": "^2.38.0" + "html-loader": "^4.2.0", + "mixpanel-browser": "2.45.0" }, "devDependencies": { - "@esbuild-plugins/node-modules-polyfill": "^0.1.4", "@esbuild-plugins/node-globals-polyfill": "^0.1.1", + "@esbuild-plugins/node-modules-polyfill": "^0.1.4", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "enso-copy-plugin": "^1.0.0", + "enso-gui-server": "^1.0.0", "esbuild": "^0.15.14", - "esbuild-dev-server": "^0.3.0", "esbuild-copy-static-files": "^0.1.0", + "esbuild-dev-server": "^0.3.0", "esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-time": "^1.0.0", "esbuild-plugin-yaml": "^0.0.1", + "eslint": "^8.30.0", + "eslint-plugin-jsdoc": "^40.0.0", "glob": "^8.0.3", - "ts-node": "^10.9.1", "source-map-loader": "^4.0.1", "ts-loader": "^9.3.0", + "ts-node": "^10.9.1", "typescript": "^4.9.3", - "yaml-loader": "^0.8.0", - "enso-gui-server": "^1.0.0", - "enso-copy-plugin": "^1.0.0" + "yaml-loader": "^0.8.0" } } diff --git a/app/ide-desktop/lib/content/src/index.html b/app/ide-desktop/lib/content/src/index.html index 4252f15b6fc9..909d66fd20a8 100644 --- a/app/ide-desktop/lib/content/src/index.html +++ b/app/ide-desktop/lib/content/src/index.html @@ -27,10 +27,10 @@ user-scalable = no" /> Enso - - - - + + + +
diff --git a/app/ide-desktop/lib/content/src/index.ts b/app/ide-desktop/lib/content/src/index.ts index d54bd587342f..3dda2fdc9171 100644 --- a/app/ide-desktop/lib/content/src/index.ts +++ b/app/ide-desktop/lib/content/src/index.ts @@ -1,28 +1,28 @@ -/// This module is responsible for loading the WASM binary, its dependencies, and providing the -/// user with a visual representation of this process (welcome screen). It also implements a view -/// allowing to choose a debug rendering test from. +/** @file This module is responsible for loading the WASM binary, its dependencies, and providing + * the user with a visual representation of this process (welcome screen). It also implements a view + * allowing to choose a debug rendering test from. */ // @ts-ignore import globalConfig from '../../../../gui/config.yaml' -import buildCfg from '../../../build.json' -import * as app from 'ensogl_app' +import * as app from '../../../../../target/ensogl-pack/linked-dist/index' import * as semver from 'semver' +import { Version, options } from 'enso-content-config' const logger = app.log.logger -const config = app.config // ============= // === Fetch === // ============= -const Timeout = (time: number) => { - let controller = new AbortController() +const timeout = (time: number) => { + const controller = new AbortController() setTimeout(() => controller.abort(), time * 1000) return controller } -async function fetchTimeout(url: string, timeout: number): Promise { - return fetch(url, { signal: Timeout(10).signal }).then(response => { +/** A version of `fetch` which timeouts after the provided time. */ +async function fetchTimeout(url: string, timeoutSeconds: number): Promise { + return fetch(url, { signal: timeout(timeoutSeconds).signal }).then(response => { const statusCodeOK = 200 if (response.status === statusCodeOK) { return response.json() @@ -32,40 +32,18 @@ async function fetchTimeout(url: string, timeout: number): Promise { }) } -// =============== -// === Version === -// =============== - -class Version { - /// Development version. - static dev = new semver.SemVer('0.0.0') - static devPrerelease = 'dev' - - /// Version of the `client` js package. - static ide = new semver.SemVer(buildCfg.version, { loose: true }) - - static isDev(): boolean { - const clientVersion = Version.ide - const releaseDev = clientVersion.compareMain(Version.dev) === 0 - const prereleaseDev = clientVersion.prerelease.toString().includes(Version.devPrerelease) - return releaseDev || prereleaseDev - } -} - -/// Return `true` if the current application version is still supported -/// and `false` otherwise. -/// -/// Function downloads the application config containing the minimum supported -/// version from GitHub and compares it with the version of the `client` js -/// package. When the function is unable to download the application config, or -/// one of the compared versions does not match the semver scheme, it returns -/// `true`. -async function checkMinSupportedVersion(config: Config) { - if (config.skipMinVersionCheck.value === true) { +/** Return `true` if the current application version is still supported and `false` otherwise. + * + * Function downloads the application config containing the minimum supported version from GitHub + * and compares it with the version of the `client` js package. When the function is unable to + * download the application config, or one of the compared versions does not match the semver + * scheme, it returns `true`. */ +async function checkMinSupportedVersion(config: typeof options) { + if (config.groups.engine.options.skipMinVersionCheck.value === true) { return true } try { - const appConfig: any = await fetchTimeout(config.applicationConfigUrl.value, 300) + const appConfig: any = await fetchTimeout(config.groups.engine.options.configUrl.value, 300) const minSupportedVersion = appConfig.minimumSupportedVersion const comparator = new semver.Comparator(`>=${minSupportedVersion}`) return comparator.test(Version.ide) @@ -75,115 +53,23 @@ async function checkMinSupportedVersion(config: Config) { } } +/** Display information that the current app version is deprecated. */ function displayDeprecatedVersionDialog() { const versionCheckText = document.createTextNode( 'This version is no longer supported. Please download a new one.' ) - let root = document.getElementById('root') - let versionCheckDiv = document.createElement('div') + const root = document.getElementById('root') + const versionCheckDiv = document.createElement('div') versionCheckDiv.id = 'version-check' versionCheckDiv.className = 'auth-info' versionCheckDiv.style.display = 'block' versionCheckDiv.appendChild(versionCheckText) - root.appendChild(versionCheckDiv) -} - -// ============== -// === Config === -// ============== - -class Config { - project: config.Param = new config.Param( - null, - 'Project name to open on startup.' - ) - projectManager: config.Param = new config.Param( - null, - 'An address of the Project Manager service.' - ) - languageServerRpc: config.Param = new config.Param( - null, - 'An address of the Language Server RPC endpoint. This argument should be provided ' + - 'together with `languageServerData` ,`namespace`, and `project` options. They make ' + - 'Enso connect directly to the already spawned Language Server of some project.' - ) - languageServerData: config.Param = new config.Param( - null, - 'An address of the Language Server Data endpoint. This argument should be provided ' + - 'together with `languageServerData` ,`namespace`, and `project` options. They make ' + - 'Enso connect directly to the already spawned Language Server of some project.' - ) - namespace: config.Param = new config.Param( - null, - 'Informs Enso about namespace of the opened project. May be used when connecting to ' + - 'existing Language Server process. Defaults to "local".' - ) - platform: config.Param = new config.Param( - null, - 'The host platform the app is running on. This is used to adjust some UI elements. For ' + - 'example, on macOS, the window close buttons are integrated to the top app panel.' - ) - frame: config.Param = new config.Param( - false, - 'Controls whether a window frame should be visible. Works in native app only.' - ) - darkTheme: config.Param = new config.Param( - false, - 'Controls whether the dark theme should be used. Please note that the dark theme is not ' + - 'fully implemented yet.' - ) - nodeLabels: config.Param = new config.Param( - true, - `Controls whether node labels should be visible.` - ) - dataGathering: config.Param = new config.Param( - true, - 'Controls whether anonymous data gathering should be enabled.' - ) - isInCloud: config.Param = new config.Param( - false, - 'Information if the app is running in the cloud.' - ) - authenticationEnabled: config.Param = new config.Param( - true, - 'Controls whether user authentication is enabled.' - ) - email: config.Param = new config.Param(null, 'The user email, if any.') - applicationConfigUrl: config.Param = new config.Param( - 'https://raw.githubusercontent.com/enso-org/ide/develop/config.json', - 'The application config URL. Used to check for available updates.' - ) - testWorkflow: config.Param = new config.Param( - null, - 'When profiling the application (e.g. with the `./run profile` command), this argument ' + - 'chooses what is profiled.' - ) - skipMinVersionCheck: config.Param = new config.Param( - Version.isDev(), - 'Controls whether the minimum engine version check should be performed. It is set to ' + - '`true` in local builds.' - ) - debug: config.Param = new config.Param( - Version.isDev(), - 'Controls whether the application should be run in the debug mode. In this mode all logs ' + - 'are printed to the console. Otherwise, the logs are hidden unless explicitly shown ' + - 'by calling `showLogs`. Moreover, additional logs from libraries are printed in ' + - 'this mode. The debug mode is set to `true` by default in local builds.' - ) - preferredEngineVersion: config.Param = new config.Param( - Version.ide, - `The preferred engine version.` - ) - enableNewComponentBrowser: config.Param = new config.Param( - true, - 'Controls whether the new component browser should be enabled.' - ) - emitUserTimingMeasurements: config.Param = new config.Param(false, 'TODO') - enableSkipAndFreeze: config.Param = new config.Param( - false, - 'Enable experimental support for skipping and freezing nodes.' - ) + if (root == null) { + console.error('Cannot find the root DOM element.') + } else { + root.appendChild(versionCheckDiv) + } } // ======================== @@ -191,34 +77,37 @@ class Config { // ======================== class Main { - async main(inputConfig: any) { - const config = Object.assign( - { - pkgWasmUrl: 'assets/pkg-opt.wasm', - pkgJsUrl: 'assets/pkg.js', - shadersUrl: 'assets/shaders', + async main() { + const config = { + loader: { + wasmUrl: 'pkg-opt.wasm', + jsUrl: 'pkg.js', + shadersUrl: 'shaders', }, - inputConfig - ) + } + const appInstance = new app.App({ config, - configExtension: new Config(), + configOptions: options, packageInfo: { + // @ts-ignore version: BUILD_INFO.default.version, + // @ts-ignore engineVersion: BUILD_INFO.default.engineVersion, }, }) if (appInstance.initialized) { - if (appInstance.config.params.dataGathering.value) { + if (options.options.dataCollection.value) { // TODO: Add remote-logging here. } - if (!(await checkMinSupportedVersion(appInstance.config.params))) { + if (!(await checkMinSupportedVersion(options))) { displayDeprecatedVersionDialog() } else { if ( - appInstance.config.params.authenticationEnabled.value && - appInstance.config.params.entry.value != appInstance.config.params.entry.default + options.options.authentication.value && + options.groups.startup.options.entry.value != + options.groups.startup.options.entry.default ) { // TODO: authentication here // appInstance.config.email.value = user.email @@ -226,10 +115,13 @@ class Main { } else { appInstance.run() } - if (appInstance.config.params.email.value) { - logger.log(`User identified as '${appInstance.config.params.email.value}'.`) + const email = options.groups.authentication.options.email.value + if (email != null) { + logger.log(`User identified as '${email}'.`) } } + } else { + console.error('Failed to initialize the application.') } } } diff --git a/app/ide-desktop/lib/content/src/project_manager.ts b/app/ide-desktop/lib/content/src/project_manager.ts index 9f8c29f45b56..7c54a500c5a2 100644 --- a/app/ide-desktop/lib/content/src/project_manager.ts +++ b/app/ide-desktop/lib/content/src/project_manager.ts @@ -1,26 +1,22 @@ -/// This module defines the Project Manager endpoint. +/** @file This module defines the Project Manager endpoint. */ const PROJECT_MANAGER_ENDPOINT = 'ws://127.0.0.1:30535' const MISSING_COMPONENT_ACTION_INSTALL = 'Install' -/** - * A WebSocket endpoint to the project manager. - */ +/** A WebSocket endpoint to the project manager. */ class ProjectManager { - protected readonly connection_url: string + protected readonly connectionUrl: string - constructor(connection_url: string) { - this.connection_url = connection_url + constructor(connectionUrl: string) { + this.connectionUrl = connectionUrl } static default() { return new ProjectManager(PROJECT_MANAGER_ENDPOINT) } - /** - * Get the projects list. - */ + /** * Get the projects list. */ listProjects(): any { const req = { jsonrpc: '2.0', @@ -29,7 +25,7 @@ class ProjectManager { params: {}, } - const ws = new WebSocket(this.connection_url) + const ws = new WebSocket(this.connectionUrl) return new Promise((resolve, reject) => { ws.onopen = () => { ws.send(JSON.stringify(req)) @@ -43,15 +39,9 @@ class ProjectManager { }).finally(() => ws.close()) } - /** - * Create an new project. - * - * @param name the project name - * @param template the project template - * @param action parameter specifying how to handle missing components - */ + /** * Create an new project. */ createProject(name: string, template?: string, action = MISSING_COMPONENT_ACTION_INSTALL): any { - let params = { + const params = { name: name, missingComponentAction: action, } @@ -66,7 +56,7 @@ class ProjectManager { params: params, } - const ws = new WebSocket(this.connection_url) + const ws = new WebSocket(this.connectionUrl) return new Promise((resolve, reject) => { ws.onopen = () => { ws.send(JSON.stringify(req)) diff --git a/app/ide-desktop/lib/content/src/run.js b/app/ide-desktop/lib/content/src/run.js index 124b45c3c3ac..deb0f6be72d2 100644 --- a/app/ide-desktop/lib/content/src/run.js +++ b/app/ide-desktop/lib/content/src/run.js @@ -1,4 +1,5 @@ -/// This file is used to simply run the IDE. It can be not invoked if the IDE needs to be used as a -/// library. +/** @file This file is used to simply run the IDE. It can be not invoked if the IDE needs to be used + * as a library. */ +/* eslint no-undef: "off" */ window.enso.main() diff --git a/app/ide-desktop/lib/content/src/style.css b/app/ide-desktop/lib/content/src/style.css index d609f16324d6..836b0fc0d895 100644 --- a/app/ide-desktop/lib/content/src/style.css +++ b/app/ide-desktop/lib/content/src/style.css @@ -2,14 +2,14 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-weight: 100; font-display: block; } @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 200; font-display: block; @@ -17,7 +17,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 300; font-display: block; @@ -25,7 +25,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 400; font-display: block; @@ -33,7 +33,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 500; font-display: block; @@ -41,7 +41,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 600; font-display: block; @@ -49,7 +49,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 700; font-display: block; @@ -57,7 +57,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 800; font-display: block; @@ -65,7 +65,7 @@ @font-face { font-family: "M PLUS 1"; - src: url("/assets/MPLUS1[wght].ttf") format("truetype"); + src: url("/MPLUS1[wght].ttf") format("truetype"); font-style: normal; font-weight: 900; font-display: block; diff --git a/app/ide-desktop/lib/content/src/wasm_imports.js b/app/ide-desktop/lib/content/src/wasm_imports.js index 97e768e4e448..8b2de030b735 100644 --- a/app/ide-desktop/lib/content/src/wasm_imports.js +++ b/app/ide-desktop/lib/content/src/wasm_imports.js @@ -1,3 +1,6 @@ +/** @file This module exports wasm Rust glue code generated by EnsoGL Pack. */ + import { default as init } from 'wasm_rust_glue' +/* eslint no-undef: "off" */ exports.init = init diff --git a/app/ide-desktop/lib/content/tsconfig.json b/app/ide-desktop/lib/content/tsconfig.json new file mode 100644 index 000000000000..3041c599789f --- /dev/null +++ b/app/ide-desktop/lib/content/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "paths": { + "@ensogl-app": ["../../../../target/ensogl-pack/linked-dist/index"], + "@build-cfg": ["../../build.json"] + } + } +} diff --git a/app/ide-desktop/package-lock.json b/app/ide-desktop/package-lock.json index f166d43eb9dd..c41133373a16 100644 --- a/app/ide-desktop/package-lock.json +++ b/app/ide-desktop/package-lock.json @@ -11,6 +11,7 @@ "workspaces": [ "lib/client", "lib/content", + "lib/content-config", "lib/copy-plugin", "lib/icons", "lib/server" @@ -23,16 +24,18 @@ "name": "enso", "version": "0.0.0-dev", "dependencies": { - "@electron/remote": "^2.0.8", + "@types/mime-types": "^2.1.1", + "chalk": "^5.2.0", "create-servers": "^3.2.0", "electron-is-dev": "^2.0.0", "enso-gui-server": "^1.0.0", "mime-types": "^2.1.35", + "string-length": "^5.0.1", "yargs": "17.6.2" }, "devDependencies": { "crypto-js": "4.1.1", - "electron": "21.3.0", + "electron": "23.0.0", "electron-builder": "^22.14.13", "electron-notarize": "1.2.2", "enso-copy-plugin": "^1.0.0", @@ -41,12 +44,343 @@ "ts-node": "^10.9.1" } }, + "lib/client/node_modules/@electron/universal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", + "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", + "dev": true, + "dependencies": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "lib/client/node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "lib/client/node_modules/app-builder-bin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", + "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", + "dev": true + }, + "lib/client/node_modules/app-builder-lib": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", + "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.0.5", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.2", + "ejs": "^3.1.6", + "electron-osx-sign": "^0.5.0", + "electron-publish": "22.14.13", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "hosted-git-info": "^4.0.2", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.8", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.0.4", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.5", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "lib/client/node_modules/builder-util": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", + "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "3.7.1", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "lib/client/node_modules/builder-util-runtime": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", + "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", + "dev": true, + "dependencies": { + "debug": "^4.3.2", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "lib/client/node_modules/builder-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "lib/client/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "lib/client/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "lib/client/node_modules/dmg-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", + "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", + "dev": true, + "dependencies": { + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.9" + } + }, + "lib/client/node_modules/electron-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", + "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", + "dev": true, + "dependencies": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "dmg-builder": "22.14.13", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "update-notifier": "^5.1.0", + "yargs": "^17.0.1" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "lib/client/node_modules/electron-builder/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "lib/client/node_modules/electron-osx-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", + "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", + "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different", + "dev": true, + "dependencies": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "lib/client/node_modules/electron-osx-sign/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "lib/client/node_modules/electron-osx-sign/node_modules/isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "dependencies": { + "buffer-alloc": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "lib/client/node_modules/electron-osx-sign/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "lib/client/node_modules/electron-publish": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", + "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "lib/client/node_modules/electron-publish/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "lib/client/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "lib/client/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "lib/client/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "lib/content": { "name": "enso-studio-content", "version": "1.0.0", "dependencies": { "@types/mixpanel-browser": "^2.38.0", "@types/semver": "^7.3.9", + "enso-content-config": "^1.0.0", "enso-gui-server": "^1.0.0", "html-loader": "^4.2.0", "mixpanel-browser": "2.45.0" @@ -54,6 +388,8 @@ "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "^0.1.1", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", "enso-copy-plugin": "^1.0.0", "enso-gui-server": "^1.0.0", "esbuild": "^0.15.14", @@ -62,6 +398,8 @@ "esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-time": "^1.0.0", "esbuild-plugin-yaml": "^0.0.1", + "eslint": "^8.30.0", + "eslint-plugin-jsdoc": "^40.0.0", "glob": "^8.0.3", "source-map-loader": "^4.0.1", "ts-loader": "^9.3.0", @@ -70,6 +408,10 @@ "yaml-loader": "^0.8.0" } }, + "lib/content-config": { + "name": "enso-content-config", + "version": "1.0.0" + }, "lib/content/node_modules/glob": { "version": "8.0.3", "dev": true, @@ -167,72 +509,27 @@ } }, "node_modules/@electron/get": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", - "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", + "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", + "dev": true, "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", - "got": "^9.6.0", + "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "engines": { - "node": ">=8.6" + "node": ">=12" }, "optionalDependencies": { - "global-agent": "^3.0.0", - "global-tunnel-ng": "^2.7.1" + "global-agent": "^3.0.0" } }, "node_modules/@electron/get/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@electron/get/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@electron/remote": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-2.0.9.tgz", - "integrity": "sha512-LR0W0ID6WAKHaSs0x5LX9aiG+5pFBNAJL6eQAJfGkCuZPUa6nZz+czZLdlTDETG45CgF/0raSvCtYOYUpr6c+A==", - "peerDependencies": { - "electron": ">= 13.0.0" - } - }, - "node_modules/@electron/universal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", - "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", - "dev": true, - "dependencies": { - "@malept/cross-spawn-promise": "^1.1.0", - "asar": "^3.0.3", - "debug": "^4.3.1", - "dir-compare": "^2.4.0", - "fs-extra": "^9.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/@electron/universal/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", @@ -249,46 +546,56 @@ } } }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=6 <7 || >=8" } }, - "node_modules/@electron/universal/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/@electron/get/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, - "node_modules/@electron/universal/node_modules/ms": { + "node_modules/@electron/get/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@electron/universal/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">= 4.0.0" + } + }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz", + "integrity": "sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg==", + "dev": true, + "dependencies": { + "comment-parser": "1.3.1", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "~3.1.0" + }, + "engines": { + "node": "^14 || ^16 || ^17 || ^18 || ^19" } }, "node_modules/@esbuild-plugins/node-globals-polyfill": { @@ -345,6 +652,120 @@ "node": ">=12" } }, + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -451,48 +872,12 @@ } } }, - "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/@malept/flatpak-bundler/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@malept/flatpak-bundler/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -529,22 +914,27 @@ } }, "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, "dependencies": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" } }, "node_modules/@tootallnate/once": { @@ -580,6 +970,18 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -624,91 +1026,445 @@ "@types/node": "*" } }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "optional": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/mime-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "optional": true + }, + "node_modules/@types/mixpanel-browser": { + "version": "2.38.0", + "resolved": "https://registry.npmjs.org/@types/mixpanel-browser/-/mixpanel-browser-2.38.0.tgz", + "integrity": "sha512-TR8rvsILnqXA7oiiGOxuMGXwvDeCoQDonXJB5UR+TYvEAFpiK8ReFj5LhZT+Xhm3NpI9aPoju30jB2ssorSUww==" + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" + }, + "node_modules/@types/plist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + }, + "node_modules/@types/verror": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz", + "integrity": "sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ==", + "dev": true, + "optional": true + }, + "node_modules/@types/yargs": { + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", + "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", "dev": true, - "optional": true, "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "peer": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "optional": true - }, - "node_modules/@types/mixpanel-browser": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/@types/mixpanel-browser/-/mixpanel-browser-2.38.0.tgz", - "integrity": "sha512-TR8rvsILnqXA7oiiGOxuMGXwvDeCoQDonXJB5UR+TYvEAFpiK8ReFj5LhZT+Xhm3NpI9aPoju30jB2ssorSUww==" + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" - }, - "node_modules/@types/plist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz", - "integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, - "optional": true, "dependencies": { - "@types/node": "*", - "xmlbuilder": ">=11.0.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" - }, - "node_modules/@types/verror": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.6.tgz", - "integrity": "sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ==", + "node_modules/@typescript-eslint/utils": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", "dev": true, - "optional": true + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, - "node_modules/@types/yargs": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", - "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { - "@types/yargs-parser": "*" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "optional": true, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", + "dev": true, "dependencies": { - "@types/node": "*" + "@typescript-eslint/types": "5.52.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@webassemblyjs/ast": { @@ -907,147 +1663,37 @@ "acorn": "^8" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/app-builder-bin": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", - "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", - "dev": true - }, - "node_modules/app-builder-lib": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", - "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", - "dev": true, - "dependencies": { - "@develar/schema-utils": "~2.6.5", - "@electron/universal": "1.0.5", - "@malept/flatpak-bundler": "^0.4.0", - "7zip-bin": "~5.1.1", - "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", - "electron-osx-sign": "^0.5.0", - "electron-publish": "22.14.13", - "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", - "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", - "js-yaml": "^4.1.0", - "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", - "read-config-file": "6.2.0", - "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", - "temp-file": "^3.4.0" + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" }, "engines": { - "node": ">=14.0.0" + "node": ">= 6.0.0" } }, - "node_modules/app-builder-lib/node_modules/debug": { + "node_modules/agent-base/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", @@ -1064,60 +1710,64 @@ } } }, - "node_modules/app-builder-lib/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/app-builder-lib/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { - "universalify": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/app-builder-lib/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } }, - "node_modules/app-builder-lib/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/app-builder-lib/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/arg": { @@ -1132,6 +1782,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -1336,6 +1995,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, "optional": true }, "node_modules/boxen": { @@ -1465,6 +2125,7 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "engines": { "node": "*" } @@ -1489,148 +2150,40 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/builder-util": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", - "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", - "dev": true, - "dependencies": { - "@types/debug": "^4.1.6", - "@types/fs-extra": "^9.0.11", - "7zip-bin": "~5.1.1", - "app-builder-bin": "3.7.1", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "cross-spawn": "^7.0.3", - "debug": "^4.3.2", - "fs-extra": "^10.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-ci": "^3.0.0", - "js-yaml": "^4.1.0", - "source-map-support": "^0.5.19", - "stat-mode": "^1.0.0", - "temp-file": "^3.4.0" - } - }, - "node_modules/builder-util-runtime": { - "version": "8.9.2", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", - "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", - "dev": true, - "dependencies": { - "debug": "^4.3.2", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/builder-util-runtime/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/builder-util-runtime/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/builder-util/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/builder-util/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/builder-util/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/builder-util/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/builder-util/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=10.6.0" } }, "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/camel-case": { @@ -1692,6 +2245,14 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "engines": { + "node": ">=12.20" + } + }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -1785,6 +2346,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, "dependencies": { "mimic-response": "^1.0.0" }, @@ -1861,6 +2423,15 @@ "node": ">= 6" } }, + "node_modules/comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -1876,16 +2447,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "optional": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -2004,14 +2565,30 @@ } }, "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, "dependencies": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-extend": { @@ -2023,15 +2600,26 @@ "node": ">=4.0.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, "optional": true, "dependencies": { "has-property-descriptors": "^1.0.0", @@ -2083,6 +2671,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, "optional": true }, "node_modules/diff": { @@ -2143,56 +2732,16 @@ "node": "*" } }, - "node_modules/dmg-builder": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", - "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", - "dev": true, - "dependencies": { - "app-builder-lib": "22.14.13", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "fs-extra": "^10.0.0", - "iconv-lite": "^0.6.2", - "js-yaml": "^4.1.0" - }, - "optionalDependencies": { - "dmg-license": "^1.0.9" - } - }, - "node_modules/dmg-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dmg-builder/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "path-type": "^4.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/dmg-builder/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=8" } }, "node_modules/dmg-license": { @@ -2221,6 +2770,18 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-walk": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", @@ -2266,7 +2827,8 @@ "node_modules/duplexer3": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true }, "node_modules/ecc-jsbn": { "version": "0.1.2", @@ -2299,12 +2861,13 @@ } }, "node_modules/electron": { - "version": "21.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-21.3.0.tgz", - "integrity": "sha512-MGRpshN8fBcx4IRuBABIsGDv0tB/MclIFsyFHFFXsBCUc+vIXaE/E6vuWaniGIFSz5WyeuapfTH5IeRb+7yIfw==", + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-23.0.0.tgz", + "integrity": "sha512-S6hVtTAjauMiiWP9sBVR5RpcUC464cNZ06I2EMUjeZBq+KooS6tLmNsfw0zLpAXDp1qosjlBP3v71NTZ3gd9iA==", + "dev": true, "hasInstallScript": true, "dependencies": { - "@electron/get": "^1.14.1", + "@electron/get": "^2.0.0", "@types/node": "^16.11.26", "extract-zip": "^2.0.1" }, @@ -2312,236 +2875,54 @@ "electron": "cli.js" }, "engines": { - "node": ">= 10.17.0" - } - }, - "node_modules/electron-builder": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", - "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", - "dev": true, - "dependencies": { - "@types/yargs": "^17.0.1", - "app-builder-lib": "22.14.13", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "dmg-builder": "22.14.13", - "fs-extra": "^10.0.0", - "is-ci": "^3.0.0", - "lazy-val": "^1.0.5", - "read-config-file": "6.2.0", - "update-notifier": "^5.1.0", - "yargs": "^17.0.1" - }, - "bin": { - "electron-builder": "cli.js", - "install-app-deps": "install-app-deps.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/electron-builder/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-builder/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-builder/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" + "node": ">= 12.20.55" } }, "node_modules/electron-is-dev": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-2.0.0.tgz", "integrity": "sha512-3X99K852Yoqu9AcW50qz3ibYBWY79/pBhlMCab8ToEWS48R0T9tyxRiQhwylE7zQdXrMnx2JKqUJyMPmt5FBqA==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/electron-notarize": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.2.tgz", - "integrity": "sha512-ZStVWYcWI7g87/PgjPJSIIhwQXOaw4/XeXU+pWqMMktSLHaGMLHdyPPN7Cmao7+Cr7fYufA16npdtMndYciHNw==", - "deprecated": "Please use @electron/notarize moving forward. There is no API change, just a package name change", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-notarize/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/electron-notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-notarize/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-notarize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/electron-notarize/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-osx-sign": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", - "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", - "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different", - "dev": true, - "dependencies": { - "bluebird": "^3.5.0", - "compare-version": "^0.1.2", - "debug": "^2.6.8", - "isbinaryfile": "^3.0.2", - "minimist": "^1.2.0", - "plist": "^3.0.1" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/electron-osx-sign/node_modules/isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "dependencies": { - "buffer-alloc": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/electron-publish": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", - "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", - "dev": true, - "dependencies": { - "@types/fs-extra": "^9.0.11", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "fs-extra": "^10.0.0", - "lazy-val": "^1.0.5", - "mime": "^2.5.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-publish/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/electron-notarize": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.2.tgz", + "integrity": "sha512-ZStVWYcWI7g87/PgjPJSIIhwQXOaw4/XeXU+pWqMMktSLHaGMLHdyPPN7Cmao7+Cr7fYufA16npdtMndYciHNw==", + "deprecated": "Please use @electron/notarize moving forward. There is no API change, just a package name change", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "debug": "^4.1.1", + "fs-extra": "^9.0.1" }, "engines": { - "node": ">=12" + "node": ">= 10.0.0" } }, - "node_modules/electron-publish/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/electron-notarize/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "universalify": "^2.0.0" + "ms": "2.1.2" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-publish/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/electron-notarize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/electron-to-chromium": { "version": "1.4.284", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", @@ -2551,7 +2932,8 @@ "node_modules/electron/node_modules/@types/node": { "version": "16.18.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -2579,6 +2961,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -2599,6 +2982,10 @@ "resolved": "lib/client", "link": true }, + "node_modules/enso-content-config": { + "resolved": "lib/content-config", + "link": true + }, "node_modules/enso-copy-plugin": { "resolved": "lib/copy-plugin", "link": true @@ -2630,6 +3017,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, "engines": { "node": ">=6" } @@ -2652,6 +3040,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, "optional": true }, "node_modules/es6-promise": { @@ -3118,42 +3507,6 @@ "js-yaml": "^4.0.0" } }, - "node_modules/esbuild-plugin-yaml/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/esbuild-plugin-yaml/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/esbuild-plugin-yaml/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/esbuild-sunos-64": { "version": "0.15.18", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", @@ -3194,82 +3547,338 @@ "x64" ], "dev": true, - "optional": true, - "os": [ - "win32" - ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.0.0.tgz", + "integrity": "sha512-LOPyIu1vAVvGPkye3ci0moj0iNf3f8bmin6do2DYDj+77NRXWnkmhKRy8swWsatUs3mB5jYPWPUsFg9pyfEiyA==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.36.1", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.4.0", + "semver": "^7.3.8", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": "^14 || ^16 || ^17 || ^18 || ^19" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "cpu": [ - "arm64" - ], + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">=4.0" } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">=6" + "node": ">=10.13.0" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "devOptional": true, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -3281,7 +3890,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "peer": true, "engines": { "node": ">=4.0" } @@ -3290,7 +3898,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true, "engines": { "node": ">=4.0" } @@ -3301,6 +3908,15 @@ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", "dev": true }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -3343,6 +3959,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -3362,6 +3979,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -3377,7 +3995,8 @@ "node_modules/extract-zip/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/extsprintf": { "version": "1.3.0", @@ -3414,6 +4033,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -3427,10 +4052,23 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "dependencies": { "pend": "~1.2.0" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", @@ -3450,9 +4088,9 @@ } }, "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -3490,6 +4128,22 @@ "node": ">= 0.8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -3499,6 +4153,40 @@ "micromatch": "^4.0.2" } }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3537,16 +4225,18 @@ "dev": true }, "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "dependencies": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=10" } }, "node_modules/fs.realpath": { @@ -3559,6 +4249,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, "optional": true }, "node_modules/get-caller-file": { @@ -3570,9 +4261,10 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, "optional": true, "dependencies": { "function-bind": "^1.1.1", @@ -3587,6 +4279,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "dependencies": { "pump": "^3.0.0" }, @@ -3664,6 +4357,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -3681,6 +4375,7 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, "optional": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3716,25 +4411,38 @@ "node": ">=10" } }, - "node_modules/global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "optional": true, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, "dependencies": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, "optional": true, "dependencies": { "define-properties": "^1.1.3" @@ -3746,36 +4454,58 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=8.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "node_modules/globby/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, "dependencies": { - "pump": "^3.0.0" + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, "node_modules/graceful-fs": { @@ -3789,6 +4519,12 @@ "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", "dev": true }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -3816,6 +4552,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "optional": true, "dependencies": { "function-bind": "^1.1.1" @@ -3836,6 +4573,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, "optional": true, "dependencies": { "get-intrinsic": "^1.1.1" @@ -3848,6 +4586,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "optional": true, "engines": { "node": ">= 0.4" @@ -3925,9 +4664,10 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -4004,6 +4744,19 @@ "npm": ">=1.3.7" } }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4089,6 +4842,15 @@ } ] }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", @@ -4101,6 +4863,22 @@ "node": ">=0.10.0" } }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -4138,7 +4916,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "devOptional": true + "dev": true }, "node_modules/ip-regex": { "version": "1.0.3", @@ -4446,6 +5224,16 @@ "integrity": "sha512-CiRVjMKBUp6VYtGwzRjrdnro41yMwKGOWdP9ATXqmixdz2n7KHNwdqthTYSSbOKj/Ha79Gct1sA8ZQpse55TYA==", "dev": true }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4464,10 +5252,20 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz", + "integrity": "sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -4486,11 +5284,17 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "devOptional": true + "dev": true }, "node_modules/json5": { "version": "2.2.3", @@ -4505,9 +5309,13 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4542,11 +5350,12 @@ } }, "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dev": true, "dependencies": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "node_modules/klaw-sync": { @@ -4576,6 +5385,19 @@ "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", "dev": true }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/load-bmfont": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", @@ -4636,11 +5458,32 @@ "node": ">=8.9.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -4650,18 +5493,19 @@ } }, "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "devOptional": true, + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4703,6 +5547,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, "optional": true, "dependencies": { "escape-string-regexp": "^4.0.0" @@ -4774,6 +5619,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, "engines": { "node": ">=4" } @@ -4865,6 +5711,18 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -4927,125 +5785,317 @@ "peer": true }, "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" + "ee-first": "1.1.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json/node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/package-json/node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "optional": true, + "node_modules/package-json/node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" } }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "node_modules/package-json/node_modules/got/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, "dependencies": { - "ee-first": "1.1.1" + "pump": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "node_modules/package-json/node_modules/got/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } + "node_modules/package-json/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "node_modules/package-json/node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", "dev": true, "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "json-buffer": "3.0.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/package-json/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/p-cancelable": { + "node_modules/package-json/node_modules/p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "node_modules/package-json/node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", "dev": true, "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/package-json/node_modules/responselike/node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/param-case": { @@ -5057,6 +6107,18 @@ "tslib": "^2.0.3" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-bmfont-ascii": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", @@ -5176,21 +6238,6 @@ "node": ">=4.8" } }, - "node_modules/patch-package/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/patch-package/node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -5203,18 +6250,6 @@ "is-ci": "bin.js" } }, - "node_modules/patch-package/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/patch-package/node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -5254,15 +6289,6 @@ "node": ">=0.10.0" } }, - "node_modules/patch-package/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/patch-package/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5275,6 +6301,15 @@ "which": "bin/which" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -5293,10 +6328,20 @@ "node": ">=8" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, "node_modules/performance-now": { "version": "2.1.0", @@ -5328,15 +6373,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -5452,10 +6488,20 @@ "node": ">=10" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, "engines": { "node": ">=4" } @@ -5473,16 +6519,11 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "optional": true - }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -5493,6 +6534,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -5547,6 +6589,18 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5618,6 +6672,18 @@ "node": ">= 6" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/registry-auth-token": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", @@ -5734,12 +6800,31 @@ "node": ">=0.10.0" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, "dependencies": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/reusify": { @@ -5768,6 +6853,7 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, "optional": true, "dependencies": { "boolean": "^3.0.1", @@ -5882,6 +6968,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -5890,6 +6977,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, "optional": true }, "node_modules/semver-diff": { @@ -5966,6 +7054,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, "optional": true, "dependencies": { "type-fest": "^0.13.1" @@ -6116,36 +7205,9 @@ } ], "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, "node_modules/simple-swizzle": { @@ -6246,10 +7308,33 @@ "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true + }, "node_modules/sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, "optional": true }, "node_modules/sshpk": { @@ -6344,6 +7429,46 @@ } ] }, + "node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6381,6 +7506,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, "dependencies": { "debug": "^4.1.0" }, @@ -6392,6 +7518,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -6407,7 +7534,8 @@ "node_modules/sumchecker/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/supports-color": { "version": "7.2.0", @@ -6481,27 +7609,6 @@ "node": ">=12" } }, - "node_modules/temp-file/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/temp-file/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/terser": { "version": "5.16.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", @@ -6558,6 +7665,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/tinycolor2": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.5.2.tgz", @@ -6632,6 +7745,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, "engines": { "node": ">=6" } @@ -6760,15 +7874,27 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "optional": true, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -6787,10 +7913,23 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, "optional": true, "engines": { "node": ">=10" @@ -6834,11 +7973,12 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { @@ -6948,6 +8088,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, "dependencies": { "prepend-http": "^2.0.0" }, @@ -7114,6 +8255,15 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -7133,7 +8283,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/write-file-atomic": { "version": "3.0.3", @@ -7246,7 +8397,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true + "dev": true }, "node_modules/yaml": { "version": "1.10.2", @@ -7309,6 +8460,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -7322,6 +8474,18 @@ "engines": { "node": ">=6" } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -7357,54 +8521,20 @@ } }, "@electron/get": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", - "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", + "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", + "dev": true, "requires": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "global-agent": "^3.0.0", - "global-tunnel-ng": "^2.7.1", - "got": "^9.6.0", + "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "@electron/remote": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@electron/remote/-/remote-2.0.9.tgz", - "integrity": "sha512-LR0W0ID6WAKHaSs0x5LX9aiG+5pFBNAJL6eQAJfGkCuZPUa6nZz+czZLdlTDETG45CgF/0raSvCtYOYUpr6c+A==", - "requires": {} - }, - "@electron/universal": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", - "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", - "dev": true, - "requires": { - "@malept/cross-spawn-promise": "^1.1.0", - "asar": "^3.0.3", - "debug": "^4.3.1", - "dir-compare": "^2.4.0", - "fs-extra": "^9.0.1" - }, "dependencies": { "debug": { "version": "4.3.4", @@ -7416,25 +8546,23 @@ } }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.6" } }, "ms": { @@ -7444,13 +8572,24 @@ "dev": true }, "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true } } }, + "@es-joy/jsdoccomment": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.36.1.tgz", + "integrity": "sha512-922xqFsTpHs6D0BUiG4toiyPOMc8/jafnWKxz1KWgS4XzKPy2qXf1Pe6UFuNSCQqt6tOuhAWXBNuuyUhJmw9Vg==", + "dev": true, + "requires": { + "comment-parser": "1.3.1", + "esquery": "^1.4.0", + "jsdoc-type-pratt-parser": "~3.1.0" + } + }, "@esbuild-plugins/node-globals-polyfill": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", @@ -7482,6 +8621,86 @@ "dev": true, "optional": true }, + "@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "@jridgewell/gen-mapping": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", @@ -7555,39 +8774,11 @@ "ms": "2.1.2" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, @@ -7618,16 +8809,18 @@ } }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true }, "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, "requires": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" } }, "@tootallnate/once": { @@ -7660,6 +8853,18 @@ "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", "dev": true }, + "@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "@types/debug": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", @@ -7715,11 +8920,30 @@ "@types/node": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "peer": true + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/mime-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==" }, "@types/minimatch": { "version": "5.1.2", @@ -7755,6 +8979,15 @@ "xmlbuilder": ">=11.0.1" } }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", @@ -7786,11 +9019,208 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "dev": true, "optional": true, "requires": { "@types/node": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz", + "integrity": "sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/type-utils": "5.52.0", + "@typescript-eslint/utils": "5.52.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz", + "integrity": "sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz", + "integrity": "sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz", + "integrity": "sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.52.0", + "@typescript-eslint/utils": "5.52.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@typescript-eslint/types": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz", + "integrity": "sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz", + "integrity": "sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/visitor-keys": "5.52.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz", + "integrity": "sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.52.0", + "@typescript-eslint/types": "5.52.0", + "@typescript-eslint/typescript-estree": "5.52.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz", + "integrity": "sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.52.0", + "eslint-visitor-keys": "^3.3.0" + } + }, "@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -7979,144 +9409,35 @@ "peer": true, "requires": {} }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "acorn-walk": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", "dev": true }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "requires": { - "string-width": "^4.1.0" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "app-builder-bin": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", - "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", - "dev": true - }, - "app-builder-lib": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", - "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", - "dev": true, - "requires": { - "@develar/schema-utils": "~2.6.5", - "@electron/universal": "1.0.5", - "@malept/flatpak-bundler": "^0.4.0", - "7zip-bin": "~5.1.1", - "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chromium-pickle-js": "^0.2.0", - "debug": "^4.3.2", - "ejs": "^3.1.6", - "electron-osx-sign": "^0.5.0", - "electron-publish": "22.14.13", - "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "hosted-git-info": "^4.0.2", - "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.8", - "js-yaml": "^4.1.0", - "lazy-val": "^1.0.5", - "minimatch": "^3.0.4", - "read-config-file": "6.2.0", - "sanitize-filename": "^1.6.3", - "semver": "^7.3.5", - "temp-file": "^3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "ms": "2.1.2" } }, "ms": { @@ -8124,24 +9445,48 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -8154,6 +9499,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -8308,6 +9659,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, "optional": true }, "boxen": { @@ -8393,7 +9745,8 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true }, "buffer-equal": { "version": "1.0.0", @@ -8412,123 +9765,33 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "builder-util": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", - "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", - "dev": true, - "requires": { - "@types/debug": "^4.1.6", - "@types/fs-extra": "^9.0.11", - "7zip-bin": "~5.1.1", - "app-builder-bin": "3.7.1", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "cross-spawn": "^7.0.3", - "debug": "^4.3.2", - "fs-extra": "^10.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-ci": "^3.0.0", - "js-yaml": "^4.1.0", - "source-map-support": "^0.5.19", - "stat-mode": "^1.0.0", - "temp-file": "^3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "builder-util-runtime": { - "version": "8.9.2", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", - "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", - "dev": true, - "requires": { - "debug": "^4.3.2", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true }, "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - } + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, "camel-case": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", @@ -8566,6 +9829,11 @@ "supports-color": "^7.1.0" } }, + "char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==" + }, "chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", @@ -8629,6 +9897,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -8687,6 +9956,12 @@ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true }, + "comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true + }, "compare-version": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", @@ -8699,16 +9974,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "optional": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -8812,11 +10077,20 @@ } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } } }, "deep-extend": { @@ -8825,15 +10099,23 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, "optional": true, "requires": { "has-property-descriptors": "^1.0.0", @@ -8866,6 +10148,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, "optional": true }, "diff": { @@ -8889,77 +10172,42 @@ "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "dmg-builder": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", - "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", - "dev": true, - "requires": { - "app-builder-lib": "22.14.13", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "dmg-license": "^1.0.9", - "fs-extra": "^10.0.0", - "iconv-lite": "^0.6.2", - "js-yaml": "^4.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-readlink": ">= 1.0.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "dmg-license": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", @@ -8977,6 +10225,15 @@ "verror": "^1.10.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-walk": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", @@ -9016,7 +10273,8 @@ "duplexer3": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true }, "ecc-jsbn": { "version": "0.1.2", @@ -9043,11 +10301,12 @@ } }, "electron": { - "version": "21.3.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-21.3.0.tgz", - "integrity": "sha512-MGRpshN8fBcx4IRuBABIsGDv0tB/MclIFsyFHFFXsBCUc+vIXaE/E6vuWaniGIFSz5WyeuapfTH5IeRb+7yIfw==", + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-23.0.0.tgz", + "integrity": "sha512-S6hVtTAjauMiiWP9sBVR5RpcUC464cNZ06I2EMUjeZBq+KooS6tLmNsfw0zLpAXDp1qosjlBP3v71NTZ3gd9iA==", + "dev": true, "requires": { - "@electron/get": "^1.14.1", + "@electron/get": "^2.0.0", "@types/node": "^16.11.26", "extract-zip": "^2.0.1" }, @@ -9055,55 +10314,7 @@ "@types/node": { "version": "16.18.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" - } - } - }, - "electron-builder": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", - "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", - "dev": true, - "requires": { - "@types/yargs": "^17.0.1", - "app-builder-lib": "22.14.13", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "dmg-builder": "22.14.13", - "fs-extra": "^10.0.0", - "is-ci": "^3.0.0", - "lazy-val": "^1.0.5", - "read-config-file": "6.2.0", - "update-notifier": "^5.1.0", - "yargs": "^17.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", "dev": true } } @@ -9132,108 +10343,11 @@ "ms": "2.1.2" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "electron-osx-sign": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", - "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.0", - "compare-version": "^0.1.2", - "debug": "^2.6.8", - "isbinaryfile": "^3.0.2", - "minimist": "^1.2.0", - "plist": "^3.0.1" - }, - "dependencies": { - "isbinaryfile": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", - "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } - } - } - }, - "electron-publish": { - "version": "22.14.13", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", - "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", - "dev": true, - "requires": { - "@types/fs-extra": "^9.0.11", - "builder-util": "22.14.13", - "builder-util-runtime": "8.9.2", - "chalk": "^4.1.1", - "fs-extra": "^10.0.0", - "lazy-val": "^1.0.5", - "mime": "^2.5.2" - }, - "dependencies": { - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, @@ -9263,6 +10377,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "requires": { "once": "^1.4.0" } @@ -9279,10 +10394,11 @@ "enso": { "version": "file:lib/client", "requires": { - "@electron/remote": "^2.0.8", + "@types/mime-types": "^2.1.1", + "chalk": "^5.2.0", "create-servers": "^3.2.0", "crypto-js": "4.1.1", - "electron": "21.3.0", + "electron": "23.0.0", "electron-builder": "^22.14.13", "electron-is-dev": "^2.0.0", "electron-notarize": "1.2.2", @@ -9291,10 +10407,283 @@ "esbuild": "^0.15.14", "fast-glob": "^3.2.12", "mime-types": "^2.1.35", + "string-length": "^5.0.1", "ts-node": "^10.9.1", "yargs": "17.6.2" + }, + "dependencies": { + "@electron/universal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", + "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "app-builder-bin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", + "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", + "dev": true + }, + "app-builder-lib": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", + "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", + "dev": true, + "requires": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.0.5", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.2", + "ejs": "^3.1.6", + "electron-osx-sign": "^0.5.0", + "electron-publish": "22.14.13", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "hosted-git-info": "^4.0.2", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.8", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.0.4", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.5", + "temp-file": "^3.4.0" + } + }, + "builder-util": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", + "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", + "dev": true, + "requires": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "3.7.1", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "builder-util-runtime": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", + "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", + "dev": true, + "requires": { + "debug": "^4.3.2", + "sax": "^1.2.4" + } + }, + "chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dmg-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", + "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", + "dev": true, + "requires": { + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "dmg-license": "^1.0.9", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + } + }, + "electron-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", + "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", + "dev": true, + "requires": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "dmg-builder": "22.14.13", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "update-notifier": "^5.1.0", + "yargs": "^17.0.1" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "electron-osx-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", + "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "electron-publish": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", + "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", + "dev": true, + "requires": { + "@types/fs-extra": "^9.0.11", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + }, + "dependencies": { + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } } }, + "enso-content-config": { + "version": "file:lib/content-config" + }, "enso-copy-plugin": { "version": "file:lib/copy-plugin", "requires": { @@ -9318,6 +10707,9 @@ "@esbuild-plugins/node-modules-polyfill": "^0.1.4", "@types/mixpanel-browser": "^2.38.0", "@types/semver": "^7.3.9", + "@typescript-eslint/eslint-plugin": "^5.52.0", + "@typescript-eslint/parser": "^5.52.0", + "enso-content-config": "^1.0.0", "enso-copy-plugin": "^1.0.0", "enso-gui-server": "^1.0.0", "esbuild": "^0.15.14", @@ -9326,6 +10718,8 @@ "esbuild-plugin-alias": "^0.2.1", "esbuild-plugin-time": "^1.0.0", "esbuild-plugin-yaml": "^0.0.1", + "eslint": "^8.30.0", + "eslint-plugin-jsdoc": "^40.0.0", "glob": "^8.0.3", "html-loader": "^4.2.0", "mixpanel-browser": "2.45.0", @@ -9373,7 +10767,8 @@ "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true }, "errs": { "version": "0.3.2", @@ -9390,6 +10785,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, "optional": true }, "es6-promise": { @@ -9646,39 +11042,9 @@ "resolved": "https://registry.npmjs.org/esbuild-plugin-yaml/-/esbuild-plugin-yaml-0.0.1.tgz", "integrity": "sha512-s3jqOeeCd+dUuUsuBqLRgN2SeQjPF2ppIglvV3B//txgQpTDThGvxu6sqiOUOJ0NOzegitmpWCXoCONdRbUS7w==", "dev": true, - "requires": { - "fs-extra": "^9.1.0", - "js-yaml": "^4.0.0" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } + "requires": { + "fs-extra": "^9.1.0", + "js-yaml": "^4.0.0" } }, "esbuild-sunos-64": { @@ -9729,23 +11095,208 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "devOptional": true + "dev": true + }, + "eslint": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "eslint-plugin-jsdoc": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.0.0.tgz", + "integrity": "sha512-LOPyIu1vAVvGPkye3ci0moj0iNf3f8bmin6do2DYDj+77NRXWnkmhKRy8swWsatUs3mB5jYPWPUsFg9pyfEiyA==", + "dev": true, + "requires": { + "@es-joy/jsdoccomment": "~0.36.1", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.4.0", + "semver": "^7.3.8", + "spdx-expression-parse": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } }, "eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, "requires": { "estraverse": "^5.2.0" }, @@ -9753,16 +11304,14 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "peer": true + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" } } }, "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "estree-walker": { "version": "0.6.1", @@ -9770,6 +11319,12 @@ "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", "dev": true }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -9803,6 +11358,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, "requires": { "@types/yauzl": "^2.9.1", "debug": "^4.1.1", @@ -9814,6 +11370,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -9821,7 +11378,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -9854,6 +11412,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -9867,10 +11431,20 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, "requires": { "pend": "~1.2.0" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-type": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", @@ -9887,9 +11461,9 @@ }, "dependencies": { "minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -9920,6 +11494,16 @@ "unpipe": "~1.0.0" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", @@ -9929,6 +11513,33 @@ "micromatch": "^4.0.2" } }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -9958,13 +11569,15 @@ "dev": true }, "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, "fs.realpath": { @@ -9977,6 +11590,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true, "optional": true }, "get-caller-file": { @@ -9985,9 +11599,10 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, "optional": true, "requires": { "function-bind": "^1.1.1", @@ -9999,6 +11614,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, "requires": { "pump": "^3.0.0" } @@ -10061,6 +11677,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, "optional": true, "requires": { "boolean": "^3.0.1", @@ -10075,6 +11692,7 @@ "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, "optional": true, "requires": { "lru-cache": "^6.0.0" @@ -10099,55 +11717,74 @@ } } }, - "global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "optional": true, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, "requires": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } } }, "globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, "optional": true, "requires": { "define-properties": "^1.1.3" } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true } } }, + "got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -10159,6 +11796,12 @@ "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", "dev": true }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -10179,6 +11822,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "optional": true, "requires": { "function-bind": "^1.1.1" @@ -10193,6 +11837,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, "optional": true, "requires": { "get-intrinsic": "^1.1.1" @@ -10202,6 +11847,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "optional": true }, "has-yarn": { @@ -10250,9 +11896,10 @@ } }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true }, "http-errors": { "version": "2.0.0", @@ -10312,6 +11959,16 @@ "sshpk": "^1.7.0" } }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -10365,12 +12022,28 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, "image-size": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -10402,7 +12075,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "devOptional": true + "dev": true }, "ip-regex": { "version": "1.0.3", @@ -10635,6 +12308,12 @@ "integrity": "sha512-CiRVjMKBUp6VYtGwzRjrdnro41yMwKGOWdP9ATXqmixdz2n7KHNwdqthTYSSbOKj/Ha79Gct1sA8ZQpse55TYA==", "dev": true }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true + }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -10650,10 +12329,17 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "jsdoc-type-pratt-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.1.0.tgz", + "integrity": "sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==", + "dev": true + }, "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -10672,11 +12358,17 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "devOptional": true + "dev": true }, "json5": { "version": "2.2.3", @@ -10685,11 +12377,13 @@ "dev": true }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, "jsprim": { @@ -10718,11 +12412,12 @@ } }, "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "dev": true, "requires": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "klaw-sync": { @@ -10749,6 +12444,16 @@ "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", "dev": true }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "load-bmfont": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", @@ -10796,11 +12501,26 @@ "json5": "^2.1.2" } }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -10810,15 +12530,16 @@ } }, "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "devOptional": true, + "dev": true, "requires": { "yallist": "^4.0.0" } @@ -10851,6 +12572,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, "optional": true, "requires": { "escape-string-regexp": "^4.0.0" @@ -10900,7 +12622,8 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true }, "min-document": { "version": "2.19.0", @@ -10979,6 +12702,18 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -11034,19 +12769,10 @@ "peer": true }, "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, - "npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "optional": true, - "requires": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - } + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true }, "oauth-sign": { "version": "0.9.0", @@ -11063,6 +12789,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "optional": true }, "on-finished": { @@ -11082,6 +12809,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "requires": { "wrappy": "1" } @@ -11096,6 +12824,20 @@ "is-wsl": "^2.1.1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -11103,9 +12845,28 @@ "dev": true }, "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } }, "package-json": { "version": "6.5.0", @@ -11117,6 +12878,133 @@ "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + } + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + } + } + } } }, "param-case": { @@ -11128,6 +13016,15 @@ "tslib": "^2.0.3" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-bmfont-ascii": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", @@ -11228,18 +13125,6 @@ "which": "^1.2.9" } }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -11249,16 +13134,6 @@ "ci-info": "^2.0.0" } }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -11286,12 +13161,6 @@ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -11303,6 +13172,12 @@ } } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -11315,10 +13190,17 @@ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true }, "performance-now": { "version": "2.1.0", @@ -11344,12 +13226,6 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "optional": true - }, "pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -11443,10 +13319,17 @@ "tunnel-agent": "^0.6.0" } }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true }, "process": { "version": "0.11.10", @@ -11457,13 +13340,8 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "optional": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "psl": { "version": "1.9.0", @@ -11475,6 +13353,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -11506,6 +13385,12 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -11562,6 +13447,12 @@ "util-deprecate": "^1.0.1" } }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "registry-auth-token": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", @@ -11657,12 +13548,25 @@ } } }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "reusify": { @@ -11684,6 +13588,7 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, "optional": true, "requires": { "boolean": "^3.0.1", @@ -11772,12 +13677,14 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, "optional": true }, "semver-diff": { @@ -11838,6 +13745,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, "optional": true, "requires": { "type-fest": "^0.13.1" @@ -11937,23 +13845,6 @@ "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" - }, - "dependencies": { - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } } }, "simple-swizzle": { @@ -12027,10 +13918,33 @@ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "dev": true + }, "sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, "optional": true }, "sshpk": { @@ -12093,6 +14007,30 @@ } } }, + "string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "requires": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -12121,6 +14059,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, "requires": { "debug": "^4.1.0" }, @@ -12129,6 +14068,7 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -12136,7 +14076,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -12199,22 +14140,6 @@ "jsonfile": "^6.0.1", "universalify": "^2.0.0" } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, @@ -12249,6 +14174,12 @@ "terser": "^5.14.1" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "tinycolor2": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.5.2.tgz", @@ -12309,7 +14240,8 @@ "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true }, "to-regex-range": { "version": "5.0.1", @@ -12393,11 +14325,22 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "optional": true + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } }, "tunnel-agent": { "version": "0.6.0", @@ -12414,10 +14357,20 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, "optional": true }, "typedarray-to-buffer": { @@ -12445,9 +14398,10 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true }, "unpipe": { "version": "1.0.0", @@ -12524,6 +14478,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, "requires": { "prepend-http": "^2.0.0" } @@ -12644,6 +14599,12 @@ "string-width": "^4.0.0" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -12657,7 +14618,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "write-file-atomic": { "version": "3.0.3", @@ -12740,7 +14702,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "devOptional": true + "dev": true }, "yaml": { "version": "1.10.2", @@ -12790,6 +14752,7 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, "requires": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" @@ -12800,6 +14763,12 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/app/ide-desktop/package.json b/app/ide-desktop/package.json index 8e5587448866..f3304e9be681 100644 --- a/app/ide-desktop/package.json +++ b/app/ide-desktop/package.json @@ -18,6 +18,7 @@ "workspaces": [ "lib/client", "lib/content", + "lib/content-config", "lib/copy-plugin", "lib/icons", "lib/server" diff --git a/app/ide-desktop/tsconfig.json b/app/ide-desktop/tsconfig.json index 33b3ec413f17..20d4d7769197 100644 --- a/app/ide-desktop/tsconfig.json +++ b/app/ide-desktop/tsconfig.json @@ -1,13 +1,21 @@ { "compilerOptions": { - "sourceMap": true, - "noImplicitAny": true, - "target": "ES2019", - "module": "ESNext", + "allowSyntheticDefaultImports": true, "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "resolveJsonModule": true + "noImplicitOverride": true, + "noUncheckedIndexedAccess": true, + "noImplicitAny": true, + "removeComments": true, + "resolveJsonModule": true, + "sourceMap": true, + "skipLibCheck": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "target": "ES2019" }, "ts-node": { "esm": true diff --git a/build/build/paths.yaml b/build/build/paths.yaml index 300bb85ff3f8..339596d09085 100644 --- a/build/build/paths.yaml +++ b/build/build/paths.yaml @@ -52,12 +52,14 @@ pkg-opt.wasm: # The optimized WASM artifact. index.js: style.css: + ensogl-app/: # Final WASM artifacts in `dist` directory. wasm/: shaders/: # Optimized shaders that contain main function code only. - index.cjs: # The main JS bundle to load WASM and JS wasm-pack bundles. + index.js: # The main JS bundle to load WASM and JS wasm-pack bundles. index.d.ts: # TypeScript types interface file. + index.js.map: # The sourcemap mapping to `index.js`. pkg.js: # The `pks.js` artifact of wasm-pack WITH bundled snippets. pkg.wasm: # The `pks_bg.wasm` artifact of wasm-pack. pkg-opt.wasm: # The optimized `pks_bg.wasm`. @@ -81,6 +83,9 @@ generate-java/: java/: target/: + ensogl-pack/: + dist/: # Here ensogl-pack outputs its artifacts + linked-dist/: # Either symlink to dist or to the gui artifacts. generated-java/: parser-upload/: test-results/: diff --git a/build/build/src/ide/web.rs b/build/build/src/ide/web.rs index 3114f60dd1c2..7d68ac945a64 100644 --- a/build/build/src/ide/web.rs +++ b/build/build/src/ide/web.rs @@ -6,6 +6,7 @@ use crate::project::gui::BuildInfo; use crate::project::wasm; use crate::project::ProcessWrapper; +use crate::paths::generated::RepoRootTargetEnsoglPackLinkedDist; use anyhow::Context; use futures_util::future::try_join; use futures_util::future::try_join4; @@ -141,9 +142,9 @@ pub enum Command { /// Things that are common to `watch` and `build`. #[derive(Debug)] pub struct ContentEnvironment { - asset_dir: Assets, - wasm: wasm::Artifact, - output_path: Output, + pub asset_dir: Assets, + pub wasm: wasm::Artifact, + pub output_path: Output, } impl> ContentEnvironment { @@ -160,6 +161,7 @@ impl> ContentEnvironment { google_font::download_google_font(&ide.cache, &ide.octocrab, "mplus1", &asset_dir); let (wasm, _, _, _) = try_join4(wasm, installation, assets_download, fonts_download).await?; + wasm.symlink_ensogl_dist(&ide.linked_dist)?; ide.write_build_info(build_info)?; Ok(ContentEnvironment { asset_dir, wasm, output_path }) } @@ -204,6 +206,7 @@ pub struct IdeDesktop { #[derivative(Debug = "ignore")] pub octocrab: Octocrab, pub cache: ide_ci::cache::Cache, + pub linked_dist: RepoRootTargetEnsoglPackLinkedDist, } impl IdeDesktop { @@ -217,6 +220,7 @@ impl IdeDesktop { package_dir: repo_root.app.ide_desktop.clone(), octocrab, cache, + linked_dist: repo_root.target.ensogl_pack.linked_dist.clone(), } } @@ -254,14 +258,26 @@ impl IdeDesktop { dest = %output_path.as_ref().display(), build_info, err))] - pub async fn build_content( + pub async fn build_content>( &self, wasm: impl Future>, build_info: &BuildInfo, - output_path: impl AsRef, - ) -> Result { + output_path: P, + ) -> Result> { let env = ContentEnvironment::new(self, wasm, build_info, output_path).await?; //env.apply(); + self.npm()? + .try_applying(&env)? + .workspace(Workspaces::Content) + .run("lint", EMPTY_ARGS) + .run_ok() + .await?; + self.npm()? + .try_applying(&env)? + .workspace(Workspaces::Content) + .run("typecheck", EMPTY_ARGS) + .run_ok() + .await?; self.npm()? .try_applying(&env)? .workspace(Workspaces::Content) @@ -269,9 +285,7 @@ impl IdeDesktop { .run_ok() .await?; - debug!(assets=?env.asset_dir, "Still kept"); - drop(env); // does this extend the lifetime? - Ok(()) + Ok(env) } diff --git a/build/build/src/project/gui.rs b/build/build/src/project/gui.rs index f8ab92f18a4a..9bf341e539c4 100644 --- a/build/build/src/project/gui.rs +++ b/build/build/src/project/gui.rs @@ -15,12 +15,13 @@ use crate::source::WatchTargetJob; use crate::source::WithDestination; use crate::BoxFuture; +use crate::paths::generated::RepoRootTargetEnsoglPackLinkedDist; use derivative::Derivative; use futures_util::future::try_join; +use ide_ci::fs::tokio::create_dir_if_missing; use ide_ci::ok_ready_boxed; - #[derive(Clone, Debug, PartialEq, Eq, Hash, Deref)] pub struct Artifact(crate::paths::generated::RepoRootDistGui); @@ -37,6 +38,11 @@ impl Artifact { // TODO: sanity check Self(crate::paths::generated::RepoRootDistGui::new_root(gui_path.as_ref())) } + + pub fn symlink_ensogl_dist(&self, linked_dist: &RepoRootTargetEnsoglPackLinkedDist) -> Result { + ide_ci::fs::remove_symlink_dir_if_exists(linked_dist)?; + ide_ci::fs::symlink_auto(&self.ensogl_app, linked_dist) + } } #[derive(Clone, Derivative, derive_more::Deref)] @@ -83,8 +89,21 @@ impl IsTarget for Gui { async move { let ide = ide_desktop_from_context(&context); let wasm = Wasm.get(context, inner.wasm); - ide.build_content(wasm, &inner.build_info.await?, &destination).await?; - Ok(Artifact::new(destination)) + let content_env = + ide.build_content(wasm, &inner.build_info.await?, &destination).await?; + + let ret = Artifact::new(destination.clone()); + let ensogl_app_dir = &ret.0.ensogl_app; + create_dir_if_missing(ensogl_app_dir).await?; + let ensogl_app_files = [ + &content_env.wasm.0.index_js.path, + &content_env.wasm.0.index_d_ts.path, + &content_env.wasm.0.index_js_map.path, + ]; + for file in ensogl_app_files { + ide_ci::fs::copy_to(file, ensogl_app_dir)?; + } + Ok(ret) } .boxed() } diff --git a/build/build/src/project/ide.rs b/build/build/src/project/ide.rs index 609644c33b49..db2b3f05fc1e 100644 --- a/build/build/src/project/ide.rs +++ b/build/build/src/project/ide.rs @@ -124,11 +124,13 @@ impl Ide { output_path: impl AsRef + Send + Sync + 'static, ) -> BoxFuture<'static, Result> { let BuildInput { version, project_manager, gui, electron_target } = input; + let linked_dist = context.repo_root.target.ensogl_pack.linked_dist.clone(); let ide_desktop = ide_desktop_from_context(context); let target_os = self.target_os; let target_arch = self.target_arch; async move { let (gui, project_manager) = try_join!(gui, project_manager)?; + gui.symlink_ensogl_dist(&linked_dist)?; ide_desktop .dist(&gui, &project_manager, &output_path, target_os, electron_target) .await?; @@ -138,6 +140,7 @@ impl Ide { } } + // impl IsTarget for Ide { // type BuildInput = BuildInput; // type Output = Artifact; diff --git a/build/build/src/project/wasm.rs b/build/build/src/project/wasm.rs index 827fedcf897d..bcbbb4b7a3c7 100644 --- a/build/build/src/project/wasm.rs +++ b/build/build/src/project/wasm.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::paths::generated::RepoRootDistWasm; +use crate::paths::generated::RepoRootTargetEnsoglPackLinkedDist; use crate::project::Context; use crate::project::IsArtifact; use crate::project::IsTarget; @@ -407,7 +408,7 @@ impl IsWatchable for Wasm { #[derive(Clone, Debug, Display, PartialEq, Eq)] -pub struct Artifact(RepoRootDistWasm); +pub struct Artifact(pub RepoRootDistWasm); impl Artifact { pub fn new(path: impl Into) -> Self { @@ -416,7 +417,7 @@ impl Artifact { /// The main JS bundle to load WASM and JS wasm-pack bundles. pub fn ensogl_app(&self) -> &Path { - &self.0.index_cjs + &self.0.index_js } /// Files that should be shipped in the Gui bundle. @@ -426,14 +427,20 @@ impl Artifact { let RepoRootDistWasm { path: _, shaders, - index_cjs: _, + index_js: _, index_d_ts: _, + index_js_map: _, pkg_js, pkg_wasm: _, pkg_opt_wasm, } = &self.0; vec![shaders.as_path(), pkg_js.as_path(), pkg_opt_wasm.as_path()] } + + pub fn symlink_ensogl_dist(&self, linked_dist: &RepoRootTargetEnsoglPackLinkedDist) -> Result { + ide_ci::fs::remove_symlink_dir_if_exists(linked_dist)?; + ide_ci::fs::symlink_auto(self, linked_dist) + } } impl AsRef for Artifact { diff --git a/build/ci_utils/src/fs.rs b/build/ci_utils/src/fs.rs index 720205364363..8b743e8867fa 100644 --- a/build/ci_utils/src/fs.rs +++ b/build/ci_utils/src/fs.rs @@ -119,9 +119,20 @@ pub async fn copy_if_different(source: impl AsRef, target: impl AsRef {}", src.as_ref().display(), dst.as_ref().display())] pub fn symlink_auto(src: impl AsRef, dst: impl AsRef) -> Result { create_parent_dir_if_missing(&dst)?; + debug!("Creating symlink {} <= {}", src.as_ref().display(), dst.as_ref().display()); symlink::symlink_auto(&src, &dst).anyhow_err() } +/// Remove a symlink if it exists. +#[context("Failed to remove symlink {}", path.as_ref().display())] +pub fn remove_symlink_dir_if_exists(path: impl AsRef) -> Result { + let result = symlink::remove_symlink_dir(&path); + match result { + Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(()), + ret => ret.anyhow_err(), + } +} + /// `fs_extra`'s error type is not friendly to `anyhow`, so we need to convert it manually. /// /// Otherwise, we get just the message to look into the error kind, but the kind information is diff --git a/lib/rust/ensogl/core/src/application.rs b/lib/rust/ensogl/core/src/application.rs index 46c5a354c52f..bf3adfb4f288 100644 --- a/lib/rust/ensogl/core/src/application.rs +++ b/lib/rust/ensogl/core/src/application.rs @@ -15,7 +15,6 @@ use crate::system::web; // === Export === // ============== -pub mod args; pub mod command; pub mod frp; pub mod shortcut; diff --git a/lib/rust/ensogl/core/src/application/args.rs b/lib/rust/ensogl/core/src/application/args.rs deleted file mode 100644 index b774305c5c94..000000000000 --- a/lib/rust/ensogl/core/src/application/args.rs +++ /dev/null @@ -1,265 +0,0 @@ -//! Implementation of application argument reader capable of reading arguments passed by a WASM -//! variable. - -use crate::prelude::*; - - - -// ============================= -// === Ident Case Conversion === -// ============================= - -/// Convert snake to camel case name. -pub fn snake_case_to_camel_case(name: &str) -> String { - let mut output = String::new(); - let mut capitalize_next = false; - for c in name.chars() { - if c == '_' { - capitalize_next = true; - } else if capitalize_next { - output.push(c.to_ascii_uppercase()); - capitalize_next = false; - } else { - output.push(c); - } - } - output -} - - - -// ==================== -// === OptArgReader === -// ==================== - -auto trait NotOption {} -impl !NotOption for Option {} - -/// Argument parser that checks if the desired parameter is of an [`Option`] type. If it is not, -/// the call is redirected to [`ArgReader`]. -#[allow(missing_docs)] -pub trait OptArgReader: Sized { - fn read_arg(input: &Option) -> Result; -} - -impl OptArgReader for Option { - fn read_arg(input: &Option) -> Result { - match input.as_ref() { - None => Ok(None), - Some(str) => ArgReader::read_arg(str.as_ref()).map(Some), - } - } -} - -impl OptArgReader for T { - fn read_arg(input: &Option) -> Result { - match input.as_ref() { - None => Err(anyhow!("Missing required argument.")), - Some(str) => ArgReader::read_arg(str.as_ref()), - } - } -} - - - -// ================= -// === ArgReader === -// ================= - -/// Marker trait used to disambiguate overlapping impls of [`ArgReader`]. -#[marker] -pub trait ArgMarker {} - -/// Trait used to convert provided string arguments to the desired type. -#[allow(missing_docs)] -pub trait ArgReader: Sized { - fn read_arg(str: &str) -> Result; -} - -// === Default === - -/// Helper trait used to disambiguate overlapping impls of [`ArgReader`]. -#[allow(missing_docs)] -pub trait ArgReaderFromString: Sized { - fn read_arg_from_string(str: &str) -> Result; -} - -impl ArgReaderFromString for T -where for<'t> &'t str: TryInto -{ - fn read_arg_from_string(input: &str) -> Result { - input.try_into().map_err(|_| anyhow!("Cannot convert '{input}' to argument value.")) - } -} - -impl ArgReaderFromString for T { - default fn read_arg_from_string(input: &str) -> Result { - Err(anyhow!("Cannot convert '{input}' to argument value.")) - } -} - -impl ArgMarker for T where T: for<'t> TryFrom<&'t str> {} -impl ArgReader for T -where T: ArgMarker -{ - default fn read_arg(str: &str) -> Result { - ArgReaderFromString::read_arg_from_string(str) - } -} - - -// === Specializations === - -impl ArgMarker for bool {} -impl ArgReader for bool { - fn read_arg(input: &str) -> Result { - let true_values = ["true", "enabled", "yes", "1"]; - let false_values = ["false", "disabled", "no", "0"]; - if true_values.contains(&input) { - Ok(true) - } else if false_values.contains(&input) { - Ok(false) - } else { - let allowed_values = true_values.iter().chain(false_values.iter()).join(", "); - Err(anyhow!("Cannot parse '{input}' as bool. Allowed values: {allowed_values}.")) - } - } -} - -impl ArgMarker for f32 {} -impl ArgReader for f32 { - fn read_arg(input: &str) -> Result { - input.parse().map_err(|_| anyhow!("Cannot parse '{input}' as f32.")) - } -} - -impl ArgMarker for semver::Version {} -impl ArgReader for semver::Version { - fn read_arg(input: &str) -> Result { - semver::Version::parse(input).map_err(|_| anyhow!("Cannot parse '{input}' as semver.")) - } -} - - - -// ================= -// === read_args === -// ================= - -/// Defines an application argument reader. As a result, a new lazy-initialized static variable -/// `ARGS` will be created, and it will read the arguments on its first access (in case you want to -/// force argument read, use the `init` function). -/// -/// For example, given the following definition: -/// ```text -/// read_args! { -/// entry: String, -/// project: String, -/// dark_theme: bool, -/// } -/// ``` -/// -/// The following structs will be generated (some functions omitted for clarity): -/// -/// ```text -/// #[derive(Clone, Debug, Default)] -/// pub struct Args { -/// pub entry: Option, -/// pub project: Option, -/// pub dark_theme: Option, -/// } -/// -/// lazy_static! { -/// pub static ref ARGS: Args = Args::new(); -/// } -/// ``` -/// -/// The header `js::global.config` means that the JavaScript space will be queried for variable -/// `global.config`, which will be queried for every field of the generated structure. In case the -/// JavaScript variable will not contain the key, it will be left as None. For each available key, -/// the [`ArgReader`] trait will be used to read it back to Rust types. The [`ArgReader`] is a thin -/// wrapper over the [`Into`] trait with some additional conversions (e.g. for [`bool`]). In case -/// the conversion will fail, a warning will be raised. -#[macro_export] -macro_rules! read_args { - ($($(#[$($attr:tt)+])* $field:ident : $field_type:ty),* $(,)?) => { - mod _READ_ARGS { - use super::*; - use $crate::prelude::*; - use $crate::system::web::traits::*; - - /// Reflection mechanism containing string representation of option names. - #[derive(Clone,Copy,Debug,Default)] - pub struct ArgNames; - impl ArgNames { - $( - /// Name of the field. - pub fn $field(&self) -> String { - $crate::application::args::snake_case_to_camel_case(stringify!{$field}) - } - )* - } - - /// The structure containing application configs. - #[derive(Clone,Debug,Default)] - #[allow(missing_docs)] - pub struct Args { - $( - $(#[$($attr)*])* - pub $field : $field_type - ),* - } - - impl Args { - /// Constructor. - fn new() -> Self { - let js_app = ensogl::system::js::app::app(); - match js_app { - Err(_) => { - error!("Cannot get the JS application. Using default arguments."); - default() - } - Ok(js_app) => { - let mut params = js_app.config().params().to_hash_map(); - $( - let js_name = $crate::application::args::snake_case_to_camel_case - (stringify!{$field}); - let $field = if let Some(param) = params.remove(&js_name) { - let str_value = param.value(); - let value = $crate::application::args::OptArgReader::read_arg(&str_value); - match value { - Err(err) => { - let tp = stringify!{$field_type}; - error!("Config error. Invalid value '{str_value:?}' for parameter \ - '{js_name}' of type '${tp}'. {err}"); - default() - } - Ok(value) => value, - } - } else { - warn!("Config error. Rust config parameter '{js_name}' not found in \ - JavaScript."); - default() - }; - )* - for js_name in params.keys() { - warn!("Config error. JavaScript config parameter '{js_name}' not found in \ - Rust."); - } - Self {$($field),*} - } - } - } - - /// Reflection mechanism to get string representation of argument names. - pub fn names(&self) -> ArgNames { ArgNames } - } - - lazy_static! { - /// Application arguments initialized in a lazy way (on first read). - pub static ref ARGS : Args = Args::new(); - } - } - pub use _READ_ARGS::*; - }; -} diff --git a/lib/rust/ensogl/core/src/system/js/app.rs b/lib/rust/ensogl/core/src/system/js/app.rs index 62d231ee08f1..16a2a5548978 100644 --- a/lib/rust/ensogl/core/src/system/js/app.rs +++ b/lib/rust/ensogl/core/src/system/js/app.rs @@ -22,7 +22,6 @@ pub mod js_bindings { extern "C" { pub type App; pub type Config; - pub type Params; pub type Param; /// Register in JS a closure to get non-precompiled shaders from Rust. @@ -46,7 +45,6 @@ pub mod js_bindings { mock_data! { App => JsValue } mock_data! { Config => JsValue } - mock_data! { Params => JsValue } mock_data! { Param => JsValue } impl App { @@ -70,30 +68,32 @@ impl App { } impl Config { - pub fn params(&self) -> Params { - Reflect::get(self, &"params".into()).unwrap().unchecked_into() + pub fn params(&self) -> Vec { + let opts_fn = + Reflect::get(self, &"optionsRecursive".into()).unwrap().unchecked_into::(); + let js_arr = opts_fn.call0(self).unwrap().unchecked_into::(); + js_arr.to_vec().into_iter().map(|t| t.unchecked_into::()).collect() } } -impl Params { - pub fn get(&self, name: &str) -> Result { - Reflect::get(self, &name.into()).map(|t| t.unchecked_into()) +impl Param { + pub fn name(&self) -> String { + let val = Reflect::get(self, &"name".into()).unwrap(); + val.print_to_string() } - pub fn to_vec(&self) -> Vec { - let obj = (*self).clone().unchecked_into::(); - let keys = Object::keys_vec(&obj); - keys.iter().map(|key| self.get(key).unwrap()).collect() + pub fn qualified_name(&self) -> String { + let js_field = Reflect::get(self, &"qualifiedName".into()).unwrap(); + let js_fn = js_field.unchecked_into::(); + js_fn.call0(self).unwrap().print_to_string() } - pub fn to_hash_map(&self) -> HashMap { - let obj = (*self).clone().unchecked_into::(); - let keys = Object::keys_vec(&obj); - keys.iter().map(|key| (key.clone(), self.get(key).unwrap())).collect() + pub fn structural_name(&self) -> String { + let js_field = Reflect::get(self, &"structuralName".into()).unwrap(); + let js_fn = js_field.unchecked_into::(); + js_fn.call0(self).unwrap().print_to_string() } -} -impl Param { pub fn value(&self) -> Option { let val = Reflect::get(self, &"value".into()).unwrap(); if val.is_null() || val.is_undefined() { diff --git a/lib/rust/ensogl/example/auto-layout/src/lib.rs b/lib/rust/ensogl/example/auto-layout/src/lib.rs index d1fe29d1dfda..4b3e0c55b1ca 100644 --- a/lib/rust/ensogl/example/auto-layout/src/lib.rs +++ b/lib/rust/ensogl/example/auto-layout/src/lib.rs @@ -86,5 +86,4 @@ pub fn main() { mem::forget(root); mem::forget(rect1); mem::forget(rect2); - warn!("Hello World!"); } diff --git a/lib/rust/ensogl/pack/js/src/runner/config.json b/lib/rust/ensogl/pack/js/src/runner/config.json new file mode 100644 index 000000000000..f5ade9f8eefd --- /dev/null +++ b/lib/rust/ensogl/pack/js/src/runner/config.json @@ -0,0 +1,65 @@ +{ + "options": { + "debug": { + "value": false, + "description": "Controls the debug mode for the application. In this mode, all logs are printed to the console, and EnsoGL extensions are loaded. Otherwise, logs are hidden unless explicitly shown with 'showLogs'." + } + }, + "groups": { + "loader": { + "description": "Options for the application loader, which downloads assets, compiles WASM code, and runs entry points.", + "options": { + "spinner": { + "value": true, + "description": "Controls the visibility of the visual loader while downloading and compiling WASM sources.", + "primary": false + }, + "wasmUrl": { + "value": "pkg.wasm", + "description": "The URL of the WASM pkg file generated by ensogl-pack.", + "primary": false + }, + "jsUrl": { + "value": "pkg.js", + "description": "The URL of the JS pkg file generated by ensogl-pack.", + "primary": false + }, + "shadersUrl": { + "value": "shaders", + "description": "The URL of pre-compiled the shaders directory.", + "primary": false + }, + "downloadToInitRatio": { + "value": 1.0, + "description": "The ratio of time needed for WASM download to the total time, including WASM app initialization. For small WASM apps, this can be set to 1.0. For larger apps, it is desirable to show the progress bar up to 70% and leave the last 30% for WASM app init.", + "primary": false + } + } + }, + "startup": { + "description": "Options for controlling the application behavior at startup, such as selecting the entry point to run.", + "options": { + "entry": { + "value": "ide", + "description": "The application entry point. Most entry points are debug utilities for testing graphical interface components. Use '_' to list available entry points." + }, + "maxBeforeMainTimeMs": { + "value": 300, + "description": "The maximum time in milliseconds before the main entry points are allowed to run. After this time, an error will be printed, but execution will continue.", + "primary": false + } + } + }, + + "debug": { + "description": "Options allowing checking for diagnosing application errors.", + "options": { + "enableSpector": { + "value": false, + "description": "Enables SpectorJS. This is a temporary flag to test Spector. It will be removed after all Spector integration issues are resolved. See: https://github.com/BabylonJS/Spector.js/issues/252.", + "primary": false + } + } + } + } +} diff --git a/lib/rust/ensogl/pack/js/src/runner/config.ts b/lib/rust/ensogl/pack/js/src/runner/config.ts index 76b6a11c30dc..fa0cd66cebb4 100644 --- a/lib/rust/ensogl/pack/js/src/runner/config.ts +++ b/lib/rust/ensogl/pack/js/src/runner/config.ts @@ -1,6 +1,7 @@ /** @file Configuration options for the application. */ import { logger } from 'runner/log' +import * as jsonCfg from './config.json' export const DEFAULT_ENTRY_POINT = 'ide' @@ -28,189 +29,387 @@ function parseBoolean(value: any): boolean | null { } } -// ============= -// === Param === -// ============= +// ============== +// === Option === +// ============== -/** A valid parameter value. */ -export type ParamValue = string | boolean | number | (string | null) +/** A valid configuration option value. */ +export type OptionValue = string | boolean | number | string[] -/** Configuration parameter. */ -export class Param { +/** A valid configuration option type. */ +export type OptionType = 'string' | 'boolean' | 'number' | 'array' + +/** Non-generic version of `Option`. */ +export type AnyOption = Option + +/** Plain object version of `Option`. Used mainly when loading options from a JSON file. */ +export interface OptionObject { + value: T + valueEval?: string + description: string + defaultDescription?: string + hidden?: boolean + primary?: boolean + passToWebApplication?: boolean +} + +/** Non-generic version of `OptionObject`. */ +export type AnyOptionObject = OptionObject + +/** Configuration option. */ +export class Option { + name = 'unnamed' + path: string[] = [] default: T value: T + type: OptionType description: string + /** The description of the default argument that should be shown to the user. For example, + * it can be set to `'true' on macOS and 'false' otherwise` to better explain mechanics for the + * default value. */ + defaultDescription: null | string = null + /** If set to false, the option will not be passed to the web application. This is useful when + * creating meta configuration options, that control some behavior, like the window style, but + * are not designed to control the web app behavior. */ + passToWebApplication = true setByUser = false - constructor(value: T, description: string) { - this.default = value - this.value = value - this.description = description + hidden: boolean + /** Controls whether this option should be visible by default in the help message. Non-primary + * options will be displayed on-demand only. */ + primary = true + constructor(cfg: OptionObject) { + this.default = cfg.value + this.value = cfg.value + this.description = cfg.description + this.defaultDescription = cfg.defaultDescription ?? null + this.hidden = cfg.hidden ?? false + this.primary = cfg.primary ?? true + this.passToWebApplication = cfg.passToWebApplication ?? true + if (typeof this.value === 'boolean') { + this.type = 'boolean' + } else if (typeof this.value === 'number') { + this.type = 'number' + } else if (Array.isArray(this.value)) { + this.type = 'array' + } else { + this.type = 'string' + } + } + + /** Names of all parent groups and name of this option intercalated with dots. */ + qualifiedName(): string { + return this.path.concat([this.name]).join('.') + } + + /** Just like `qualifiedName`, but also contains names of 'groups' and 'options' fields. */ + structuralName(): string { + const lastSegment = 'options.' + this.name + if (this.path.length === 0) { + return lastSegment + } else { + return 'groups.' + this.path.join('.groups.') + '.' + lastSegment + } + } + + load(input: string) { + if (typeof this.value === 'boolean') { + const newVal = parseBoolean(input) + if (newVal == null) { + this.printValueUpdateError(input) + } else { + this.value = newVal as T + this.setByUser = true + } + } else if (typeof this.value == 'number') { + const newVal = Number(input) + if (isNaN(newVal)) { + this.printValueUpdateError(input) + } else { + this.value = newVal as T + this.setByUser = true + } + } else { + this.value = String(input) as T + this.setByUser = true + } + } + + printValueUpdateError(input: string) { + logger.error( + `The provided value for '${this.qualifiedName()}' is invalid. Expected ${this.type}, ` + + `got '${input}'. Using the default value '${String(this.default)}' instead.` + ) } } -// ============== -// === Params === -// ============== +// ============= +// === Group === +// ============= -export type ExternalConfig = Record - -/** Application default configuration. Users of this library can extend it with their own - * options. */ -export class Params { - [key: string]: Param - - pkgWasmUrl = new Param( - 'pkg.wasm', - 'The URL of the WASM pkg file generated by ensogl-pack.' - ) - pkgJsUrl = new Param('pkg.js', 'The URL of the JS pkg file generated by ensogl-pack.') - shadersUrl = new Param('shaders', 'The URL of the pre-compiled shaders directory.') - entry = new Param( - DEFAULT_ENTRY_POINT, - 'The application entry point. Use `entry=_` to list available entry points.' - ) - theme = new Param('default', 'The EnsoGL theme to be used.') - useLoader = new Param( - true, - 'Controls whether the visual loader should be visible on the screen when downloading and ' + - 'compiling WASM sources. By default, the loader is used only if the `entry` is set ' + - `to ${DEFAULT_ENTRY_POINT}.` - ) - loaderDownloadToInitRatio = new Param( - 1.0, - 'The (time needed for WASM download) / (total time including WASM download and WASM app ' + - 'initialization). In case of small WASM apps, this can be set to 1.0. In case of ' + - 'bigger WASM apps, it is desired to show the progress bar growing up to e.g. 70% and ' + - 'leaving the last 30% for WASM app init.' - ) - debug = new Param( - false, - 'Controls whether the application should be run in the debug mode. In this mode all logs ' + - 'are printed to the console. Otherwise, the logs are hidden unless explicitly shown ' + - 'by calling `showLogs`. Moreover, EnsoGL extensions are loaded in the debug mode ' + - 'which may cause additional logs to be printed.' - ) - maxBeforeMainEntryPointsTimeMs = new Param( - 300, - 'The maximum time in milliseconds a before main entry point is allowed to run. After ' + - 'this time, an error will be printed, but the execution will continue.' - ) - enableSpector = new Param( - false, - 'Enables SpectorJS. This is a temporary flag to test Spector. It will be removed after ' + - 'all Spector integration issues are resolved. See: ' + - 'https://github.com/BabylonJS/Spector.js/issues/252.' - ) +export interface StringConfig { + [key: string]: string | StringConfig } -// ============== -// === Config === -// ============== +/** Record containing options. */ +type OptionsRecord = Record -/** The configuration of the EnsoGL application. The options can be overriden by the user. The - * implementation automatically casts the values to the correct types. For example, if an option - * override for type boolean was provided as `'true'`, it will be parsed automatically. Moreover, - * it is possible to extend the provided option list with custom options. See the `extend` method - * to learn more. */ -export class Config { - params = new Params() +/** Record containing option groups. */ +type GroupsRecord = Record + +/** Plain object representation of `Group`. Used mainly to load groups from JSON files. */ +export interface GroupObject { + description?: string + options?: Record + groups?: Record +} + +/** Options group. The same as `Group` but with elided generic parameters. */ +export interface AnyGroup { + name: string + description: string + options: OptionsRecord + groups: GroupsRecord + setPath(path: string[]): void + merge(other: Other): this & Other + load(config: StringConfig, stack?: string[]): string[] + stringify(): StringConfig + prettyPrint(indent: number): string + optionsRecursive(): AnyOption[] +} - constructor(config?: ExternalConfig) { - this.extend(config) +/** Options group. Allows defining nested options. The class is generic in order to allow TypeScript + * to infer the types of its children and thus allow accessing them in a type-safe way. */ +export class Group { + name = 'unnamed' + description: string + options: Options = {} as Options + groups: Groups = {} as Groups + constructor(cfg?: { description?: string; options?: Options; groups?: Groups }) { + this.description = cfg?.description ?? 'No description.' + const options = cfg?.options + if (options != null) { + for (const [name, option] of Object.entries(options)) { + this.addOption(name, option) + } + } + const groups = cfg?.groups + if (groups != null) { + for (const [name, group] of Object.entries(groups)) { + this.addGroup(name, group) + } + } } - /** Extend the configuration with user provided options. */ - extend(config?: ExternalConfig) { - if (config != null) { - Object.assign(this.params, config) + addOption(name: string, option: AnyOption) { + const existingOption = this.options[name] + if (existingOption != null) { + logger.error(`Duplicate config option found '${existingOption.qualifiedName()}'.`) } + const options = this.options as OptionsRecord + options[name] = option + option.name = name } - /** Resolve the configuration from the provided record list. - * @returns list of unrecognized parameters. */ - resolve(overrides: (Record | undefined)[]): null | string[] { - const allOverrides = {} - for (const override of overrides) { - if (override != null) { - Object.assign(allOverrides, override) + addGroup(name: string, group: AnyGroup) { + const existingGroup = this.groups[name] + if (existingGroup != null) { + existingGroup.merge(group) + } else { + const groups = this.groups as GroupsRecord + groups[name] = group + group.name = name + } + group.setPath([name]) + } + + /** Set the path of this group. If this group was placed in another group, the path will contain + * all the parent group names. */ + setPath(path: string[]) { + for (const option of Object.values(this.options)) { + option.path = path + } + for (const [name, group] of Object.entries(this.groups)) { + group.setPath(path.concat([name])) + } + } + + /** Merge this group definition with another group definition. Returns a deeply merged group. In + * case the argument will override some options, errors will be logged. */ + merge(other?: Other | null): this & Other { + if (other == null) { + return this as this & Other + } else { + const result: AnyGroup = new Group() + Object.assign(result.groups, this.groups) + for (const [otherGroupName, otherGroup] of Object.entries(other.groups)) { + const group = result.groups[otherGroupName] + if (group == null) { + result.groups[otherGroupName] = otherGroup + } else { + result.groups[otherGroupName] = group.merge(otherGroup) + } } + Object.assign(result.options, this.options) + for (const [otherOptionName, otherOption] of Object.entries(other.options)) { + const option = result.options[otherOptionName] + if (option != null) { + logger.error(`Duplicate config option found '${option.qualifiedName()}'.`) + } + result.options[otherOptionName] = otherOption + } + result.name = this.name + result.description = this.description + return result as this & Other } - const unrecognizedParams = this.resolveFromObject(allOverrides) - this.finalize() - return unrecognizedParams - } - - /** Resolve the configuration from the provided record. - * @returns list of unrecognized parameters. */ - resolveFromObject(other: Record): null | string[] { - const paramsToBeAssigned = new Set(Object.keys(other)) - const invalidParams = new Set() - for (const key of Object.keys(this.params)) { - paramsToBeAssigned.delete(key) - const otherVal: unknown = other[key] - const param = this.params[key] - if (param == null) { - invalidParams.add(key) + } + + load(config: StringConfig, stack: string[] = []): string[] { + let unrecognized: string[] = [] + const addUnrecognized = (name: string) => { + unrecognized.push(stack.concat([name]).join('.')) + } + for (const [key, value] of Object.entries(config)) { + if (typeof value === 'string') { + const option = this.options[key] + if (option == null) { + addUnrecognized(key) + } else { + option.load(value) + } } else { - const selfVal = param.value - if (otherVal != null) { - if (typeof selfVal === 'boolean') { - const newVal = parseBoolean(otherVal) - if (newVal == null) { - this.printValueUpdateError(key, selfVal, otherVal) - } else { - param.value = newVal - param.setByUser = true - } - } else if (typeof selfVal == 'number') { - const newVal = Number(otherVal) - if (isNaN(newVal)) { - this.printValueUpdateError(key, selfVal, otherVal) - } else { - param.value = newVal - param.setByUser = true - } - } else { - param.value = String(otherVal) - param.setByUser = true - } + const group = this.groups[key] + if (group == null) { + addUnrecognized(key) + } else { + const subStack = stack.concat([key]) + unrecognized = unrecognized.concat(group.load(value, subStack)) } } } - if (paramsToBeAssigned.size > 0 || invalidParams.size > 0) { - return [...paramsToBeAssigned, ...invalidParams] - } else { - return null - } + return unrecognized } - /** Finalize the configuration. Set some default options based on the provided values. */ - finalize() { - if (!this.params.useLoader.setByUser && this.params.entry.value !== DEFAULT_ENTRY_POINT) { - this.params.useLoader.value = false + loadAll(configs: (StringConfig | null | undefined)[]): string[] { + let unrecognized: string[] = [] + for (const config of configs) { + if (config != null) { + unrecognized = unrecognized.concat(this.load(config)) + } } + return unrecognized } - printValueUpdateError(key: string, selfVal: any, otherVal: any) { - console.error( - `The provided value for Config.${key} is invalid. Expected boolean, got '${otherVal}'. \ - Using the default value '${selfVal}' instead.` - ) + stringify(): StringConfig { + const config: StringConfig = {} + const groupsEntries = Object.entries(this.groups) + if (groupsEntries.length > 0) { + config.groups = {} + for (const [name, group] of groupsEntries) { + config.groups[name] = group.stringify() + } + } + const optionsEntries = Object.entries(this.options) + if (optionsEntries.length > 0) { + config.options = {} + for (const [name, option] of optionsEntries) { + config.options[name] = option.value.toString() + } + } + return config } - strigifiedKeyValueMap(): Record { - const map: Record = {} - for (const [key, param] of Object.entries(this.params)) { - if (param.value) { - map[key] = param.value.toString() - } else { - map[key] = param.value + prettyPrint(indent = 0): string { + // The number is used for sorting in ordering to put options before groups. + const entries: [string, number, string][] = [] + const optionsEntries = Object.entries(this.options) + if (optionsEntries.length > 0) { + for (const [name, option] of optionsEntries) { + entries.push([name, 0, option.value.toString()]) } } - return map + const groupsEntries = Object.entries(this.groups) + if (groupsEntries.length > 0) { + for (const [name, group] of groupsEntries) { + entries.push([name, 1, '\n' + group.prettyPrint(indent + 1)]) + } + } + entries.sort() + return entries + .map(([name, _, value]) => ' '.repeat(2 * indent) + name + ': ' + value) + .join('\n') } - print() { - logger.log(`Resolved config:`, this.strigifiedKeyValueMap()) + optionsRecursive(): AnyOption[] { + const options: AnyOption[] = [] + for (const option of Object.values(this.options)) { + options.push(option) + } + for (const group of Object.values(this.groups)) { + options.push(...group.optionsRecursive()) + } + return options + } +} + +// =============== +// === Options === +// =============== + +/** Type-level conversion of `OptionObject` to `Option`. */ +type ToOption = Option + +/** Type-level conversion of `GroupObject` to `Group`. */ +type ToGroup = Group< + { [K in keyof T['options']]: ToOption[K]> }, + { [K in keyof T['groups']]: ToGroup[K]> } +> + +/** Convert the plain group object to a `Group` object instance. */ +export function objectToGroup( + obj: T, + scope: Record = {} +): ToGroup { + const options: Record = {} + const groups: Record = {} + if (obj.options) { + for (const [name, option] of Object.entries(obj.options)) { + options[name] = objectToOption(option, scope) + } + } + if (obj.groups) { + for (const [name, group] of Object.entries(obj.groups)) { + groups[name] = objectToGroup(group, scope) + } } + const description = obj.description + return new Group({ description, options, groups }) as ToGroup } + +/** Convert the plain option object to an `Option` object instance. */ +export function objectToOption( + obj: T, + scope: Record +): ToOption { + const code = obj.valueEval + if (code != null) { + /* eslint @typescript-eslint/no-implied-eval: "off" */ + const value: unknown = new Function('scope', 'return ' + code)(scope) + const expectedType = typeof obj.value + if (typeof value === typeof obj.value) { + obj.value = value as OptionValue + } else { + logger.error(`The value of eval option '${code}' did not resolve to '${expectedType}'.`) + } + } + return new Option(obj) +} + +/** The configuration of the EnsoGL application. The options can be overriden by the user. The + * implementation automatically casts the values to the correct types. For example, if an option + * override for type boolean was provided as `'true'`, it will be parsed automatically. Moreover, + * it is possible to extend the provided option list with custom options. See the `extend` method + * to learn more. */ +export const options = objectToGroup(jsonCfg) + +/** Type of configuration options. */ +export type Options = typeof options & AnyGroup diff --git a/lib/rust/ensogl/pack/js/src/runner/debug/help-screen.ts b/lib/rust/ensogl/pack/js/src/runner/debug/help-screen.ts index b392b131dfe3..17db2301df52 100644 --- a/lib/rust/ensogl/pack/js/src/runner/debug/help-screen.ts +++ b/lib/rust/ensogl/pack/js/src/runner/debug/help-screen.ts @@ -2,6 +2,21 @@ import * as dom from '../dom/dom' +// ========================= +// === HelpScreenSection === +// ========================= + +export class HelpScreenSection { + description?: string + name: string + entries: HelpScreenEntry[] + constructor(cfg: { name: string; description?: string; entries: HelpScreenEntry[] }) { + this.name = cfg.name + this.description = cfg.description + this.entries = cfg.entries + } +} + // ======================= // === HelpScreenEntry === // ======================= @@ -27,14 +42,18 @@ export class HelpScreenEntry { /** A visual help screen. It displays a table of the provided entries. */ export class HelpScreen { /** Displays a debug screen which allows the user to run one of predefined debug examples. */ - display(cfg: { title: string; headers: string[]; entries: HelpScreenEntry[] }) { + display(cfg: { title: string; headers: string[]; sections: HelpScreenSection[] }) { const padding = '8px' - const backgroundRadius = '8px' + const backgroundRadiusPx = 8 + const sectionPaddingPx = 10 + const backgroundRadius = `${backgroundRadiusPx}px` + const sectionBackgroundRadius = `${backgroundRadiusPx + sectionPaddingPx}px` const div = dom.newTopLevelDiv() div.style.fontFamily = '"SF Pro Text","SF Pro Icons","Helvetica Neue","Helvetica","Arial",sans-serif' div.style.fontSize = '14px' div.style.overflow = 'scroll' + div.style.color = '#000000c9' const div2 = document.createElement('div') div2.style.padding = '10px' div.appendChild(div2) @@ -42,64 +61,98 @@ export class HelpScreen { const title = document.createElement('div') title.style.fontWeight = 'bold' title.style.padding = '8px' + title.style.fontSize = '16px' + title.style.color = 'white' + title.style.background = '#d5461e' + title.style.borderRadius = '8px' const content = document.createTextNode(cfg.title) - const table = document.createElement('table') - table.style.paddingTop = '20px' - table.style.borderCollapse = 'collapse' - table.style.maxWidth = '800px' + div2.style.position = 'absolute' div2.style.zIndex = '1' title.appendChild(content) div2.appendChild(title) - div2.appendChild(table) - - const tr = document.createElement('tr') - for (const header of cfg.headers) { - const th = document.createElement('th') - th.innerText = header - th.style.textAlign = 'left' - th.style.padding = padding - tr.appendChild(th) - } - table.appendChild(tr) - let rowWithBg = true - for (const entry of cfg.entries) { + for (const section of cfg.sections) { + const sectionDiv = document.createElement('div') + sectionDiv.style.marginTop = '16px' + sectionDiv.style.padding = `${sectionPaddingPx}px` + sectionDiv.style.border = '3px solid #000000c9' + sectionDiv.style.borderRadius = sectionBackgroundRadius + sectionDiv.style.maxWidth = '800px' + + const sectionTitleDiv = document.createElement('div') + const sectionTitle = document.createTextNode(section.name) + sectionTitleDiv.style.fontWeight = 'bold' + sectionTitleDiv.style.fontSize = '16px' + sectionTitleDiv.style.marginBottom = '6px' + sectionTitleDiv.style.marginLeft = '2px' + sectionDiv.appendChild(sectionTitleDiv) + sectionTitleDiv.appendChild(sectionTitle) + + if (section.description) { + const sectionDescriptionDiv = document.createElement('div') + const sectionDescription = document.createTextNode(section.description) + sectionDescriptionDiv.style.marginBottom = '16px' + sectionDescriptionDiv.style.marginLeft = '2px' + sectionDiv.appendChild(sectionDescriptionDiv) + sectionDescriptionDiv.appendChild(sectionDescription) + } + + const table = document.createElement('table') + table.style.paddingTop = '20px' + table.style.borderCollapse = 'collapse' + const tr = document.createElement('tr') + for (const header of cfg.headers) { + const th = document.createElement('th') + th.innerText = header + th.style.textAlign = 'left' + th.style.padding = padding + tr.appendChild(th) + } table.appendChild(tr) - const last = cfg.headers.length - 1 - for (let i = 0; i < cfg.headers.length; i++) { - const td = document.createElement('td') - td.style.padding = padding - tr.appendChild(td) - if (rowWithBg) { - td.style.background = '#00000010' - if (i == 0) { - td.style.borderTopLeftRadius = backgroundRadius - td.style.borderBottomLeftRadius = backgroundRadius - } else if (i == last) { - td.style.borderTopRightRadius = backgroundRadius - td.style.borderBottomRightRadius = backgroundRadius - } - } - if (i == 0) { - const a = document.createElement('a') - const linkText = document.createTextNode(entry.name) - a.appendChild(linkText) - a.title = entry.name - if (entry.href) { - a.href = entry.href + sectionDiv.appendChild(table) + div2.appendChild(sectionDiv) + + let rowWithBg = true + for (const entry of section.entries) { + const tr = document.createElement('tr') + table.appendChild(tr) + + const last = cfg.headers.length - 1 + for (let i = 0; i < cfg.headers.length; i++) { + const td = document.createElement('td') + td.style.padding = padding + tr.appendChild(td) + if (rowWithBg) { + td.style.background = '#00000010' + if (i == 0) { + td.style.borderTopLeftRadius = backgroundRadius + td.style.borderBottomLeftRadius = backgroundRadius + } else if (i == last) { + td.style.borderTopRightRadius = backgroundRadius + td.style.borderBottomRightRadius = backgroundRadius + } } - td.appendChild(a) - } else { - const value = entry.values[i - 1] - if (value != null) { - td.innerText = value + if (i == 0) { + const a = document.createElement('a') + const linkText = document.createTextNode(entry.name) + a.appendChild(linkText) + a.title = entry.name + if (entry.href) { + a.href = entry.href + } + td.appendChild(a) + } else { + const value = entry.values[i - 1] + if (value != null) { + td.innerText = value + } } } + rowWithBg = !rowWithBg } - rowWithBg = !rowWithBg } } } diff --git a/lib/rust/ensogl/pack/js/src/runner/debug/package-info.ts b/lib/rust/ensogl/pack/js/src/runner/debug/package-info.ts index a001119169d9..9d4522fc5535 100644 --- a/lib/rust/ensogl/pack/js/src/runner/debug/package-info.ts +++ b/lib/rust/ensogl/pack/js/src/runner/debug/package-info.ts @@ -18,7 +18,7 @@ export class PackageInfo { display() { const entries = Object.entries(this) if (entries.length > 0) { - logger.with('Package info.', () => { + logger.group('Package info.', () => { for (const [key, value] of Object.entries(this)) { if (value != null) { logger.log(`${key}: ${value}`) diff --git a/lib/rust/ensogl/pack/js/src/runner/host.ts b/lib/rust/ensogl/pack/js/src/runner/host.ts index d8cedd83c7af..75de27eda059 100644 --- a/lib/rust/ensogl/pack/js/src/runner/host.ts +++ b/lib/rust/ensogl/pack/js/src/runner/host.ts @@ -1,5 +1,7 @@ /** @file Utilities to work with the host environment, whether it is a browser of node. */ +import { logger } from './log' + // ====================== // === Host Utilities === // ====================== @@ -17,11 +19,36 @@ const node = !browser // const global = {} global ??= window +interface UrlParams { + [key: string]: string | UrlParams +} + /** Returns the parameters passed in the URL query string. */ -function urlParams(): Record { +function urlParams(): UrlParams { if (browser) { + const out: UrlParams = {} const urlParams = new URLSearchParams(window.location.search) - return Object.fromEntries(urlParams.entries()) + for (const [name, value] of urlParams.entries()) { + let obj = out + const path = name.split('.') + const lastSegment = path.pop() + if (lastSegment == null) { + logger.error(`Invalid URL parameter name: '${name}'`) + } else { + let segment = null + while ((segment = path.shift()) != null) { + const nextObj = obj[segment] ?? {} + if (typeof nextObj === 'string') { + logger.error(`Duplicate URL parameter name: '${name}'`) + } else { + obj[segment] = nextObj + obj = nextObj + } + } + obj[lastSegment] = value + } + } + return out } else { return {} } diff --git a/lib/rust/ensogl/pack/js/src/runner/index.ts b/lib/rust/ensogl/pack/js/src/runner/index.ts index 6e37fc85662d..737926f44561 100644 --- a/lib/rust/ensogl/pack/js/src/runner/index.ts +++ b/lib/rust/ensogl/pack/js/src/runner/index.ts @@ -12,6 +12,7 @@ import * as debug from 'runner/debug' import host from 'runner/host' import { logger } from 'runner/log' import { sortedWasmFunctions } from 'runner/wasm' +import { HelpScreenSection } from 'runner/debug' // =============== // === Exports === @@ -22,7 +23,7 @@ export { config } export type { LogLevel } from 'runner/log/logger' export { logger, Logger, Consumer } from 'runner/log' -export { Param } from 'runner/config' +export { Option } from 'runner/config' // ============================== // === Files to be downloaded === @@ -193,7 +194,7 @@ class Scheduler { /** The main application class. */ export class App { packageInfo: debug.PackageInfo - config: config.Config + config: config.Options wasm: any = null loader: wasm.Loader | null = null shaders: Shaders | null = null @@ -203,16 +204,23 @@ export class App { initialized = false constructor(opts?: { - configExtension?: config.ExternalConfig + configOptions?: config.Options packageInfo?: Record - config?: Record + config?: config.StringConfig }) { this.packageInfo = new debug.PackageInfo(opts?.packageInfo ?? {}) - this.config = new config.Config(opts?.configExtension) - const unrecognizedParams = this.config.resolve([opts?.config, host.urlParams()]) - if (unrecognizedParams) { - this.config.print() - this.showConfigOptions(unrecognizedParams) + this.config = config.options + const unrecognized = log.Task.runCollapsed('Resolving application configuration.', () => { + const inputConfig = opts?.configOptions + if (inputConfig != null) { + this.config = inputConfig + } + logger.log(this.config.prettyPrint()) + return this.config.loadAll([opts?.config, host.urlParams()]) + }) + if (unrecognized.length > 0) { + logger.error(`Unrecognized configuration parameters: ${unrecognized.join(', ')}.`) + this.showConfigOptions(unrecognized) } else { this.initBrowser() this.initialized = true @@ -243,7 +251,7 @@ export class App { if (host.browser) { this.styleRoot() dom.disableContextMenu() - if (this.config.params.debug.value) { + if (this.config.options.debug.value) { logger.log('Application is run in debug mode. Logs will not be hidden.') } else { this.printScamWarning() @@ -267,7 +275,6 @@ export class App { if (!this.initialized) { logger.log("App wasn't initialized properly. Skipping run.") } else { - this.config.print() await this.loadAndInitWasm() await this.runEntryPoints() } @@ -289,7 +296,7 @@ export class App { return module.exports` )() const out: unknown = await snippetsFn.init(wasm) - if (this.config.params.enableSpector.value) { + if (this.config.groups.debug.options.enableSpector.value) { /* eslint @typescript-eslint/no-unsafe-member-access: "off" */ /* eslint @typescript-eslint/no-unsafe-call: "off" */ if (host.browser) { @@ -309,7 +316,7 @@ export class App { async loadWasm() { const loader = new wasm.Loader(this.config) - const shadersUrl = this.config.params.shadersUrl.value + const shadersUrl = this.config.groups.loader.options.shadersUrl.value const shadersNames = await log.Task.asyncRunCollapsed( 'Downloading shaders list.', async () => { @@ -320,8 +327,8 @@ export class App { ) const files = new Files( - this.config.params.pkgJsUrl.value, - this.config.params.pkgWasmUrl.value + this.config.groups.loader.options.jsUrl.value, + this.config.groups.loader.options.wasmUrl.value ) for (const mangledName of shadersNames) { const unmangledName = name.unmangle(mangledName) @@ -387,7 +394,7 @@ export class App { /** Check whether the time needed to run before main entry points is reasonable. Print a warning * message otherwise. */ checkBeforeMainEntryPointsTime(time: number) { - if (time > this.config.params.maxBeforeMainEntryPointsTimeMs.value) { + if (time > this.config.groups.startup.options.maxBeforeMainTimeMs.value) { logger.error( `Entry points took ${time} milliseconds to run. This is too long. ` + 'Before main entry points should be used for fast initialization only.' @@ -397,7 +404,7 @@ export class App { /** Run both before main entry points and main entry point. */ async runEntryPoints() { - const entryPointName = this.config.params.entry.value + const entryPointName = this.config.groups.startup.options.entry.value const entryPoint = this.mainEntryPoints.get(entryPointName) if (entryPoint) { await this.runBeforeMainEntryPoints() @@ -433,25 +440,75 @@ export class App { description = rustDocs } } - const href = '?entry=' + entryPoint.strippedName + const href = '?startup.entry=' + entryPoint.strippedName return new debug.HelpScreenEntry(entryPoint.strippedName, [description], href) }) + const name = 'Entry points' + const sections = [new debug.HelpScreenSection({ name, entries })] const headers = ['Name', 'Description'] - new debug.HelpScreen().display({ title, headers, entries }) + new debug.HelpScreen().display({ title, headers, sections }) } - showConfigOptions(unknownConfigOptions?: string[]) { + showConfigOptions(unknownOptions?: string[]) { logger.log('Showing config options help screen.') - const msg = unknownConfigOptions - ? `Unknown config options: '${unknownConfigOptions.join(', ')}'. ` - : '' - const title = msg + 'Available options:' - const entries = Array.from(Object.entries(this.config.params)).map(([key, option]) => { - return new debug.HelpScreenEntry(key, [option.description, String(option.default)]) + let msg = '' + if (unknownOptions) { + const optionLabel = unknownOptions.length > 1 ? 'options' : 'option' + msg = `Unknown config ${optionLabel}: ${unknownOptions.map(t => `'${t}'`).join(', ')}. ` + } + const sectionsData: [string, string, debug.HelpScreenEntry[]][] = Object.entries( + this.config.groups + ).map(([groupName, group]) => { + const groupOptions = group.optionsRecursive() + const entriesData: [string, string, string][] = groupOptions.map(opt => [ + opt.qualifiedName(), + opt.description, + String(opt.default), + ]) + entriesData.sort() + const entries = entriesData.map(([name, description, def]) => { + return new debug.HelpScreenEntry(name, [description, def]) + }) + const option = this.config.options[groupName] + if (option != null) { + const entry = new debug.HelpScreenEntry(groupName, [ + option.description, + String(option.default), + ]) + entries.unshift(entry) + } + const name = + groupName.charAt(0).toUpperCase() + + groupName.slice(1).replace(/([A-Z])/g, ' $1') + + ' Options' + const description = group.description + return [name, description, entries] + }) + sectionsData.sort() + const sections = sectionsData.map( + ([name, description, entries]) => + new debug.HelpScreenSection({ name, description, entries }) + ) + + const rootEntries = Object.entries(this.config.options).flatMap(([optionName, option]) => { + if (optionName in this.config.groups) { + return [] + } + const entry = new debug.HelpScreenEntry(optionName, [ + option.description, + String(option.default), + ]) + return [entry] }) + if (rootEntries.length > 0) { + const name = 'Other Options' + sections.push(new debug.HelpScreenSection({ name, entries: rootEntries })) + } + + const title = msg + 'Available options:' const headers = ['Name', 'Description', 'Default'] - new debug.HelpScreen().display({ title, headers, entries }) + new debug.HelpScreen().display({ title, headers, sections }) } /** Print the warning for the end user that they should not copy any code to the console. */ diff --git a/lib/rust/ensogl/pack/js/src/runner/log.ts b/lib/rust/ensogl/pack/js/src/runner/log.ts index 0a96c69bc821..1e26246c11d4 100644 --- a/lib/rust/ensogl/pack/js/src/runner/log.ts +++ b/lib/rust/ensogl/pack/js/src/runner/log.ts @@ -1,7 +1,6 @@ /** @file Logging utilities. */ export * from './log/logger' -export * from './log/task' export * from './log/router' /** Panics with the provided message. diff --git a/lib/rust/ensogl/pack/js/src/runner/log/logger.ts b/lib/rust/ensogl/pack/js/src/runner/log/logger.ts index 2adae8135594..87803797f6e2 100644 --- a/lib/rust/ensogl/pack/js/src/runner/log/logger.ts +++ b/lib/rust/ensogl/pack/js/src/runner/log/logger.ts @@ -21,13 +21,25 @@ function isObject(value: any): boolean { /* eslint @typescript-eslint/no-extraneous-class: "off" */ class Colors { static resetCode = '\x1b[0m' + static blackCode = '\x1b[30m' static redCode = '\x1b[31m' - static orangeCode = '\x1b[33m' + static greenCode = '\x1b[32m' + static yellowCode = '\x1b[33m' + static blueCode = '\x1b[34m' + static magentaCode = '\x1b[35m' + static cyanCode = '\x1b[36m' + static whiteCode = '\x1b[37m' + static black(text: string): string { + return Colors.blackCode + text + Colors.resetCode + } static red(text: string): string { return Colors.redCode + text + Colors.resetCode } - static orange(text: string): string { - return Colors.orangeCode + text + Colors.resetCode + static green(text: string): string { + return Colors.greenCode + text + Colors.resetCode + } + static yellow(text: string): string { + return Colors.yellowCode + text + Colors.resetCode } static boldStart(): string { return '\x1b[1m' @@ -41,13 +53,13 @@ class Colors { static levelStart(level: number): string { switch (level) { case 0: - return `\x1b[38;5;155m` + return Colors.greenCode case 1: - return `\x1b[38;5;85m` + return Colors.cyanCode case 2: - return `\x1b[38;5;51m` + return Colors.blueCode default: - return `\x1b[38;5;64m` + return Colors.magentaCode } } } @@ -63,14 +75,20 @@ export abstract class Consumer { abstract message(fn: LogLevel, ...args: unknown[]): void /** Start a group and log a message. */ - abstract group(...args: unknown[]): void + abstract startGroup(...args: unknown[]): void /** Start a group and log a message. */ - abstract groupCollapsed(...args: unknown[]): void + abstract startGroupCollapsed(...args: unknown[]): void /** Log a message and end the last opened group. */ abstract groupEnd(...args: unknown[]): void + /** The width of the terminal in columns. In case there is no terminal, e.g. when the output + * stream is redirected to a file, this results in a `undefined`. */ + terminalWidth(): number | undefined { + return process.stdout.columns + } + /** Log a message. */ log(...args: unknown[]) { this.message('log', ...args) @@ -92,8 +110,8 @@ export abstract class Consumer { } /** Start a group, log a message, evaluate the provided function, and end the group. */ - with(message: string, f: () => T): T { - this.group(message) + group(message: string, f: () => T): T { + this.startGroup(message) const out = f() this.groupEnd() return out @@ -101,16 +119,16 @@ export abstract class Consumer { /** Start a collapsed group, log a message, evaluate the provided function, and end the * group. */ - withCollapsed(message: string, f: () => T): T { - this.groupCollapsed(message) + groupCollapsed(message: string, f: () => T): T { + this.startGroupCollapsed(message) const out = f() this.groupEnd() return out } /** Start a group, log a message, evaluate the provided async function, and end the group. */ - async asyncWith(message: string, f: () => Promise): Promise { - this.group(message) + async asyncGroup(message: string, f: () => Promise): Promise { + this.startGroup(message) const out = await f() this.groupEnd() return out @@ -118,12 +136,24 @@ export abstract class Consumer { /** Start a collapsed group, log a message, evaluate the provided async function, and end the * group. */ - async asyncWithCollapsed(message: string, f: () => Promise): Promise { - this.groupCollapsed(message) + async asyncGroupCollapsed(message: string, f: () => Promise): Promise { + this.startGroupCollapsed(message) const out = await f() this.groupEnd() return out } + + /** Start a group, log a message, evaluate the provided function, end the group, and log the + * total operation time. */ + groupMeasured(message: string, f: () => T): T { + return Task.run(message, f) + } + + /** Start a group, log a message, evaluate the provided async function, end the group, and log + * the total operation time. */ + async asyncGroupMeasured(message: string, f: () => Promise): Promise { + return await Task.asyncRun(message, f) + } } // ============== @@ -147,16 +177,16 @@ export class Logger extends Consumer { } /** Start a log group. */ - group(...args: unknown[]) { + startGroup(...args: unknown[]) { for (const consumer of this.consumers) { - consumer.group(...args) + consumer.startGroup(...args) } } /** Start a collapsed log group. */ - groupCollapsed(...args: unknown[]) { + startGroupCollapsed(...args: unknown[]) { for (const consumer of this.consumers) { - consumer.groupCollapsed(...args) + consumer.startGroupCollapsed(...args) } } @@ -201,10 +231,10 @@ export class Console extends Consumer { if (host.browser) { c[fn](...strArgs) } else { - let color: null | 'orange' | 'red' + let color: null | 'yellow' | 'red' switch (fn) { case 'warn': - color = 'orange' + color = 'yellow' break case 'error': color = 'red' @@ -223,12 +253,12 @@ export class Console extends Consumer { const indentedArgs = coloredArgs.map(arg => arg.replaceAll('\n', `\n${indent}`)) c.log(this.indentShorter(), ...indentedArgs) } else { - c.log(...strArgs) + c.log(...coloredArgs) } } } - group(...args: unknown[]) { + startGroup(...args: unknown[]) { if (host.browser) { console.group(...args) } else { @@ -238,12 +268,12 @@ export class Console extends Consumer { this.indentLvl += 1 } - groupCollapsed(...args: unknown[]) { + startGroupCollapsed(...args: unknown[]) { if (host.browser) { console.groupCollapsed(...args) this.indentLvl += 1 } else { - this.group(...args) + this.startGroup(...args) } } @@ -257,7 +287,7 @@ export class Console extends Consumer { console.groupEnd() } else { const styleStart = `${Colors.levelStart(this.indentLvl)}` - console.log(`${this.indent()}${styleStart}╰`, ...args) + console.log(`${this.indent()}${styleStart}╰`, ...args, Colors.reset()) } } else { this.log(...args) @@ -278,6 +308,179 @@ export class Console extends Consumer { } } +// ============ +// === Task === +// ============ + +/** A logging utility which groups subsequent operations in nicely formatted groups and logs their + * evaluation time. */ +export class Task { + startTime = 0 + endTime = 0 + constructor(public message: string) {} + + private startBody() { + this.startTime = performance.now() + } + + private endBody(): [number, number] { + this.endTime = performance.now() + const ms = this.endTime - this.startTime + let msRounded = Math.round(ms * 10) / 10 + if (msRounded == 0) { + msRounded = Math.round(ms * 100) / 100 + } + if (msRounded == 0) { + msRounded = Math.round(ms * 1000) / 1000 + } + return [ms, msRounded] + } + + /** Start the task. You have to explicitly call the `end` method to finish this task. If + * possible, use the `with` method instead. */ + start() { + logger.startGroup(`${this.message}`) + this.startBody() + } + + /** Start the task and display subsequent logs in a collapsed group. You have to explicitly call + * the `end` method to finish this task. If possible, use the `withCollapsed` method instead. */ + startCollapsed() { + logger.startGroupCollapsed(`${this.message}`) + this.startBody() + } + + /** Start the task but do not group subsequent logs. You have to explicitly call the + * `endNoGroup` method to finish this task. If possible, use the `withNoGroup` method + * instead. */ + startNoGroup() { + logger.log(`Started ${this.message}.`) + this.startBody() + } + + /** End the previously started task. If possible use the `with*` function family instead. */ + end(): number { + const [ms, msRounded] = this.endBody() + logger.groupEnd(`Done in ${msRounded} ms.`) + return ms + } + + /** End the previously started no-group task. If possible use the `with*` function family + * instead. */ + endNoGroup(): number { + const [ms, msRounded] = this.endBody() + logger.log(`Finished ${this.message} in ${msRounded} ms.`) + return ms + } + + /** Start the task. You have to explicitly call the `end` method to finish this task. If + * possible, use the `with` method instead. */ + static start(message: string): Task { + const task = new Task(message) + task.start() + return task + } + + /** Start the task and display subsequent logs in a collapsed group. You have to explicitly call + * the `end` method to finish this task. If possible, use the `withCollapsed` method instead. */ + static startCollapsed(message: string): Task { + const task = new Task(message) + task.startCollapsed() + return task + } + + /** Start the task but do not group subsequent logs. You have to explicitly call the + * `endNoGroup` method to finish this task. If possible, use the `withNoGroup` method + * instead. */ + static startNoGroup(message: string): Task { + const task = new Task(message) + task.startNoGroup() + return task + } + + /** Start the task, evaluate the provided function, and end the task. */ + static run(message: string, f: () => T): T { + const task = Task.start(message) + const out = f() + task.end() + return out + } + + /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided + * function, and end the task. */ + static runCollapsed(message: string, f: () => T): T { + const task = Task.startCollapsed(message) + const out = f() + task.end() + return out + } + + /** Start the task, evaluate the provided async function, and end the task. */ + static async asyncRun(message: string, f: () => Promise): Promise { + const task = Task.start(message) + const out = await f() + task.end() + return out + } + + /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided + * async function, and end the task. */ + static async asyncRunCollapsed(message: string, f: () => Promise): Promise { + const task = Task.startCollapsed(message) + const out = await f() + task.end() + return out + } + + /** Start the task, evaluate the provided async function, and end the task. Do not group + * subsequent logs. */ + static async asyncRunNoGroup(message: string, f: () => Promise): Promise { + const task = Task.startNoGroup(message) + const out = await f() + task.endNoGroup() + return out + } + + /** Start the task, evaluate the provided function, and end the task. Return the function result + * together with the time information. */ + static runTimed(message: string, f: () => T): [number, T] { + const task = Task.start(message) + const out = f() + const ms = task.end() + return [ms, out] + } + + /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided + * function, and end the task. Return the function result together with the time information. */ + static runCollapsedTimed(message: string, f: () => T): [number, T] { + const task = Task.startCollapsed(message) + const out = f() + const ms = task.end() + return [ms, out] + } + + /** Start the task, evaluate the provided async function, and end the task. Return the function + * result together with the time information. */ + static async asyncRunTimed(message: string, f: () => Promise): Promise<[number, T]> { + const task = Task.start(message) + const out = await f() + const ms = task.end() + return [ms, out] + } + + /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided async + * function, and end the task. Return the function result together with the time information. */ + static async asyncRunCollapsedTimed( + message: string, + f: () => Promise + ): Promise<[number, T]> { + const task = Task.startCollapsed(message) + const out = await f() + const ms = task.end() + return [ms, out] + } +} + // =============================== // === Default Logger Instance === // =============================== diff --git a/lib/rust/ensogl/pack/js/src/runner/log/task.ts b/lib/rust/ensogl/pack/js/src/runner/log/task.ts deleted file mode 100644 index 6b39a554033c..000000000000 --- a/lib/rust/ensogl/pack/js/src/runner/log/task.ts +++ /dev/null @@ -1,177 +0,0 @@ -/** @file A logging utility which groups subsequent operations in nicely formatted groups and logs - * their evaluation time. */ - -import { logger } from 'runner/log/logger' - -// ============ -// === Task === -// ============ - -/** A logging utility which groups subsequent operations in nicely formatted groups and logs their - * evaluation time. */ -export class Task { - startTime = 0 - endTime = 0 - constructor(public message: string) {} - - private startBody() { - this.startTime = performance.now() - } - - private endBody(): [number, number] { - this.endTime = performance.now() - const ms = this.endTime - this.startTime - let msRounded = Math.round(ms * 10) / 10 - if (msRounded == 0) { - msRounded = Math.round(ms * 100) / 100 - } - if (msRounded == 0) { - msRounded = Math.round(ms * 1000) / 1000 - } - return [ms, msRounded] - } - - /** Start the task. You have to explicitly call the `end` method to finish this task. If - * possible, use the `with` method instead. */ - start() { - logger.group(`${this.message}`) - this.startBody() - } - - /** Start the task and display subsequent logs in a collapsed group. You have to explicitly call - * the `end` method to finish this task. If possible, use the `withCollapsed` method instead. */ - startCollapsed() { - logger.groupCollapsed(`${this.message}`) - this.startBody() - } - - /** Start the task but do not group subsequent logs. You have to explicitly call the - * `endNoGroup` method to finish this task. If possible, use the `withNoGroup` method - * instead. */ - startNoGroup() { - logger.log(`Started ${this.message}.`) - this.startBody() - } - - /** End the previously started task. If possible use the `with*` function family instead. */ - end(): number { - const [ms, msRounded] = this.endBody() - logger.groupEnd(`Done in ${msRounded} ms.`) - return ms - } - - /** End the previously started no-group task. If possible use the `with*` function family - * instead. */ - endNoGroup(): number { - const [ms, msRounded] = this.endBody() - logger.log(`Finished ${this.message} in ${msRounded} ms.`) - return ms - } - - /** Start the task. You have to explicitly call the `end` method to finish this task. If - * possible, use the `with` method instead. */ - static start(message: string): Task { - const task = new Task(message) - task.start() - return task - } - - /** Start the task and display subsequent logs in a collapsed group. You have to explicitly call - * the `end` method to finish this task. If possible, use the `withCollapsed` method instead. */ - static startCollapsed(message: string): Task { - const task = new Task(message) - task.startCollapsed() - return task - } - - /** Start the task but do not group subsequent logs. You have to explicitly call the - * `endNoGroup` method to finish this task. If possible, use the `withNoGroup` method - * instead. */ - static startNoGroup(message: string): Task { - const task = new Task(message) - task.startNoGroup() - return task - } - - /** Start the task, evaluate the provided function, and end the task. */ - static run(message: string, f: () => T): T { - const task = Task.start(message) - const out = f() - task.end() - return out - } - - /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided - * function, and end the task. */ - static runCollapsed(message: string, f: () => T): T { - const task = Task.startCollapsed(message) - const out = f() - task.end() - return out - } - - /** Start the task, evaluate the provided async function, and end the task. */ - static async asyncRun(message: string, f: () => Promise): Promise { - const task = Task.start(message) - const out = await f() - task.end() - return out - } - - /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided - * async function, and end the task. */ - static async asyncRunCollapsed(message: string, f: () => Promise): Promise { - const task = Task.startCollapsed(message) - const out = await f() - task.end() - return out - } - - /** Start the task, evaluate the provided async function, and end the task. Do not group - * subsequent logs. */ - static async asyncRunNoGroup(message: string, f: () => Promise): Promise { - const task = Task.startNoGroup(message) - const out = await f() - task.endNoGroup() - return out - } - - /** Start the task, evaluate the provided function, and end the task. Return the function result - * together with the time information. */ - static runTimed(message: string, f: () => T): [number, T] { - const task = Task.start(message) - const out = f() - const ms = task.end() - return [ms, out] - } - - /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided - * function, and end the task. Return the function result together with the time information. */ - static runCollapsedTimed(message: string, f: () => T): [number, T] { - const task = Task.startCollapsed(message) - const out = f() - const ms = task.end() - return [ms, out] - } - - /** Start the task, evaluate the provided async function, and end the task. Return the function - * result together with the time information. */ - static async asyncRunTimed(message: string, f: () => Promise): Promise<[number, T]> { - const task = Task.start(message) - const out = await f() - const ms = task.end() - return [ms, out] - } - - /** Start the task, hide all subsequent logs in a collapsed group, evaluate the provided async - * function, and end the task. Return the function result together with the time information. */ - static async asyncRunCollapsedTimed( - message: string, - f: () => Promise - ): Promise<[number, T]> { - const task = Task.startCollapsed(message) - const out = await f() - const ms = task.end() - return [ms, out] - } -} diff --git a/lib/rust/ensogl/pack/js/src/runner/wasm/loader.ts b/lib/rust/ensogl/pack/js/src/runner/wasm/loader.ts index 55df0058b5be..1377da15aa99 100644 --- a/lib/rust/ensogl/pack/js/src/runner/wasm/loader.ts +++ b/lib/rust/ensogl/pack/js/src/runner/wasm/loader.ts @@ -4,7 +4,7 @@ import * as animation from 'runner/animation' import * as html_utils from 'runner/dom/dom' import * as math from 'runner/math' import * as svg from 'runner/dom/svg' -import { Config } from 'runner/config' +import { Options } from 'runner/config' import { Logo } from 'runner/dom/logo' import { logger } from 'runner/log' @@ -34,7 +34,7 @@ class ProgressIndicator { targetValue = 0 minProgressSize = 0.1 - constructor(cfg: Config) { + constructor(cfg: Options) { this.ringInnerRadius = 48 this.ringWidth = 12 @@ -87,7 +87,7 @@ class ProgressIndicator { this.set(0) this.setIndicatorOpacity(0) - if (cfg.params.useLoader.value) { + if (cfg.groups.loader.options.spinner.value) { this.initialized = Promise.all([ this.animateShow(), this.animateShowLogo(), @@ -128,8 +128,8 @@ class ProgressIndicator { - - + + @@ -316,14 +316,14 @@ export class Loader { capProgressAt: number done: Promise doneResolve: null | ((value: void | PromiseLike) => void) = null - constructor(cfg: Config) { + constructor(cfg: Options) { this.indicator = new ProgressIndicator(cfg) this.totalBytes = 0 this.receivedBytes = 0 this.downloadSpeed = 0 this.lastReceiveTime = performance.now() this.initialized = this.indicator.initialized - this.capProgressAt = cfg.params.loaderDownloadToInitRatio.value + this.capProgressAt = cfg.groups.loader.options.downloadToInitRatio.value this.done = new Promise(resolve => { this.doneResolve = resolve diff --git a/lib/rust/ensogl/pack/js/src/shader-extractor/shader-extractor.ts b/lib/rust/ensogl/pack/js/src/shader-extractor/shader-extractor.ts index decdbfc79826..1bb5cebc22ca 100644 --- a/lib/rust/ensogl/pack/js/src/shader-extractor/shader-extractor.ts +++ b/lib/rust/ensogl/pack/js/src/shader-extractor/shader-extractor.ts @@ -15,8 +15,8 @@ import * as runner from 'runner/index' * not optimized shaders and saves them to files. */ class App extends runner.App { override async loadWasm() { - const mainJsUrl = path.join(__dirname, this.config.params.pkgJsUrl.value) - const mainWasmUrl = path.join(__dirname, this.config.params.pkgWasmUrl.value) + const mainJsUrl = path.join(__dirname, this.config.groups.loader.options.jsUrl.value) + const mainWasmUrl = path.join(__dirname, this.config.groups.loader.options.wasmUrl.value) const mainJs = await fs.readFile(mainJsUrl, 'utf8') const mainWasm = await fs.readFile(mainWasmUrl) this.wasm = await this.compileAndRunWasm(mainJs, mainWasm) @@ -49,7 +49,6 @@ class App extends runner.App { const outDir = parser.args.outDir.value if (outDir) { await log.Task.asyncRun('Running the program.', async () => { - app.config.print() await app.loadAndInitWasm() const r = app.runBeforeMainEntryPoints().then(() => { return app.extractShaders(outDir) diff --git a/lib/rust/ensogl/pack/js/tsconfig.json b/lib/rust/ensogl/pack/js/tsconfig.json index b19a152ed346..e1142fa5a315 100644 --- a/lib/rust/ensogl/pack/js/tsconfig.json +++ b/lib/rust/ensogl/pack/js/tsconfig.json @@ -2,8 +2,9 @@ "include": ["src/**/*"], "compilerOptions": { "allowSyntheticDefaultImports": true, - "rootDir": "src", "baseUrl": "./src", + "declaration": true, + "declarationMap": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "inlineSourceMap": true, @@ -12,16 +13,15 @@ "moduleResolution": "node", "noImplicitOverride": true, "noUncheckedIndexedAccess": true, + "outDir": "dist", "removeComments": true, "resolveJsonModule": true, + "rootDir": "src", + "skipLibCheck": true, "strict": true, "strictNullChecks": true, "strictPropertyInitialization": true, - "target": "ES2019", - "skipLibCheck": true, - "outDir": "dist", - "declaration": true, - "declarationMap": true + "target": "ES2019" }, "ts-node": { "esm": true diff --git a/lib/rust/ensogl/pack/js/tsup.config.ts b/lib/rust/ensogl/pack/js/tsup.config.ts new file mode 100644 index 000000000000..5771948a5c59 --- /dev/null +++ b/lib/rust/ensogl/pack/js/tsup.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + outExtension({ format }) { + return { + js: `.js`, + } + }, + // FIXME Does not work: https://github.com/egoist/tsup/issues/819 + bundle: true, + skipNodeModulesBundle: false, +}) diff --git a/lib/rust/ensogl/pack/src/lib.rs b/lib/rust/ensogl/pack/src/lib.rs index 4b993ce9eb74..80c6aa47fb19 100644 --- a/lib/rust/ensogl/pack/src/lib.rs +++ b/lib/rust/ensogl/pack/src/lib.rs @@ -11,7 +11,7 @@ //! workspace | The main workspace directory (repo root). //! ├─ ... / this_crate | This crate's directory. //! │ ╰─ js | This crate's JS sources. -//! │ ├─ runner | Runner of WASM app. Compiles to `dist/index.cjs`. +//! │ ├─ runner | Runner of WASM app. Compiles to `dist/index.js`. //! │ ├─ runtime-libs | Additional libs bundled with app. E.g. SpectorJS. //! │ ├─ shader-extractor | App to extract shaders from WASM. //! │ ╰─ wasm-pack-bundle | Glue for `wasm-pack` artifacts. @@ -28,18 +28,19 @@ //! ├─ shaders | Not optimized shaders sources extracted from WASM bundle. //! │ ├─ list.txt | List of extracted not optimized shaders (no extensions). //! │ ├─ ..glsl | A single not optimized shader. (Stage = vertex|fragment). -//! │ ╰─ ... +//! │ ╰─ ... //! ├─ shaders-hash | Not optimized shader hashes. Used to detect changes. //! │ ├─ ..hash | A single not optimized shader hash. -//! │ ╰─ ... +//! │ ╰─ ... //! ├─ runtime-libs //! │ ╰─ runtime-libs.js +//! ├─ linked-dist | Either symlink to dist or to the gui artifacts. //! ╰─ dist | Final build artifacts of ensogl-pack. -//! * ├─ index.cjs | The main JS bundle to load WASM and JS wasm-pack bundles. -//! ├─ index.cjs.map | The sourcemap mapping to sources in TypeScript. +//! * ├─ index.js | The main JS bundle to load WASM and JS wasm-pack bundles. +//! ├─ index.js.map | The sourcemap mapping to sources in TypeScript. //! ** ├─ index.d.ts | TypeScript types interface file. -//! ├─ shader-extractor.cjs | Node program to extract non optimized shaders from WASM. -//! ├─ shader-extractor.cjs.map | The sourcemap mapping to sources in TypeScript. +//! ├─ shader-extractor.js | Node program to extract non optimized shaders from WASM. +//! ├─ shader-extractor.js.map | The sourcemap mapping to sources in TypeScript. //! ├─ shader-extractor.d.ts | TypeScript types interface file. //! * ├─ pkg.js | The `pks.js` artifact of wasm-pack WITH bundled snippets. //! ├─ pkg.js.map | The sourcemap mapping to `pkg.js` generated by wasm-pack. @@ -52,7 +53,7 @@ //! //! The high-level app compilation process is summarized below: //! -//! 1. If the `dist/index.cjs` file does not exist, or its modification date is older than +//! 1. If the `dist/index.js` file does not exist, or its modification date is older than //! `this_crate/js` sources: //! //! 1. `npm run install` is run in the `this_crate/js` directory. @@ -62,7 +63,7 @@ //! before-main entry points, and running the main entry point of the application. //! //! 3. The `this_crate/js/shader-extractor` is compiled to -//! `target/ensogl-pack/dist/shader-extractor.cjs`. This is a node program that extracts +//! `target/ensogl-pack/dist/shader-extractor.js`. This is a node program that extracts //! non-optimized shaders from the WASM file. //! //! 4. The `this_crate/js/runtime-libs` is compiled to @@ -77,7 +78,7 @@ //! `target/ensogl-pack/wasm-pack/index.ts`. This is the main file which when compiled glues //! `pkg.js`, `snippets`, and `runtime-libs.js` into a single bundle. //! -//! 4. The program `target/ensogl-pack/dist/shader-extractor.cjs` is run. It loads +//! 4. The program `target/ensogl-pack/dist/shader-extractor.js` is run. It loads //! `target/dist/pkg.wasm` and writes non-optimized shader code to `target/ensogl-pack/shaders`. //! //! 5. For each shader, the hash of its code is computed and compared to the hash stored in @@ -86,12 +87,12 @@ //! `dist/shaders`. //! //! 6. The `target/ensogl-pack/wasm-pack/index.ts` is compiled to -//! `target/ensogl-pack/dis/index.cjs`. It is then compiled to `target/ensogl-pack/dist/index.cjs`. +//! `target/ensogl-pack/dis/index.js`. It is then compiled to `target/ensogl-pack/dist/index.js`. //! //! //! //! # Runtime process. -//! When `target/dist/index.cjs` is run: +//! When `target/dist/index.js` is run: //! //! 1. The following files are downloaded from a server: `target/dist/{pkg.js, pkg.wasm, shaders}`. //! 2. The code from `pkg.js` is run to compile the WASM file. @@ -220,6 +221,7 @@ pub mod paths { shaders_hash: PathBuf, runtime_libs: TargetEnsoglPackRuntimeLibs, dist: TargetEnsoglPackDist, + linked_dist: PathBuf, } TargetEnsoglPackShaders { @@ -280,9 +282,10 @@ impl Paths { p.target.ensogl_pack.runtime_libs.runtime_libs = p.target.ensogl_pack.runtime_libs.join("runtime-libs.js"); p.target.ensogl_pack.dist.root = p.target.ensogl_pack.join("dist"); - p.target.ensogl_pack.dist.app = p.target.ensogl_pack.dist.join("index.cjs"); + p.target.ensogl_pack.linked_dist = p.target.ensogl_pack.join("linked-dist"); + p.target.ensogl_pack.dist.app = p.target.ensogl_pack.dist.join("index.js"); p.target.ensogl_pack.dist.shader_extractor = - p.target.ensogl_pack.dist.join("shader-extractor.cjs"); + p.target.ensogl_pack.dist.join("shader-extractor.js"); p.target.ensogl_pack.dist.pkg_js = p.target.ensogl_pack.dist.join("pkg.js"); p.target.ensogl_pack.dist.main_wasm = p.target.ensogl_pack.dist.join("pkg.wasm"); p.target.ensogl_pack.dist.shaders.root = p.target.ensogl_pack.dist.join("shaders"); @@ -522,13 +525,13 @@ pub async fn build( outputs: WasmPackOutputs, provider: impl FnOnce(WasmPackOutputs) -> Result, ) -> Result { - // FIXME: [mwu] To be removed, when shader tools are properly handled as a goodie-thingy. - let _ = ide_ci::env::prepend_to_path(r"C:\varia\install\bin"); let paths = Paths::new().await?; compile_this_crate_ts_sources(&paths).await?; run_wasm_pack(&paths, provider).await?; extract_shaders(&paths).await?; optimize_shaders(&paths).await?; let out_dir = Path::new(&outputs.out_dir); - ide_ci::fs::copy(&paths.target.ensogl_pack.dist, out_dir) + ide_ci::fs::copy(&paths.target.ensogl_pack.dist, out_dir)?; + ide_ci::fs::remove_symlink_dir_if_exists(&paths.target.ensogl_pack.linked_dist)?; + ide_ci::fs::symlink_auto(&paths.target.ensogl_pack.dist, &paths.target.ensogl_pack.linked_dist) } diff --git a/lib/rust/json-to-struct/Cargo.toml b/lib/rust/json-to-struct/Cargo.toml new file mode 100644 index 000000000000..933df1096988 --- /dev/null +++ b/lib/rust/json-to-struct/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "enso-json-to-struct" +version = "0.1.0" +authors = ["Enso Team "] +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +enso-prelude = { path = "../prelude" } +serde = { version = "1.0" } +serde_json = { workspace = true } +proc-macro2 = "1.0" diff --git a/lib/rust/json-to-struct/src/lib.rs b/lib/rust/json-to-struct/src/lib.rs new file mode 100644 index 000000000000..9c3270684a67 --- /dev/null +++ b/lib/rust/json-to-struct/src/lib.rs @@ -0,0 +1,375 @@ +//! Implementation of the [`json_to_struct`] macro, which converts a JSON file to a Rust struct. + +// === Features === +#![feature(exact_size_is_empty)] +#![feature(proc_macro_span)] +#![feature(proc_macro_def_site)] +#![feature(track_path)] +// === Standard Linter Configuration === +#![deny(non_ascii_idents)] +#![warn(unsafe_code)] +#![allow(clippy::bool_to_int_with_if)] +#![allow(clippy::let_and_return)] +// === Non-Standard Linter Configuration === +#![warn(missing_docs)] +#![warn(trivial_casts)] +#![warn(trivial_numeric_casts)] +#![warn(unused_import_braces)] +#![warn(unused_qualifications)] +#![warn(missing_copy_implementations)] +#![warn(missing_debug_implementations)] + +use enso_prelude::*; + +use serde_json::Value; +use std::path::PathBuf; +use std::str::FromStr; + + + +// ================== +// === JSON Utils === +// ================== + +/// Merge two JSON definitions with overriding. Return overridden keys. +fn merge_json(a: &mut Value, b: &Value) -> Vec { + let mut overrides = vec![]; + merge_internal(a, b, &mut vec![], &mut overrides); + overrides +} + +fn merge_internal(a: &mut Value, b: &Value, path: &mut Vec, overrides: &mut Vec) { + match (a, b) { + (&mut Value::Object(ref mut a), Value::Object(b)) => + for (k, v) in b { + path.push(k.clone()); + merge_internal(a.entry(k.clone()).or_insert(Value::Null), v, path, overrides); + path.pop(); + }, + (a, b) => { + if a != &Value::Null { + overrides.push(path.join(".")); + } + *a = b.clone(); + } + } +} + + + +// =================== +// === Boilerplate === +// =================== + +/// The boilerplate code which will be added to every generated code by the macro. +const BOILERPLATE: &str = " +/// Error containing the path to the field and the reason of the error. +#[derive(Debug, Clone)] +pub struct Error { + pub path: String, + pub reason: String, +} + +impl Error { + /// Constructor. + pub fn new(path: impl Into, reason: impl Into) -> Self { + let path = path.into(); + let reason = reason.into(); + Self { path, reason } + } + + /// Change the path of this error. + pub fn with_path(self, path: impl Into) -> Self { + let path = path.into(); + Self { path, ..self } + } + + /// Convert the error to a human-readable form. + pub fn display(&self) -> String { + format!(\"{}: {}\", self.path, self.reason) + } +} + +/// Try setting a boolean value. If the value is not a boolean, returns an error. +pub fn set_bool(target: &mut bool, value: &str, name: &str) -> Option { + let parsed_value = match value { + \"false\" => Some(false), + \"true\" => Some(true), + \"0\" => Some(false), + \"1\" => Some(true), + \"enabled\" => Some(true), + \"disabled\" => Some(false), + \"on\" => Some(true), + \"off\" => Some(false), + _ => None + }; + match parsed_value { + Some(value) => { + *target = value; + None + }, + None => Some(Error::new(name, format!(\"Expected a boolean, got '{}'\", value))) + } +} + +/// Try setting a number value. If the value is not a number, returns an error. +pub fn set_number(target: &mut f64, value: &str, name: &str) -> Option { + if let Ok(number) = value.parse::() { + *target = number; + None + } else { + Some(Error::new(name, format!(\"Expected a number, got '{}'\", value))) + } +} + +/// Try setting a string value. If the value is not a string, returns an error. +pub fn set_string(target: &mut String, value: &str, name: &str) -> Option { + *target = value.to_owned(); + None +} + +/// Allows setting values by names of the original JSON fields. The name can contain dots to refer +/// to nested fields. +#[allow(missing_docs)] +trait Setter { + fn set(&mut self, name: &str, value: String) -> Option; +} +"; + + + +// ====================== +// === JSON To Struct === +// ====================== + +/// Converts the provided JSON files into a Rust struct. If more than one file is provided, the +/// files will be merged. In case any keys will overlap, it will panic. Supports all JSON types but +/// arrays. +/// +/// For example, for the following JSON file (`test.json`): +/// ```text +/// { +/// "test": { +/// "nested": { +/// "field1": 1 +/// }, +/// "field2": "value" +/// } +/// } +/// ``` +/// The macro call `json_to_struct("test.json")` will include the [`BOILERPLATE`] code, and will +/// generate the following code: +/// +/// ```text +/// #[derive(Clone, Debug)] +/// pub struct Args { +/// pub test: RootTest, +/// } +/// +/// #[derive(Clone, Debug)] +/// pub struct RootTest { +/// pub field2: String, +/// pub nested: RootTestNested, +/// } +/// +/// #[derive(Clone, Debug)] +/// pub struct RootTestNested { +/// pub field1: f64, +/// } +/// ``` +/// +/// Also, for each struct the implementation of `Default` and `Setter` will be generated. +#[proc_macro] +pub fn json_to_struct(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let paths = files_paths(input); + mark_paths_as_tracked(&paths); + let json = read_and_merge_jsons(paths); + let code = generate(&json); + // Uncomment for debug purposes: + // std::fs::write("/tmp/out.txt", code.clone()).unwrap(); + proc_macro::TokenStream::from_str(&code).unwrap() +} + +/// Parse the input token stream as file paths. +fn files_paths(input: proc_macro::TokenStream) -> Vec { + let span = proc_macro::Span::call_site(); + let call_site_file_desc = span.source_file(); + let call_site_file = PathBuf::from(call_site_file_desc.path().to_str().unwrap()); + let call_site_dir = call_site_file.parent().unwrap(); + let rel_paths: Vec<_> = input + .into_iter() + .filter_map(|tt| match tt { + proc_macro::TokenTree::Literal(lit) => { + let lit = lit.to_string(); + let lit = lit.trim_matches('"'); + Some(lit.to_string()) + } + proc_macro::TokenTree::Punct(_) => None, + _ => panic!("Wrong arguments to macro."), + }) + .collect(); + rel_paths.into_iter().map(|t| call_site_dir.join(t)).collect() +} + +/// Mark the JSON files as tracked, so this macro is re-evaluated when they cahnge. +fn mark_paths_as_tracked(paths: &[PathBuf]) { + for path in paths { + let resolved_path = path.canonicalize().unwrap(); + let path_str = resolved_path.to_str().unwrap(); + proc_macro::tracked_path::path(path_str) + } +} + +/// Read the JSON files and merge them into a single JSON value. +fn read_and_merge_jsons(paths: Vec) -> Value { + let values: Vec<_> = paths + .iter() + .map(|path| { + let file = std::fs::File::open(path).unwrap(); + let value: Value = serde_json::from_reader(file).unwrap(); + value + }) + .collect(); + + let mut merged = Value::Null; + for value in values { + let overlaps = merge_json(&mut merged, &value); + if !overlaps.is_empty() { + let overlaps = overlaps.join(", "); + panic!("The following fields overlap: {overlaps}."); + } + } + merged +} + + + +// ======================= +// === Code Generation === +// ======================= + +/// Adds a new code line with the given indentation. +fn add_code_line(code: &mut String, indent: usize, line: &str) { + code.push_str(&" ".repeat(indent)); + code.push_str(line); + code.push('\n'); +} + +/// Wrapper for [`add_code_line`] which uses [`format!`] to generate the line. +macro_rules! ln { + ($code:expr, $indent:tt, $($ts:tt)*) => { + add_code_line($code, $indent, &format!($($ts)*)) + }; +} + +/// The main code generation entry point. +fn generate(val: &Value) -> String { + let mut decls = vec![]; + generate_rec(val, &mut vec!["Args".to_string()], &mut decls); + format!("{BOILERPLATE}\n\n{}", decls.join("\n\n")) +} + +fn generate_rec(val: &Value, path: &mut Vec, decls: &mut Vec) { + match val { + Value::Object(obj) => { + let name = path.iter().map(|t| t.capitalize_first_letter()).join(""); + let qname = path.join("."); + let mut decl = String::new(); + let mut imp_default = String::new(); + let mut imp_set = String::new(); + + ln!(&mut decl, 0, "#[derive(Clone, Debug)]"); + ln!(&mut decl, 0, "pub struct {name} {{"); + ln!(&mut decl, 1, "pub __name__: &'static str,"); + + ln!(&mut imp_default, 0, "#[allow(clippy::derivable_impls)]"); + ln!(&mut imp_default, 0, "impl Default for {name} {{"); + ln!(&mut imp_default, 1, "fn default() -> Self {{"); + ln!(&mut imp_default, 2, "Self {{"); + ln!(&mut imp_default, 3, "__name__: \"{qname}\","); + + ln!(&mut imp_set, 0, "impl Setter for {name} {{"); + ln!(&mut imp_set, 1, "fn set(&mut self, name: &str, v: String) -> Option {{"); + + for (k, v) in obj { + let key = k.camel_case_to_snake_case(); + path.push(k.clone()); + let qname = path.join("."); + ln!(&mut decl, 1, "pub {key}: {},", val_to_type(v, path)); + match v { + Value::String(v) => { + ln!(&mut imp_default, 3, "{key}: \"{v}\".to_string(),"); + ln!(&mut imp_set, 2, "if name == \"{k}\" {{"); + ln!(&mut imp_set, 3, "return set_string(&mut self.{key}, &v, \"{qname}\")"); + ln!(&mut imp_set, 2, "}}"); + } + Value::Number(v) => { + ln!(&mut imp_default, 3, "{key}: {},", format_number(v.as_f64().unwrap())); + ln!(&mut imp_set, 2, "if name == \"{k}\" {{"); + ln!(&mut imp_set, 3, "return set_number(&mut self.{key}, &v, \"{qname}\")"); + ln!(&mut imp_set, 2, "}}"); + } + Value::Bool(v) => { + ln!(&mut imp_default, 3, "{key}: {v},"); + ln!(&mut imp_set, 2, "if name == \"{k}\" {{"); + ln!(&mut imp_set, 3, "return set_bool(&mut self.{key}, &v, \"{qname}\")"); + ln!(&mut imp_set, 2, "}}"); + } + Value::Object(_) => { + ln!(&mut imp_default, 3, "{key}: Default::default(),"); + ln!(&mut imp_set, 2, "let pfx = \"{k}.\";"); + ln!(&mut imp_set, 2, "if let Some(sub_name) = name.strip_prefix(pfx) {{"); + ln!(&mut imp_set, 3, "return self.{key}.set(sub_name, v)"); + ln!(&mut imp_set, 4, ".map(|e| e.with_path(\"{qname}\"))"); + ln!(&mut imp_set, 2, "}}"); + generate_rec(v, path, decls); + } + Value::Null => { + ln!(&mut imp_default, 3, "{key}: (),"); + ln!(&mut imp_set, 2, "if name == \"{k}\" {{"); + ln!(&mut imp_set, 3, "return None"); + ln!(&mut imp_set, 2, "}}"); + } + Value::Array(_) => panic!("Arrays are not supported ('{qname}')."), + } + path.pop(); + } + ln!(&mut decl, 0, "}}"); + ln!(&mut imp_default, 2, "}}"); + ln!(&mut imp_default, 1, "}}"); + ln!(&mut imp_default, 0, "}}"); + ln!( + &mut imp_set, + 2, + "Some(Error::new(\"{qname}\", format!(\"Unknown field '{{}}'.\", name)))" + ); + ln!(&mut imp_set, 1, "}}"); + ln!(&mut imp_set, 0, "}}"); + decls.push(decl); + decls.push(imp_default); + decls.push(imp_set); + } + _ => panic!(), + } +} + +/// Format the number to always contain a dot, so it can be properly parsed as Rust code. +fn format_number(num: f64) -> String { + let mut str = format!("{num}"); + if !str.contains('.') { + str.push_str(".0"); + } + str +} + +/// Convert a JSON value to a Rust type. +fn val_to_type(val: &Value, path: &[String]) -> String { + match val { + Value::String(_) => "String".to_string(), + Value::Number(_) => "f64".to_string(), + Value::Bool(_) => "bool".to_string(), + Value::Object(_) => path.iter().map(|t| t.capitalize_first_letter()).join(""), + Value::Null => "()".to_string(), + Value::Array(_) => panic!("Arrays are not supported ('{}').", path.join(".")), + } +} diff --git a/lib/rust/prelude/src/string.rs b/lib/rust/prelude/src/string.rs index af433eb52414..a02d51a8608e 100644 --- a/lib/rust/prelude/src/string.rs +++ b/lib/rust/prelude/src/string.rs @@ -35,6 +35,12 @@ pub trait StringOps { ) -> Option<(&'a str, &'a str, &'a str)> where P: pattern::Pattern<'a>; + + /// Converts the camel case string to snake case. For example, converts `FooBar` to `foo_bar`. + fn camel_case_to_snake_case(&self) -> String; + + /// Converts the first letter of the string to uppercase. For example, converts `foo` to `Foo`. + fn capitalize_first_letter(&self) -> String; } impl> StringOps for T { @@ -67,6 +73,32 @@ impl> StringOps for T { let (mid, suffix) = rest.split_once(end_marker)?; Some((prefix, mid, suffix)) } + + fn camel_case_to_snake_case(&self) -> String { + let mut result = String::new(); + let mut chars = self.as_ref().chars(); + if let Some(first) = chars.next() { + result.push(first.to_ascii_lowercase()); + } + for c in chars { + if c.is_uppercase() { + result.push('_'); + result.push(c.to_ascii_lowercase()); + } else { + result.push(c); + } + } + result + } + + fn capitalize_first_letter(&self) -> String { + let mut chars = self.as_ref().chars(); + if let Some(first) = chars.next() { + first.to_uppercase().to_string() + chars.as_str() + } else { + String::new() + } + } } // =========== @@ -465,6 +497,8 @@ pub fn common_postfix_length(source_a: &str, source_b: &str) -> usize { mismatch.map(|(ix, _)| ix).unwrap_or(shortest) } + + // ============= // === Tests === // ============= diff --git a/lib/rust/web/src/binding/mock.rs b/lib/rust/web/src/binding/mock.rs index df90b55f037f..76f99d31926b 100644 --- a/lib/rust/web/src/binding/mock.rs +++ b/lib/rust/web/src/binding/mock.rs @@ -41,6 +41,12 @@ impl MockDefault for Result { } } +impl MockDefault for Vec { + fn mock_default() -> Self { + vec![] + } +} + /// Macro which generates [`MockDefault`] impls which redirect the call to [`Default::default`]. macro_rules! auto_impl_mock_default { ( $($tp:ident $(< $($arg:ident),* >)? ),* ) => { @@ -466,6 +472,7 @@ mock_data! { Array => Object fn of3(a: &JsValue, b: &JsValue, c: &JsValue) -> Array; fn of4(a: &JsValue, b: &JsValue, c: &JsValue, d: &JsValue) -> Array; fn of5(a: &JsValue, b: &JsValue, c: &JsValue, d: &JsValue, e: &JsValue) -> Array; + fn to_vec(&self) -> Vec; } @@ -547,6 +554,7 @@ mock_data! { Window => EventTarget // === Function === mock_data! { Function + fn call0(&self, context: &JsValue) -> Result; fn call1(&self, context: &JsValue, arg1: &JsValue) -> Result; fn call2(&self, context: &JsValue, arg1: &JsValue, arg2: &JsValue) -> Result; fn call3(&self, context: &JsValue, arg1: &JsValue, arg2: &JsValue, arg3: &JsValue)