From 1791f463b7c1203250d07a5367213abee28867c1 Mon Sep 17 00:00:00 2001 From: Empire Phoenix Date: Mon, 22 Sep 2025 01:49:25 +0200 Subject: [PATCH] remove anyhow --- rust/Cargo.toml | 32 +- rust/build.rs | 10 +- rust/rust-toolchain.toml | 1 - rust/scratch/v4_hal.rs | 440 ------ rust/scratch/water.rs | 176 --- rust/src/FatError.rs | 152 ++ rust/src/hal/battery.rs | 67 +- rust/src/hal/esp.rs | 240 ++-- rust/src/hal/initial_hal.rs | 47 +- rust/src/hal/little_fs2storage_adapter.rs | 16 +- rust/src/hal/mod.rs | 321 ++--- rust/src/hal/rtc.rs | 11 +- rust/src/hal/v4_hal.rs | 426 ++++++ rust/src/hal/water.rs | 172 +++ rust/src/log/mod.rs | 62 +- rust/src/main.rs | 192 +-- rust/src/tank.rs | 55 +- rust/src/webserver/mod.rs | 199 +-- rust/src_webpack/package-lock.json | 1540 ++++++++++++--------- rust/src_webpack/package.json | 1 + rust/src_webpack/webpack.config.js | 90 +- 21 files changed, 2268 insertions(+), 1982 deletions(-) delete mode 100644 rust/scratch/v4_hal.rs delete mode 100644 rust/scratch/water.rs create mode 100644 rust/src/FatError.rs create mode 100644 rust/src/hal/v4_hal.rs create mode 100644 rust/src/hal/water.rs diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 71624d9..cbf7567 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -26,25 +26,14 @@ command = [ "partitions.csv" ] -[profile.dev] -lto = true -strip = false -debug = false -overflow-checks = true -panic = "abort" -incremental = true -opt-level = 3 - -[profile.release] -# Explicitly disable LTO which the Xtensa codegen backend has issues -lto = true +lto = "fat" strip = true debug = false overflow-checks = true panic = "abort" incremental = true -opt-level = 3 +opt-level = "z" [package.metadata.espflash] @@ -61,7 +50,7 @@ esp-hal = { version = "=1.0.0-rc.0", features = [ ] } log = "0.4.27" -embassy-net = { version = "0.7.0", features = [ +embassy-net = { version = "0.7.1", default-features = false, features = [ "dhcpv4", "log", "medium-ethernet", @@ -83,9 +72,9 @@ esp-println = { version = "0.15.0", features = ["esp32c6", "log-04"] } # for more networking protocol support see https://crates.io/crates/edge-net embassy-executor = { version = "0.7.0", features = [ "log", - "task-arena-size-131072" + "task-arena-size-98304" ] } -embassy-time = { version = "0.5.0", features = ["log"] } +embassy-time = { version = "0.5.0", features = ["log"], default-features = false } esp-hal-embassy = { version = "0.9.0", features = ["esp32c6", "log-04"] } esp-storage = { version = "0.7.0", features = ["esp32c6"] } @@ -117,14 +106,9 @@ heapless = { version = "0.8", features = ["serde"] } embedded-hal-bus = { version = "0.3.0" } #Hardware additional driver -#ds18b20 = "0.1.1" -#bq34z100 = { version = "0.3.0", default-features = false } -one-wire-bus = "0.1.1" -ds323x = "0.6.0" -#pure code dependencies -#once_cell = "1.19.0" -anyhow = { version = "1.0.75", default-features = false } +#bq34z100 = { version = "0.3.0", default-features = false } +onewire = "0.4.0" #strum = { version = "0.27.0", default-feature = false, features = ["derive"] } measurements = "0.11.0" @@ -156,7 +140,7 @@ edge-http = { version = "0.6.1", features = ["log"] } littlefs2 = { version = "0.6.1", features = ["c-stubs", "alloc"] } littlefs2-core = "0.1.1" bytemuck = { version = "1.23.2", features = ["derive", "min_const_generics", "pod_saturating", "extern_crate_alloc"] } - +deranged = "0.5.3" [patch.crates-io] #bq34z100 = { path = "../../bq34z100_rust" } diff --git a/rust/build.rs b/rust/build.rs index de1608d..05b5381 100644 --- a/rust/build.rs +++ b/rust/build.rs @@ -58,7 +58,7 @@ fn main() { fn webpack() { //println!("cargo:rerun-if-changed=./src/src_webpack"); Command::new("rm") - .arg("./src/webserver/bundle.js") + .arg("./src/webserver/bundle.js.gz") .output() .unwrap(); @@ -81,14 +81,14 @@ fn webpack() { let _ = Command::new("cmd") .arg("/K") .arg("move") - .arg("./src_webpack/bundle.js") + .arg("./src_webpack/bundle.js.gz") .arg("./src/webserver") .output() .unwrap(); let _ = Command::new("cmd") .arg("/K") .arg("move") - .arg("./src_webpack/index.html") + .arg("./src_webpack/index.html.gz") .arg("./src/webserver") .output() .unwrap(); @@ -107,12 +107,12 @@ fn webpack() { // move webpack results to rust webserver src let _ = Command::new("mv") - .arg("./src_webpack/bundle.js") + .arg("./src_webpack/bundle.js.gz") .arg("./src/webserver") .output() .unwrap(); let _ = Command::new("mv") - .arg("./src_webpack/index.html") + .arg("./src_webpack/index.html.gz") .arg("./src/webserver") .output() .unwrap(); diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml index fd2fa13..5d56faf 100644 --- a/rust/rust-toolchain.toml +++ b/rust/rust-toolchain.toml @@ -1,3 +1,2 @@ [toolchain] channel = "nightly" -toolchain = "esp" diff --git a/rust/scratch/v4_hal.rs b/rust/scratch/v4_hal.rs deleted file mode 100644 index b6f81e9..0000000 --- a/rust/scratch/v4_hal.rs +++ /dev/null @@ -1,440 +0,0 @@ -use crate::config::PlantControllerConfig; -use crate::hal::battery::BatteryInteraction; -use crate::hal::esp::Esp; -use crate::hal::rtc::RTCModuleInteraction; -use crate::hal::v4_sensor::SensorImpl; -use crate::hal::v4_sensor::SensorInteraction; -use crate::hal::water::TankSensor; -use crate::hal::{ - deep_sleep, BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT -}; -use crate::log::{log, LogMessage}; -use anyhow::bail; -use embedded_hal::digital::OutputPin; -use embedded_hal_bus::i2c::MutexDevice; -use ina219::address::{Address, Pin}; -use ina219::calibration::UnCalibrated; -use ina219::configuration::{Configuration, OperatingMode}; -use ina219::SyncIna219; -use measurements::{Current, Resistance, Voltage}; -use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface}; -use std::result::Result::Ok as OkStd; -use embedded_can::Frame; -use embedded_can::StandardId; -use alloc::string::ToString; -use alloc::boxed::Box; -use esp_hal::gpio::Pull; - -pub enum Charger<'a> { - SolarMpptV1 { - mppt_ina: SyncIna219>, UnCalibrated>, - solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>, - charge_indicator: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>, - }, - ErrorInit {}, -} - -impl Charger<'_> { - pub(crate) fn power_save(&mut self) { - match self { - Charger::SolarMpptV1 { mppt_ina, .. } => { - let _ = mppt_ina - .set_configuration(Configuration { - reset: Default::default(), - bus_voltage_range: Default::default(), - shunt_voltage_range: Default::default(), - bus_resolution: Default::default(), - shunt_resolution: Default::default(), - operating_mode: OperatingMode::PowerDown, - }) - .map_err(|e| { - log::info!( - "Error setting ina mppt configuration during deep sleep preparation{:?}", - e - ); - }); - } - _ => {} - } - } - fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> { - match self { - Self::SolarMpptV1 { - charge_indicator, .. - } => { - charge_indicator.set_state(charging.into())?; - } - _ => {} - } - Ok(()) - } - - fn is_day(&self) -> bool { - match self { - Charger::SolarMpptV1 { solar_is_day, .. } => solar_is_day.get_level().into(), - _ => true, - } - } - - fn get_mptt_voltage(&mut self) -> anyhow::Result { - let voltage = match self { - Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina - .bus_voltage() - .map(|v| Voltage::from_millivolts(v.voltage_mv() as f64))?, - _ => { - bail!("hardware error during init") - } - }; - Ok(voltage) - } - - fn get_mptt_current(&mut self) -> anyhow::Result { - let current = match self { - Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina.shunt_voltage().map(|v| { - let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64); - let shut_value = Resistance::from_ohms(0.05_f64); - let current = shunt_voltage.as_volts() / shut_value.as_ohms(); - Current::from_amperes(current) - })?, - _ => { - bail!("hardware error during init") - } - }; - Ok(current) - } -} - -pub struct V4<'a> { - esp: Esp<'a>, - tank_sensor: TankSensor<'a>, - charger: Charger<'a>, - rtc_module: Box, - battery_monitor: Box, - config: PlantControllerConfig, - - awake: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>, - light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>, - general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>, - pump_expander: Pca9535Immediate>>, - pump_ina: Option>, UnCalibrated>>, - sensor: SensorImpl<'a>, - extra1: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>, - extra2: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>, -} - -pub(crate) fn create_v4( - peripherals: FreePeripherals, - esp: Esp<'static>, - config: PlantControllerConfig, - battery_monitor: Box, - rtc_module: Box, -) -> anyhow::Result + Send + 'static>> { - log::info!("Start v4"); - let mut awake = PinDriver::output(peripherals.gpio21.downgrade())?; - awake.set_high()?; - - let mut general_fault = PinDriver::input_output(peripherals.gpio23.downgrade())?; - general_fault.set_pull(Pull::Floating)?; - general_fault.set_low()?; - - let mut extra1 = PinDriver::output(peripherals.gpio6.downgrade())?; - extra1.set_low()?; - - let mut extra2 = PinDriver::output(peripherals.gpio15.downgrade())?; - extra2.set_low()?; - - let one_wire_pin = peripherals.gpio18.downgrade(); - let tank_power_pin = peripherals.gpio11.downgrade(); - let flow_sensor_pin = peripherals.gpio4.downgrade(); - - let tank_sensor = TankSensor::create( - one_wire_pin, - peripherals.adc1, - peripherals.gpio5, - tank_power_pin, - flow_sensor_pin, - peripherals.pcnt1, - )?; - - let mut sensor_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 34); - let sensor = match sensor_expander.pin_into_output(GPIOBank::Bank0, 0) { - Ok(_) => { - log::info!("SensorExpander answered"); - //pulse counter version - let mut signal_counter = PcntDriver::new( - peripherals.pcnt0, - Some(peripherals.gpio22), - Option::::None, - Option::::None, - Option::::None, - )?; - - signal_counter.channel_config( - PcntChannel::Channel0, - PinIndex::Pin0, - PinIndex::Pin1, - &PcntChannelConfig { - lctrl_mode: PcntControlMode::Keep, - hctrl_mode: PcntControlMode::Keep, - pos_mode: PcntCountMode::Increment, - neg_mode: PcntCountMode::Hold, - counter_h_lim: i16::MAX, - counter_l_lim: 0, - }, - )?; - - for pin in 0..8 { - let _ = sensor_expander.pin_into_output(GPIOBank::Bank0, pin); - let _ = sensor_expander.pin_into_output(GPIOBank::Bank1, pin); - let _ = sensor_expander.pin_set_low(GPIOBank::Bank0, pin); - let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin); - } - - SensorImpl::PulseCounter { - signal_counter, - sensor_expander, - } - } - Err(_) => { - log::info!("Can bus mode "); - let timing = can::config::Timing::B25K; - let config = can::config::Config::new().timing(timing); - let can = can::CanDriver::new(peripherals.can, peripherals.gpio0, peripherals.gpio2, &config).unwrap(); - - - let frame = StandardId::new(0x042).unwrap(); - let tx_frame = Frame::new(frame, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); - can.transmit(&tx_frame, 1000).unwrap(); - - if let Ok(rx_frame) = can.receive(1000) { - log::info!("rx {:}:", rx_frame); - } - //can bus version - SensorImpl::CanBus { - can - } - } - }; - - - - - let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?; - solar_is_day.set_pull(Pull::Floating)?; - - let mut light = PinDriver::input_output(peripherals.gpio10.downgrade())?; - light.set_pull(Pull::Floating)?; - - let mut charge_indicator = PinDriver::input_output(peripherals.gpio3.downgrade())?; - charge_indicator.set_pull(Pull::Floating)?; - charge_indicator.set_low()?; - - let mut pump_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 32); - for pin in 0..8 { - let _ = pump_expander.pin_into_output(GPIOBank::Bank0, pin); - let _ = pump_expander.pin_into_output(GPIOBank::Bank1, pin); - let _ = pump_expander.pin_set_low(GPIOBank::Bank0, pin); - let _ = pump_expander.pin_set_low(GPIOBank::Bank1, pin); - } - - - - let mppt_ina = SyncIna219::new( - MutexDevice::new(&I2C_DRIVER), - Address::from_pins(Pin::Vcc, Pin::Gnd), - ); - - let charger = match mppt_ina { - Ok(mut mppt_ina) => { - mppt_ina.set_configuration(Configuration { - reset: Default::default(), - bus_voltage_range: Default::default(), - shunt_voltage_range: Default::default(), - bus_resolution: Default::default(), - shunt_resolution: ina219::configuration::Resolution::Avg128, - operating_mode: Default::default(), - })?; - - Charger::SolarMpptV1 { - mppt_ina, - solar_is_day, - charge_indicator, - } - } - Err(_) => Charger::ErrorInit {}, - }; - - let pump_ina = match SyncIna219::new( - MutexDevice::new(&I2C_DRIVER), - Address::from_pins(Pin::Gnd, Pin::Sda), - ) { - Ok(pump_ina) => Some(pump_ina), - Err(err) => { - log::info!("Error creating pump ina: {:?}", err); - None - } - }; - - let v = V4 { - rtc_module, - esp, - awake, - tank_sensor, - light, - general_fault, - pump_ina, - pump_expander, - config, - battery_monitor, - charger, - extra1, - extra2, - sensor, - }; - Ok(Box::new(v)) -} - -impl<'a> BoardInteraction<'a> for V4<'a> { - fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> { - Some(&mut self.tank_sensor) - } - - fn get_esp(&mut self) -> &mut Esp<'a> { - &mut self.esp - } - - fn get_config(&mut self) -> &PlantControllerConfig { - &self.config - } - - fn get_battery_monitor(&mut self) -> &mut Box { - &mut self.battery_monitor - } - - fn get_rtc_module(&mut self) -> &mut Box { - &mut self.rtc_module - } - - fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> { - self.charger.set_charge_indicator(charging) - } - - fn deep_sleep(&mut self, duration_in_ms: u64) -> ! { - self.awake.set_low().unwrap(); - self.charger.power_save(); - deep_sleep(duration_in_ms); - } - - fn is_day(&self) -> bool { - self.charger.is_day() - } - - fn light(&mut self, enable: bool) -> anyhow::Result<()> { - unsafe { gpio_hold_dis(self.light.pin()) }; - self.light.set_state(enable.into())?; - unsafe { gpio_hold_en(self.light.pin()) }; - anyhow::Ok(()) - } - - fn pump(&mut self, plant: usize, enable: bool) -> anyhow::Result<()> { - if enable { - self.pump_expander - .pin_set_high(GPIOBank::Bank0, plant.try_into()?)?; - } else { - self.pump_expander - .pin_set_low(GPIOBank::Bank0, plant.try_into()?)?; - } - anyhow::Ok(()) - } - - fn pump_current(&mut self, _plant: usize) -> anyhow::Result { - //sensore is shared for all pumps, ignore plant id - match self.pump_ina.as_mut() { - None => { - bail!("pump current sensor not available"); - } - Some(pump_ina) => { - let v = pump_ina.shunt_voltage().map(|v| { - let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64); - let shut_value = Resistance::from_ohms(0.05_f64); - let current = shunt_voltage.as_volts() / shut_value.as_ohms(); - Current::from_amperes(current) - })?; - Ok(v) - } - } - } - - fn fault(&mut self, plant: usize, enable: bool) -> anyhow::Result<()> { - if enable { - self.pump_expander - .pin_set_high(GPIOBank::Bank1, plant.try_into()?)? - } else { - self.pump_expander - .pin_set_low(GPIOBank::Bank1, plant.try_into()?)? - } - anyhow::Ok(()) - } - - fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result { - self.sensor.measure_moisture_hz(plant, sensor) - } - - fn general_fault(&mut self, enable: bool) { - unsafe { gpio_hold_dis(self.general_fault.pin()) }; - self.general_fault.set_state(enable.into()).unwrap(); - unsafe { gpio_hold_en(self.general_fault.pin()) }; - } - - fn test(&mut self) -> anyhow::Result<()> { - self.general_fault(true); - self.esp.delay.delay_ms(100); - self.general_fault(false); - self.esp.delay.delay_ms(500); - self.light(true)?; - self.esp.delay.delay_ms(500); - self.light(false)?; - self.esp.delay.delay_ms(500); - for i in 0..PLANT_COUNT { - self.fault(i, true)?; - self.esp.delay.delay_ms(500); - self.fault(i, false)?; - self.esp.delay.delay_ms(500); - } - for i in 0..PLANT_COUNT { - self.pump(i, true)?; - self.esp.delay.delay_ms(100); - self.pump(i, false)?; - self.esp.delay.delay_ms(100); - } - for plant in 0..PLANT_COUNT { - let a = self.measure_moisture_hz(plant, Sensor::A); - let b = self.measure_moisture_hz(plant, Sensor::B); - let aa = match a { - OkStd(a) => a as u32, - Err(_) => u32::MAX, - }; - let bb = match b { - OkStd(b) => b as u32, - Err(_) => u32::MAX, - }; - log(LogMessage::TestSensor, aa, bb, &plant.to_string(), ""); - } - self.esp.delay.delay_ms(10); - anyhow::Ok(()) - } - - fn set_config(&mut self, config: PlantControllerConfig) -> anyhow::Result<()> { - self.config = config; - self.esp.save_config(&self.config)?; - anyhow::Ok(()) - } - - fn get_mptt_voltage(&mut self) -> anyhow::Result { - self.charger.get_mptt_voltage() - } - - fn get_mptt_current(&mut self) -> anyhow::Result { - self.charger.get_mptt_current() - } -} diff --git a/rust/scratch/water.rs b/rust/scratch/water.rs deleted file mode 100644 index 30f215d..0000000 --- a/rust/scratch/water.rs +++ /dev/null @@ -1,176 +0,0 @@ -use crate::hal::TANK_MULTI_SAMPLE; -use anyhow::{anyhow, bail}; -use ds18b20::Ds18b20; -use esp_idf_hal::adc::oneshot::config::AdcChannelConfig; -use esp_idf_hal::adc::oneshot::{AdcChannelDriver, AdcDriver}; -use esp_idf_hal::adc::{attenuation, Resolution, ADC1}; -use esp_idf_hal::delay::Delay; -use esp_idf_hal::gpio::{AnyIOPin, AnyInputPin, Gpio5, InputOutput, PinDriver, Pull}; -use esp_idf_hal::pcnt::{ - PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex, PCNT1, -}; -use esp_idf_sys::EspError; -use one_wire_bus::OneWire; - -pub struct TankSensor<'a> { - // one_wire_bus: OneWire>, - // tank_channel: AdcChannelDriver<'a, Gpio5, AdcDriver<'a, ADC1>>, - // tank_power: PinDriver<'a, AnyIOPin, InputOutput>, - // flow_counter: PcntDriver<'a>, - // delay: Delay, -} - -impl<'a> TankSensor<'a> { - pub(crate) fn create( - // one_wire_pin: AnyIOPin, - // adc1: ADC1, - // gpio5: Gpio5, - // tank_power_pin: AnyIOPin, - // flow_sensor_pin: AnyIOPin, - // pcnt1: PCNT1, - ) -> anyhow::Result> { - // let mut one_wire_pin = - // PinDriver::input_output_od(one_wire_pin).expect("Failed to configure pin"); - // one_wire_pin - // .set_pull(Pull::Floating) - // .expect("Failed to set pull"); - // - // let adc_config = AdcChannelConfig { - // attenuation: attenuation::DB_11, - // resolution: Resolution::Resolution12Bit, - // calibration: esp_idf_hal::adc::oneshot::config::Calibration::Curve, - // }; - // let tank_driver = AdcDriver::new(adc1).expect("Failed to configure ADC"); - // let tank_channel = AdcChannelDriver::new(tank_driver, gpio5, &adc_config) - // .expect("Failed to configure ADC channel"); - // - // let mut tank_power = - // PinDriver::input_output(tank_power_pin).expect("Failed to configure pin"); - // tank_power - // .set_pull(Pull::Floating) - // .expect("Failed to set pull"); - // - // let one_wire_bus = - // OneWire::new(one_wire_pin).expect("OneWire bus did not pull up after release"); - // - // let mut flow_counter = PcntDriver::new( - // pcnt1, - // Some(flow_sensor_pin), - // Option::::None, - // Option::::None, - // Option::::None, - // )?; - // - // flow_counter.channel_config( - // PcntChannel::Channel1, - // PinIndex::Pin0, - // PinIndex::Pin1, - // &PcntChannelConfig { - // lctrl_mode: PcntControlMode::Keep, - // hctrl_mode: PcntControlMode::Keep, - // pos_mode: PcntCountMode::Increment, - // neg_mode: PcntCountMode::Hold, - // counter_h_lim: i16::MAX, - // counter_l_lim: 0, - // }, - // )?; - // - // Ok(TankSensor { - // one_wire_bus, - // tank_channel, - // tank_power, - // flow_counter, - // delay: Default::default(), - // }) - bail!("Tank sensor not implemented"); - } - - pub fn reset_flow_meter(&mut self) { - // self.flow_counter.counter_pause().unwrap(); - // self.flow_counter.counter_clear().unwrap(); - } - - pub fn start_flow_meter(&mut self) { - //self.flow_counter.counter_resume().unwrap(); - } - - pub fn get_flow_meter_value(&mut self) -> i16 { - //self.flow_counter.get_counter_value().unwrap() - 5_i16 - } - - pub fn stop_flow_meter(&mut self) -> i16 { - //self.flow_counter.counter_pause().unwrap(); - self.get_flow_meter_value() - } - - pub async fn water_temperature_c(&mut self) -> anyhow::Result { - //multisample should be moved to water_temperature_c - let mut attempt = 1; - let water_temp: Result = loop { - let temp = self.single_temperature_c().await; - match &temp { - Ok(res) => { - log::info!("Water temp is {}", res); - break temp; - } - Err(err) => { - log::info!("Could not get water temp {} attempt {}", err, attempt) - } - } - if attempt == 5 { - break temp; - } - attempt += 1; - }; - water_temp - } - - async fn single_temperature_c(&mut self) -> anyhow::Result { - bail!("err"); - // self.one_wire_bus - // .reset(&mut self.delay) - // .map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?; - // let first = self.one_wire_bus.devices(false, &mut self.delay).next(); - // if first.is_none() { - // bail!("Not found any one wire Ds18b20"); - // } - // let device_address = first - // .unwrap() - // .map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?; - - // let water_temp_sensor = Ds18b20::new::(device_address) - // .map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?; - // - // water_temp_sensor - // .start_temp_measurement(&mut self.one_wire_bus, &mut self.delay) - // .map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?; - // ds18b20::Resolution::Bits12.delay_for_measurement_time(&mut self.delay); - // let sensor_data = water_temp_sensor - // .read_data(&mut self.one_wire_bus, &mut self.delay) - // .map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?; - // if sensor_data.temperature == 85_f32 { - // bail!("Ds18b20 dummy temperature returned"); - // } - //anyhow::Ok(sensor_data.temperature / 10_f32) - Ok(13_f32) - } - - pub async fn tank_sensor_voltage(&mut self) -> anyhow::Result { - // self.tank_power.set_high()?; - // //let stabilize - // self.delay.delay_ms(100); - // - // let mut store = [0_u16; TANK_MULTI_SAMPLE]; - // for multisample in 0..TANK_MULTI_SAMPLE { - // let value = self.tank_channel.read()?; - // store[multisample] = value; - // } - // self.tank_power.set_low()?; - // - // store.sort(); - // let median_mv = store[6] as f32 / 1000_f32; - let median_mv = 10_f32; - anyhow::Ok(median_mv) - } -} diff --git a/rust/src/FatError.rs b/rust/src/FatError.rs new file mode 100644 index 0000000..e8e25f3 --- /dev/null +++ b/rust/src/FatError.rs @@ -0,0 +1,152 @@ +use alloc::string::{String, ToString}; +use core::convert::Infallible; +use core::fmt; +use embassy_executor::SpawnError; +use embassy_sync::mutex::TryLockError; +use esp_wifi::wifi::WifiError; +use littlefs2_core::PathError; +use onewire::Error; + +//All error superconstruct +#[derive(Debug)] +pub enum FatError { + OneWireError { + error: Error, + }, + String { + error: String, + }, + LittleFSError { + error: littlefs2_core::Error, + }, + PathError { + error: PathError, + }, + TryLockError { + error: TryLockError, + }, + WifiError { + error: WifiError, + }, + SerdeError { + error: serde_json::Error, + }, + PreconditionFailed { + error: String, + }, + NoBatteryMonitor, + SpawnError { + error: SpawnError, + }, + PartitionError { + error: esp_bootloader_esp_idf::partitions::Error, + }, +} + +pub type FatResult = Result; + +impl fmt::Display for FatError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + FatError::SpawnError { error } => { + write!(f, "SpawnError {:?}", error.to_string()) + } + FatError::OneWireError { error } => write!(f, "OneWireError {:?}", error), + FatError::String { error } => write!(f, "{}", error), + FatError::LittleFSError { error } => write!(f, "LittleFSError {:?}", error), + FatError::PathError { error } => write!(f, "PathError {:?}", error), + FatError::TryLockError { error } => write!(f, "TryLockError {:?}", error), + FatError::WifiError { error } => write!(f, "WifiError {:?}", error), + FatError::SerdeError { error } => write!(f, "SerdeError {:?}", error), + FatError::PreconditionFailed { error } => write!(f, "PreconditionFailed {:?}", error), + FatError::PartitionError { error } => { + write!(f, "PartitionError {:?}", error) + } + FatError::NoBatteryMonitor => { + write!(f, "No Battery Monitor") + } + } + } +} + +#[macro_export] +macro_rules! bail { + ($msg:literal $(,)?) => { + return $crate::FatError::fat_bail($msg) + }; + ($fmt:literal, $($arg:tt)*) => { + return $crate::FatError::fat_bail(&alloc::format!($fmt, $($arg)*)) + }; +} + +pub fn fat_bail(message: &str) -> Result { + Err(FatError::String { + error: message.to_string(), + }) +} + +pub trait ContextExt { + fn context(self, context: C) -> Result + where + C: AsRef; +} +impl ContextExt for Option { + fn context(self, context: C) -> Result + where + C: AsRef, + { + match self { + Some(value) => Ok(value), + None => Err(FatError::PreconditionFailed { + error: context.as_ref().to_string(), + }), + } + } +} + +impl From> for FatError { + fn from(error: Error) -> Self { + FatError::OneWireError { error } + } +} +impl From for FatError { + fn from(value: littlefs2_core::Error) -> Self { + FatError::LittleFSError { error: value } + } +} + +impl From for FatError { + fn from(value: PathError) -> Self { + FatError::PathError { error: value } + } +} + +impl From for FatError { + fn from(value: TryLockError) -> Self { + FatError::TryLockError { error: value } + } +} + +impl From for FatError { + fn from(value: WifiError) -> Self { + FatError::WifiError { error: value } + } +} + +impl From for FatError { + fn from(value: serde_json::Error) -> Self { + FatError::SerdeError { error: value } + } +} + +impl From for FatError { + fn from(value: SpawnError) -> Self { + FatError::SpawnError { error: value } + } +} + +impl From for FatError { + fn from(value: esp_bootloader_esp_idf::partitions::Error) -> Self { + FatError::PartitionError { error: value } + } +} diff --git a/rust/src/hal/battery.rs b/rust/src/hal/battery.rs index f096350..ba321b5 100644 --- a/rust/src/hal/battery.rs +++ b/rust/src/hal/battery.rs @@ -1,27 +1,20 @@ -use crate::hal::Box; +use crate::FatError::{FatError, FatResult}; use alloc::string::String; use async_trait::async_trait; -use core::error::Error; use serde::Serialize; #[async_trait] pub trait BatteryInteraction { - async fn state_charge_percent(&mut self) -> Result; - async fn remaining_milli_ampere_hour(&mut self) -> Result; - async fn max_milli_ampere_hour(&mut self) -> Result; - async fn design_milli_ampere_hour(&mut self) -> Result; - async fn voltage_milli_volt(&mut self) -> Result; - async fn average_current_milli_ampere(&mut self) -> Result; - async fn cycle_count(&mut self) -> Result; - async fn state_health_percent(&mut self) -> Result; - async fn bat_temperature(&mut self) -> Result; - async fn get_battery_state(&mut self) -> Result; -} - -impl From for anyhow::Error { - fn from(err: BatteryError) -> Self { - anyhow::anyhow!(err) - } + async fn state_charge_percent(&mut self) -> FatResult; + async fn remaining_milli_ampere_hour(&mut self) -> FatResult; + async fn max_milli_ampere_hour(&mut self) -> FatResult; + async fn design_milli_ampere_hour(&mut self) -> FatResult; + async fn voltage_milli_volt(&mut self) -> FatResult; + async fn average_current_milli_ampere(&mut self) -> FatResult; + async fn cycle_count(&mut self) -> FatResult; + async fn state_health_percent(&mut self) -> FatResult; + async fn bat_temperature(&mut self) -> FatResult; + async fn get_battery_state(&mut self) -> FatResult; } #[derive(Debug, Serialize)] @@ -60,43 +53,43 @@ pub enum BatteryState { pub struct NoBatteryMonitor {} #[async_trait] impl BatteryInteraction for NoBatteryMonitor { - async fn state_charge_percent(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn state_charge_percent(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn remaining_milli_ampere_hour(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn remaining_milli_ampere_hour(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn max_milli_ampere_hour(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn max_milli_ampere_hour(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn design_milli_ampere_hour(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn design_milli_ampere_hour(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn voltage_milli_volt(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn voltage_milli_volt(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn average_current_milli_ampere(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn average_current_milli_ampere(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn cycle_count(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn cycle_count(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn state_health_percent(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn state_health_percent(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn bat_temperature(&mut self) -> Result { - Err(BatteryError::NoBatteryMonitor) + async fn bat_temperature(&mut self) -> FatResult { + Err(FatError::NoBatteryMonitor) } - async fn get_battery_state(&mut self) -> Result { + async fn get_battery_state(&mut self) -> FatResult { Ok(BatteryState::Unknown) } } diff --git a/rust/src/hal/esp.rs b/rust/src/hal/esp.rs index 5a49049..1bca222 100644 --- a/rust/src/hal/esp.rs +++ b/rust/src/hal/esp.rs @@ -1,33 +1,31 @@ use crate::config::{NetworkConfig, PlantControllerConfig}; use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT, TIME_ACCESS}; -use crate::log::{ LogArray, LogMessage, LOG_ACCESS}; -use crate::STAY_ALIVE; -use anyhow::{anyhow, bail, Context}; -use chrono::{DateTime, FixedOffset, Utc}; +use crate::log::{LogMessage, LOG_ACCESS}; +use crate::{bail, STAY_ALIVE}; +use chrono::{DateTime, Utc}; use serde::Serialize; use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem; +use crate::FatError::{ContextExt, FatError, FatResult}; use alloc::string::ToString; use alloc::sync::Arc; use alloc::{format, string::String, vec::Vec}; use core::marker::PhantomData; use core::net::{IpAddr, Ipv4Addr}; use core::str::FromStr; -use embassy_executor::{Spawner}; +use embassy_executor::Spawner; use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::{Duration, Instant, Timer}; +use embassy_time::{Duration, Timer}; use embedded_storage::nor_flash::ReadNorFlash; -use embedded_storage::Storage; -use esp_bootloader_esp_idf::ota::{Ota, OtaImageState, Slot}; -use esp_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable}; +use esp_bootloader_esp_idf::ota::{Ota, OtaImageState}; +use esp_bootloader_esp_idf::partitions::FlashRegion; use esp_hal::gpio::Input; use esp_hal::rng::Rng; -use esp_hal::rtc_cntl::Rtc; use esp_hal::rtc_cntl::sleep::RtcSleepConfig; use esp_hal::system::software_reset; -use esp_println::{println}; +use esp_println::println; use esp_storage::FlashStorage; use esp_wifi::wifi::{ AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig, @@ -35,7 +33,7 @@ use esp_wifi::wifi::{ }; use littlefs2::fs::Filesystem; use littlefs2_core::{DynFile, FileType, PathBuf, SeekFrom}; -use log::{info}; +use log::info; #[esp_hal::ram(rtc_fast, persistent)] static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT]; @@ -113,12 +111,10 @@ macro_rules! mk_static { } impl Esp<'_> { - pub(crate) async fn delete_file(&self, filename: String) -> anyhow::Result<()> { + pub(crate) async fn delete_file(&self, filename: String) -> FatResult<()> { let file = PathBuf::try_from(filename.as_str()).unwrap(); let access = self.fs.lock().await; - access - .remove(&*file) - .map_err(|err| anyhow!("Could not delete file: {:?}", err))?; + access.remove(&*file)?; Ok(()) } pub(crate) async fn write_file( @@ -126,11 +122,10 @@ impl Esp<'_> { filename: String, offset: u32, buf: &[u8], - ) -> anyhow::Result<()> { - let file = PathBuf::try_from(filename.as_str()).unwrap(); + ) -> Result<(), FatError> { + let file = PathBuf::try_from(filename.as_str())?; let access = self.fs.lock().await; - info!("write file {} at offset {}", filename, offset); - match access.open_file_with_options_and_then( + access.open_file_with_options_and_then( |options| options.read(true).write(true).create(true), &*file, |file| { @@ -138,51 +133,45 @@ impl Esp<'_> { file.write(buf)?; Ok(()) }, - ) { - Ok(_) => Ok(()), - Err(err) => { - bail!(format!("{err:?}")) - } - } + )?; + Ok(()) + } + + pub async fn get_size(&mut self, filename: String) -> FatResult { + let file = PathBuf::try_from(filename.as_str())?; + let access = self.fs.lock().await; + let data = access.metadata(&*file)?; + Ok(data.len()) } pub(crate) async fn get_file( &mut self, filename: String, chunk: u32, - ) -> anyhow::Result<([u8; 128], usize)> { + ) -> FatResult<([u8; 512], usize)> { use littlefs2::io::Error as lfs2Error; - let file = PathBuf::try_from(filename.as_str()).unwrap(); + let file = PathBuf::try_from(filename.as_str())?; let access = self.fs.lock().await; - let mut buf = [0_u8; 128]; + let mut buf = [0_u8; 512]; let mut read = 0; - let offset = chunk * 128; - info!("read file {} at offset {}", filename, offset); - match access.open_file_with_options_and_then( + let offset = chunk * buf.len() as u32; + access.open_file_with_options_and_then( |options| options.read(true), &*file, |file| { let length = file.len()? as u32; - info!("file length {}", length); if length == 0 { Err(lfs2Error::IO) } else if length > offset { file.seek(SeekFrom::Start(offset))?; - info!("seek to {}", offset); read = file.read(&mut buf)?; - info!("read {} bytes", read); Ok(()) } else { //exactly at end, do nothing Ok(()) } }, - ) { - Ok(_) => {} - Err(err) => { - bail!(format!("{err:?}")) - } - } + )?; Ok((buf, read)) } @@ -219,7 +208,7 @@ impl Esp<'_> { pub(crate) fn mode_override_pressed(&mut self) -> bool { self.boot_button.is_low() } - pub(crate) async fn sntp(&mut self, _max_wait_ms: u32) -> anyhow::Result> { + pub(crate) async fn sntp(&mut self, _max_wait_ms: u32) -> FatResult> { //let sntp = sntp::EspSntp::new_default()?; //let mut counter = 0; //while sntp.get_sync_status() != SyncStatus::Completed { @@ -233,19 +222,15 @@ impl Esp<'_> { todo!(); } - pub async fn flash_ota(&mut self) -> anyhow::Result<()> { + pub async fn flash_ota(&mut self) -> FatResult<()> { let capacity = self.ota_next.capacity(); bail!("not implemented") } - - pub(crate) async fn wifi_scan(&mut self) -> anyhow::Result> { + pub(crate) async fn wifi_scan(&mut self) -> FatResult> { info!("start wifi scan"); - let mut lock = self - .controller - .try_lock() - .map_err(|_| anyhow!("Could not lock wifi controller, currently in use"))?; + let mut lock = self.controller.try_lock()?; info!("start wifi scan lock"); let scan_config = ScanConfig { ssid: None, @@ -254,10 +239,7 @@ impl Esp<'_> { show_hidden: false, scan_type: ScanTypeConfig::Passive(core::time::Duration::from_secs(2)), }; - let rv = lock - .scan_with_config_async(scan_config) - .await - .map_err(|err| anyhow!("Could not scan wifi: {:?}", err))?; + let rv = lock.scan_with_config_async(scan_config).await?; info!("end wifi scan lock"); Ok(rv) } @@ -294,7 +276,7 @@ impl Esp<'_> { unsafe { CONSECUTIVE_WATERING_PLANT[plant] } } pub(crate) fn get_restart_to_conf(&mut self) -> bool { - unsafe { RESTART_TO_CONF == 1} + unsafe { RESTART_TO_CONF == 1 } } pub(crate) fn set_restart_to_conf(&mut self, to_conf: bool) { unsafe { @@ -306,7 +288,7 @@ impl Esp<'_> { } } - pub(crate) async fn wifi_ap(&mut self) -> anyhow::Result> { + pub(crate) async fn wifi_ap(&mut self) -> FatResult> { let ssid = match self.load_config().await { Ok(config) => config.network.ap_ssid.as_str().to_string(), Err(_) => "PlantCtrl Emergency Mode".to_string(), @@ -358,7 +340,7 @@ impl Esp<'_> { .config_v4() .inspect(|c| println!("ipv4 config: {c:?}")); - anyhow::Ok(stack.clone()) + Ok(stack.clone()) } pub async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! { @@ -376,7 +358,6 @@ impl Esp<'_> { if duration_in_ms == 0 { software_reset(); } else { - loop { info!("todo deepsleep") } @@ -390,11 +371,19 @@ impl Esp<'_> { //}; } - pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> anyhow::Result { - let _ssid = network_config - .ssid - .clone() - .ok_or(anyhow!("No ssid configured"))?; + pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> FatResult { + let _ssid = network_config.ssid.clone(); + match &_ssid { + Some(ssid) => { + if ssid.is_empty() { + bail!("Wifi ssid was empty") + } + } + None => { + bail!("Wifi ssid was empty") + } + } + let _ssid = _ssid.unwrap(); let _password = network_config.password.clone(); let _max_wait = network_config.max_wait; bail!("todo") @@ -452,59 +441,32 @@ impl Esp<'_> { // log(LogMessage::WifiInfo, 0, 0, "", &format!("{address:?}")); // anyhow::Ok(address) } - pub(crate) async fn load_config(&mut self) -> anyhow::Result { + pub(crate) async fn load_config(&mut self) -> FatResult { let cfg = PathBuf::try_from(CONFIG_FILE).unwrap(); - match self.fs.lock().await.read::<4096>(&cfg) { - Ok(data) => { - let config: PlantControllerConfig = serde_json::from_slice(&data)?; - anyhow::Ok(config) - } - Err(err) => { - bail!(format!("{err:?}")) - } - } + let data = self.fs.lock().await.read::<4096>(&cfg)?; + let config: PlantControllerConfig = serde_json::from_slice(&data)?; + return Ok(config); } - pub(crate) async fn save_config(&mut self, config: Vec) -> anyhow::Result<()> { + pub(crate) async fn save_config(&mut self, config: Vec) -> FatResult<()> { let filesystem = self.fs.lock().await; - let cfg = PathBuf::try_from(CONFIG_FILE).unwrap(); - - match filesystem.write(&cfg, &*config) { - Ok(_) => {} - Err(err) => { - bail!(format!("{err:?}")) - } - } - anyhow::Ok(()) + let cfg = PathBuf::try_from(CONFIG_FILE)?; + filesystem.write(&cfg, &*config)?; + Ok(()) } - async fn file_system_size(&mut self) -> anyhow::Result { - bail!("fail"); - // let storage = CString::new(Self::SPIFFS_PARTITION_NAME)?; - // let mut total_size = 0; - // let mut used_size = 0; - // unsafe { - // esp_idf_sys::esp!(esp_spiffs_info( - // storage.as_ptr(), - // &mut total_size, - // &mut used_size - // ))?; - // } - // anyhow::Ok(FileSystemSizeInfo { - // total_size, - // used_size, - // free_size: total_size - used_size, - // }) - } - - pub(crate) async fn list_files(&self) -> anyhow::Result { + pub(crate) async fn list_files(&self) -> FatResult { let path = PathBuf::new(); + let fs = self.fs.lock().await; + let free_size = fs.available_space()?; + let total_size = fs.total_space(); + let mut result = FileList { - total: 0, - used: 0, + total: total_size, + used: total_size - free_size, files: Vec::new(), }; - match self.fs.lock().await.read_dir_and_then(&path, |dir| { + fs.read_dir_and_then(&path, |dir| { for entry in dir { let e = entry?; if e.file_type() == FileType::File { @@ -514,29 +476,11 @@ impl Esp<'_> { }); } } - Result::Ok(()) - }) { - Ok(_) => {} - Err(err) => { - bail!(format!("{err:?}")) - } - } + Ok(()) + })?; Ok(result) } - // pub(crate) async fn get_file_handle( - // &self, - // filename: &str, - // write: bool, - // ) -> anyhow::Result { - // let filepath = Path::new(Self::BASE_PATH).join(Path::new(filename)); - // anyhow::Ok(if write { - // File::create(filepath)? - // } else { - // File::open(filepath)? - // }) - // } - pub(crate) async fn init_rtc_deepsleep_memory( &self, init_rtc_store: bool, @@ -558,22 +502,28 @@ impl Esp<'_> { if to_config_mode { RESTART_TO_CONF = 1; } - LOG_ACCESS.lock().await.log( - LogMessage::RestartToConfig, - RESTART_TO_CONF as u32, - 0, - "", - "", - ).await - ; - LOG_ACCESS.lock().await.log( - LogMessage::LowVoltage, - LOW_VOLTAGE_DETECTED as u32, - 0, - "", - "", - ).await - ; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::RestartToConfig, + RESTART_TO_CONF as u32, + 0, + "", + "", + ) + .await; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::LowVoltage, + LOW_VOLTAGE_DETECTED as u32, + 0, + "", + "", + ) + .await; for i in 0..PLANT_COUNT { log::info!( "LAST_WATERING_TIMESTAMP[{}] = UTC {}", @@ -592,7 +542,7 @@ impl Esp<'_> { } } - pub(crate) async fn mqtt(&mut self, network_config: &NetworkConfig) -> anyhow::Result<()> { + pub(crate) async fn mqtt(&mut self, network_config: &NetworkConfig) -> FatResult<()> { let base_topic = network_config .base_topic .as_ref() @@ -756,11 +706,7 @@ impl Esp<'_> { // } // bail!("Mqtt did not fire connection callback in time"); } - pub(crate) async fn mqtt_publish( - &mut self, - _subtopic: &str, - _message: &[u8], - ) -> anyhow::Result<()> { + pub(crate) async fn mqtt_publish(&mut self, _subtopic: &str, _message: &[u8]) -> FatResult<()> { bail!("todo"); // // if self.mqtt_client.is_none() { diff --git a/rust/src/hal/initial_hal.rs b/rust/src/hal/initial_hal.rs index 54155ee..1ca9246 100644 --- a/rust/src/hal/initial_hal.rs +++ b/rust/src/hal/initial_hal.rs @@ -3,16 +3,17 @@ use crate::hal::rtc::{BackupHeader, RTCModuleInteraction}; use alloc::vec::Vec; //use crate::hal::water::TankSensor; use crate::alloc::boxed::Box; +use crate::hal::water::TankSensor; use crate::hal::{BoardInteraction, FreePeripherals, Sensor}; +use crate::FatError::FatError; use crate::{ + bail, config::PlantControllerConfig, hal::battery::{BatteryInteraction, NoBatteryMonitor}, }; -use anyhow::{bail, Result}; use async_trait::async_trait; use chrono::{DateTime, Utc}; use esp_hal::gpio::{Level, Output, OutputConfig}; -use log::info; use measurements::{Current, Voltage}; pub struct Initial<'a> { @@ -23,27 +24,27 @@ pub struct Initial<'a> { pub rtc: Box, } -struct NoRTC {} +pub(crate) struct NoRTC {} #[async_trait] impl RTCModuleInteraction for NoRTC { - async fn get_backup_info(&mut self) -> Result { + async fn get_backup_info(&mut self) -> Result { bail!("Please configure board revision") } - async fn get_backup_config(&mut self) -> Result> { + async fn get_backup_config(&mut self) -> Result, FatError> { bail!("Please configure board revision") } - async fn backup_config(&mut self, _bytes: &[u8]) -> Result<()> { + async fn backup_config(&mut self, _bytes: &[u8]) -> Result<(), FatError> { bail!("Please configure board revision") } - async fn get_rtc_time(&mut self) -> Result> { + async fn get_rtc_time(&mut self) -> Result, FatError> { bail!("Please configure board revision") } - async fn set_rtc_time(&mut self, _time: &DateTime) -> Result<()> { + async fn set_rtc_time(&mut self, _time: &DateTime) -> Result<(), FatError> { bail!("Please configure board revision") } } @@ -52,7 +53,7 @@ pub(crate) fn create_initial_board( free_pins: FreePeripherals<'static>, config: PlantControllerConfig, esp: Esp<'static>, -) -> Result + Send>> { +) -> Result + Send>, FatError> { log::info!("Start initial"); let general_fault = Output::new(free_pins.gpio23, Level::Low, OutputConfig::default()); let v = Initial { @@ -67,9 +68,9 @@ pub(crate) fn create_initial_board( #[async_trait] impl<'a> BoardInteraction<'a> for Initial<'a> { - // fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> { - // None - // } + fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> { + bail!("Please configure board revision") + } fn get_esp(&mut self) -> &mut Esp<'a> { &mut self.esp @@ -87,7 +88,7 @@ impl<'a> BoardInteraction<'a> for Initial<'a> { &mut self.rtc } - fn set_charge_indicator(&mut self, _charging: bool) -> Result<()> { + fn set_charge_indicator(&mut self, _charging: bool) -> Result<(), FatError> { bail!("Please configure board revision") } @@ -97,23 +98,27 @@ impl<'a> BoardInteraction<'a> for Initial<'a> { fn is_day(&self) -> bool { false } - fn light(&mut self, _enable: bool) -> Result<()> { + fn light(&mut self, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } - async fn pump(&mut self, _plant: usize, _enable: bool) -> Result<()> { + async fn pump(&mut self, _plant: usize, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } - async fn pump_current(&mut self, _plant: usize) -> Result { + async fn pump_current(&mut self, _plant: usize) -> Result { bail!("Please configure board revision") } - async fn fault(&mut self, _plant: usize, _enable: bool) -> Result<()> { + async fn fault(&mut self, _plant: usize, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } - async fn measure_moisture_hz(&mut self, _plant: usize, _sensor: Sensor) -> Result { + async fn measure_moisture_hz( + &mut self, + _plant: usize, + _sensor: Sensor, + ) -> Result { bail!("Please configure board revision") } @@ -121,7 +126,7 @@ impl<'a> BoardInteraction<'a> for Initial<'a> { self.general_fault.set_level(enable.into()); } - async fn test(&mut self) -> Result<()> { + async fn test(&mut self) -> Result<(), FatError> { bail!("Please configure board revision") } @@ -129,11 +134,11 @@ impl<'a> BoardInteraction<'a> for Initial<'a> { self.config = config; } - async fn get_mptt_voltage(&mut self) -> Result { + async fn get_mptt_voltage(&mut self) -> Result { bail!("Please configure board revision") } - async fn get_mptt_current(&mut self) -> Result { + async fn get_mptt_current(&mut self) -> Result { bail!("Please configure board revision") } } diff --git a/rust/src/hal/little_fs2storage_adapter.rs b/rust/src/hal/little_fs2storage_adapter.rs index 59f197b..41e660a 100644 --- a/rust/src/hal/little_fs2storage_adapter.rs +++ b/rust/src/hal/little_fs2storage_adapter.rs @@ -4,10 +4,9 @@ use esp_storage::FlashStorage; use littlefs2::consts::U512 as lfsCache; use littlefs2::consts::U512 as lfsLookahead; use littlefs2::driver::Storage as lfs2Storage; -use littlefs2::fs::Filesystem as lfs2Filesystem; use littlefs2::io::Error as lfs2Error; use littlefs2::io::Result as lfs2Result; -use log::{error, info}; +use log::error; pub struct LittleFs2Filesystem { pub(crate) storage: &'static mut FlashRegion<'static, FlashStorage>, @@ -27,7 +26,7 @@ impl lfs2Storage for LittleFs2Filesystem { assert_eq!(off % read_size, 0); assert_eq!(buf.len() % read_size, 0); match self.storage.read(off as u32, buf) { - anyhow::Result::Ok(..) => lfs2Result::Ok(buf.len()), + Ok(..) => Ok(buf.len()), Err(err) => { error!("Littlefs2Filesystem read error: {:?}", err); Err(lfs2Error::IO) @@ -36,16 +35,11 @@ impl lfs2Storage for LittleFs2Filesystem { } fn write(&mut self, off: usize, data: &[u8]) -> lfs2Result { - info!( - "Littlefs2Filesystem write at offset {} with len {}", - off, - data.len() - ); let write_size: usize = Self::WRITE_SIZE; assert_eq!(off % write_size, 0); assert_eq!(data.len() % write_size, 0); match self.storage.write(off as u32, data) { - anyhow::Result::Ok(..) => lfs2Result::Ok(data.len()), + Ok(..) => Ok(data.len()), Err(err) => { error!("Littlefs2Filesystem write error: {:?}", err); Err(lfs2Error::IO) @@ -54,10 +48,6 @@ impl lfs2Storage for LittleFs2Filesystem { } fn erase(&mut self, off: usize, len: usize) -> lfs2Result { - info!( - "Littlefs2Filesystem erase at offset {} with len {}", - off, len - ); let block_size: usize = Self::BLOCK_SIZE; debug_assert!(off % block_size == 0); debug_assert!(len % block_size == 0); diff --git a/rust/src/hal/mod.rs b/rust/src/hal/mod.rs index 09a585f..baa4775 100644 --- a/rust/src/hal/mod.rs +++ b/rust/src/hal/mod.rs @@ -3,28 +3,55 @@ pub mod esp; mod initial_hal; mod little_fs2storage_adapter; mod rtc; +mod v4_hal; +mod water; //mod water; use crate::alloc::string::ToString; use crate::hal::rtc::RTCModuleInteraction; use esp_hal::peripherals::Peripherals; +use esp_hal::peripherals::GPIO0; +use esp_hal::peripherals::GPIO1; +use esp_hal::peripherals::GPIO10; +use esp_hal::peripherals::GPIO11; +use esp_hal::peripherals::GPIO12; +use esp_hal::peripherals::GPIO13; +use esp_hal::peripherals::GPIO14; +use esp_hal::peripherals::GPIO15; +use esp_hal::peripherals::GPIO16; +use esp_hal::peripherals::GPIO17; +use esp_hal::peripherals::GPIO18; +use esp_hal::peripherals::GPIO2; +use esp_hal::peripherals::GPIO21; +use esp_hal::peripherals::GPIO22; use esp_hal::peripherals::GPIO23; +use esp_hal::peripherals::GPIO24; +use esp_hal::peripherals::GPIO25; +use esp_hal::peripherals::GPIO26; +use esp_hal::peripherals::GPIO27; +use esp_hal::peripherals::GPIO28; +use esp_hal::peripherals::GPIO29; +use esp_hal::peripherals::GPIO3; +use esp_hal::peripherals::GPIO30; +use esp_hal::peripherals::GPIO4; +use esp_hal::peripherals::GPIO5; use esp_hal::peripherals::GPIO6; +use esp_hal::peripherals::GPIO7; +use esp_hal::peripherals::GPIO8; //use crate::hal::water::TankSensor; use crate::{ + bail, config::{BatteryBoardVersion, BoardVersion, PlantControllerConfig}, hal::{ battery::{BatteryInteraction, NoBatteryMonitor}, esp::Esp, }, - log::{LogMessage}, + log::LogMessage, }; use alloc::boxed::Box; use alloc::format; use alloc::sync::Arc; -use core::cell::OnceCell; -use anyhow::{bail, Ok, Result}; use async_trait::async_trait; use chrono::{DateTime, FixedOffset, Utc}; use embassy_executor::Spawner; @@ -39,6 +66,9 @@ use esp_hal::gpio::{Input, InputConfig, Pull}; use measurements::{Current, Voltage}; use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem; +use crate::hal::water::TankSensor; +use crate::log::LOG_ACCESS; +use crate::FatError::FatError; use embassy_sync::mutex::Mutex; use embassy_sync::once_lock::OnceLock; use esp_alloc as _; @@ -53,7 +83,6 @@ use esp_wifi::{init, EspWifiController}; use littlefs2::fs::{Allocation, Filesystem as lfs2Filesystem}; use littlefs2::object_safe::DynStorage; use log::{info, warn}; -use crate::log::{LogArray, LOG_ACCESS}; pub static TIME_ACCESS: OnceLock = OnceLock::new(); @@ -78,26 +107,26 @@ pub struct HAL<'a> { #[async_trait] pub trait BoardInteraction<'a> { - //fn get_tank_sensor(&mut self) -> Option<&mut TankSensor>; + fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError>; fn get_esp(&mut self) -> &mut Esp<'a>; fn get_config(&mut self) -> &PlantControllerConfig; fn get_battery_monitor(&mut self) -> &mut Box; fn get_rtc_module(&mut self) -> &mut Box; - fn set_charge_indicator(&mut self, charging: bool) -> Result<()>; + fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError>; async fn deep_sleep(&mut self, duration_in_ms: u64) -> !; fn is_day(&self) -> bool; //should be multsampled - fn light(&mut self, enable: bool) -> Result<()>; - async fn pump(&mut self, plant: usize, enable: bool) -> Result<()>; - async fn pump_current(&mut self, plant: usize) -> Result; - async fn fault(&mut self, plant: usize, enable: bool) -> Result<()>; - async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result; + fn light(&mut self, enable: bool) -> Result<(), FatError>; + async fn pump(&mut self, plant: usize, enable: bool) -> Result<(), FatError>; + async fn pump_current(&mut self, plant: usize) -> Result; + async fn fault(&mut self, plant: usize, enable: bool) -> Result<(), FatError>; + async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result; async fn general_fault(&mut self, enable: bool); - async fn test(&mut self) -> Result<()>; + async fn test(&mut self) -> Result<(), FatError>; fn set_config(&mut self, config: PlantControllerConfig); - async fn get_mptt_voltage(&mut self) -> anyhow::Result; - async fn get_mptt_current(&mut self) -> anyhow::Result; + async fn get_mptt_voltage(&mut self) -> Result; + async fn get_mptt_current(&mut self) -> Result; } impl dyn BoardInteraction<'_> { @@ -119,36 +148,36 @@ impl dyn BoardInteraction<'_> { #[allow(dead_code)] pub struct FreePeripherals<'a> { - // pub gpio0: Gpio0, - // pub gpio1: Gpio1, - // pub gpio2: Gpio2, - // pub gpio3: Gpio3, - // pub gpio4: Gpio4, - // pub gpio5: Gpio5, + pub gpio0: GPIO0<'a>, + pub gpio1: GPIO1<'a>, + pub gpio2: GPIO2<'a>, + pub gpio3: GPIO3<'a>, + pub gpio4: GPIO4<'a>, + pub gpio5: GPIO5<'a>, pub gpio6: GPIO6<'a>, - // pub gpio7: Gpio7, - // pub gpio8: Gpio8, + pub gpio7: GPIO7<'a>, + pub gpio8: GPIO8<'a>, // //config button here - // pub gpio10: Gpio10, - // pub gpio11: Gpio11, - // pub gpio12: Gpio12, - // pub gpio13: Gpio13, - // pub gpio14: Gpio14, - // pub gpio15: Gpio15, - // pub gpio16: Gpio16, - // pub gpio17: Gpio17, - // pub gpio18: Gpio18, + pub gpio10: GPIO10<'a>, + pub gpio11: GPIO11<'a>, + pub gpio12: GPIO12<'a>, + pub gpio13: GPIO13<'a>, + pub gpio14: GPIO14<'a>, + pub gpio15: GPIO15<'a>, + pub gpio16: GPIO16<'a>, + pub gpio17: GPIO17<'a>, + pub gpio18: GPIO18<'a>, // //i2c here - // pub gpio21: Gpio21, - // pub gpio22: Gpio22, + pub gpio21: GPIO21<'a>, + pub gpio22: GPIO22<'a>, pub gpio23: GPIO23<'a>, - // pub gpio24: Gpio24, - // pub gpio25: Gpio25, - // pub gpio26: Gpio26, - // pub gpio27: Gpio27, - // pub gpio28: Gpio28, - // pub gpio29: Gpio29, - // pub gpio30: Gpio30, + pub gpio24: GPIO24<'a>, + pub gpio25: GPIO25<'a>, + pub gpio26: GPIO26<'a>, + pub gpio27: GPIO27<'a>, + pub gpio28: GPIO28<'a>, + pub gpio29: GPIO29<'a>, + pub gpio30: GPIO30<'a>, // pub pcnt0: PCNT0, // pub pcnt1: PCNT1, // pub adc1: ADC1, @@ -183,7 +212,9 @@ impl PlantHal { // Mutex::new(I2cDriver::new(i2c, sda, scl, &config).unwrap()) // } - pub async fn create(spawner: Spawner) -> Result>> { + pub async fn create( + spawner: Spawner, + ) -> Result>, FatError> { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals: Peripherals = esp_hal::init(config); @@ -191,7 +222,7 @@ impl PlantHal { esp_alloc::heap_allocator!(#[link_section = ".dram2_uninit"] size: 64000); let rtc: Rtc = Rtc::new(peripherals.LPWR); - match(TIME_ACCESS.init(rtc)){ + match (TIME_ACCESS.init(rtc)) { Result::Ok(_) => {} Err(_) => {} } @@ -223,36 +254,35 @@ impl PlantHal { // adc1: peripherals.adc1, // pcnt0: peripherals.pcnt0, // pcnt1: peripherals.pcnt1, - // gpio0: peripherals.pins.gpio0, - // gpio1: peripherals.pins.gpio1, - // gpio2: peripherals.pins.gpio2, - // gpio3: peripherals.pins.gpio3, - // gpio4: peripherals.pins.gpio4, - // gpio5: peripherals.pins.gpio5, + gpio0: peripherals.GPIO0, + gpio1: peripherals.GPIO1, + gpio2: peripherals.GPIO2, + gpio3: peripherals.GPIO3, + gpio4: peripherals.GPIO4, + gpio5: peripherals.GPIO5, gpio6: peripherals.GPIO6, - // gpio7: peripherals.pins.gpio7, - // gpio8: peripherals.pins.gpio8, - // gpio10: peripherals.pins.gpio10, - // gpio11: peripherals.pins.gpio11, - // gpio12: peripherals.pins.gpio12, - // gpio13: peripherals.pins.gpio13, - // gpio14: peripherals.pins.gpio14, - // gpio15: peripherals.pins.gpio15, - // gpio16: peripherals.pins.gpio16, - // gpio17: peripherals.pins.gpio17, - // gpio18: peripherals.pins.gpio18, - // gpio21: peripherals.pins.gpio21, - // gpio22: peripherals.pins.gpio22, + gpio7: peripherals.GPIO7, + gpio8: peripherals.GPIO8, + gpio10: peripherals.GPIO10, + gpio11: peripherals.GPIO11, + gpio12: peripherals.GPIO12, + gpio13: peripherals.GPIO13, + gpio14: peripherals.GPIO14, + gpio15: peripherals.GPIO15, + gpio16: peripherals.GPIO16, + gpio17: peripherals.GPIO17, + gpio18: peripherals.GPIO18, + gpio21: peripherals.GPIO21, + gpio22: peripherals.GPIO22, gpio23: peripherals.GPIO23, - // gpio24: peripherals.pins.gpio24, - // gpio25: peripherals.pins.gpio25, - // gpio26: peripherals.pins.gpio26, - // gpio27: peripherals.pins.gpio27, - // gpio28: peripherals.pins.gpio28, - // gpio29: peripherals.pins.gpio29, - // gpio30: peripherals.pins.gpio30, + gpio24: peripherals.GPIO24, + gpio25: peripherals.GPIO25, + gpio26: peripherals.GPIO26, + gpio27: peripherals.GPIO27, + gpio28: peripherals.GPIO28, + gpio29: peripherals.GPIO29, + gpio30: peripherals.GPIO30, }; - // let tablebuffer = mk_static!( [u8; esp_bootloader_esp_idf::partitions::PARTITION_TABLE_MAX_LEN], @@ -351,77 +381,45 @@ impl PlantHal { let mut init_rtc_store: bool = false; let mut to_config_mode: bool = false; let reasons = match reset_reason() { - None => { - "unknown" - } - Some(reason) => { - match reason { - SocResetReason::ChipPowerOn => { - "power on" - } - SocResetReason::CoreSw => { - "software reset" - } - SocResetReason::CoreDeepSleep => { - "deep sleep" - } - SocResetReason::CoreSDIO => { - "sdio reset" - } - SocResetReason::CoreMwdt0 => { - "Watchdog Main" - } - SocResetReason::CoreMwdt1 => { - "Watchdog 1" - } - SocResetReason::CoreRtcWdt => { - "Watchdog RTC" - } - SocResetReason::Cpu0Mwdt0 => { - "Watchdog MCpu0" - } - SocResetReason::Cpu0Sw => { - "software reset cpu0" - } - SocResetReason::Cpu0RtcWdt => { - init_rtc_store = true; - "Watchdog RTC cpu0" - } - SocResetReason::SysBrownOut => { - "sys brown out" - } - SocResetReason::SysRtcWdt => { - "Watchdog Sys rtc" - } - SocResetReason::Cpu0Mwdt1 => { - "cpu0 mwdt1" - } - SocResetReason::SysSuperWdt => { - "Watchdog Super" - } - SocResetReason::CoreEfuseCrc => { - "core efuse crc" - } - SocResetReason::CoreUsbUart => { - to_config_mode = true; - "core usb uart" - } - SocResetReason::CoreUsbJtag => { - "core usb jtag" - } - SocResetReason::Cpu0JtagCpu => { - "cpu0 jtag cpu" - } + None => "unknown", + Some(reason) => match reason { + SocResetReason::ChipPowerOn => "power on", + SocResetReason::CoreSw => "software reset", + SocResetReason::CoreDeepSleep => "deep sleep", + SocResetReason::CoreSDIO => "sdio reset", + SocResetReason::CoreMwdt0 => "Watchdog Main", + SocResetReason::CoreMwdt1 => "Watchdog 1", + SocResetReason::CoreRtcWdt => "Watchdog RTC", + SocResetReason::Cpu0Mwdt0 => "Watchdog MCpu0", + SocResetReason::Cpu0Sw => "software reset cpu0", + SocResetReason::Cpu0RtcWdt => { + init_rtc_store = true; + "Watchdog RTC cpu0" } - } + SocResetReason::SysBrownOut => "sys brown out", + SocResetReason::SysRtcWdt => "Watchdog Sys rtc", + SocResetReason::Cpu0Mwdt1 => "cpu0 mwdt1", + SocResetReason::SysSuperWdt => "Watchdog Super", + SocResetReason::CoreEfuseCrc => "core efuse crc", + SocResetReason::CoreUsbUart => { + to_config_mode = true; + "core usb uart" + } + SocResetReason::CoreUsbJtag => "core usb jtag", + SocResetReason::Cpu0JtagCpu => "cpu0 jtag cpu", + }, }; - LOG_ACCESS.lock().await.log( - LogMessage::ResetReason, - init_rtc_store as u32, - to_config_mode as u32, - "", - &format!("{reasons:?}"), - ).await; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::ResetReason, + init_rtc_store as u32, + to_config_mode as u32, + "", + &format!("{reasons:?}"), + ) + .await; esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode) .await; @@ -449,7 +447,7 @@ impl PlantHal { // } // let storage = Storage::new(eeprom, Delay::new(1000)); - //let rtc_module: Box = + let rtc_module: Box = Box::new(initial_hal::NoRTC {}); // Box::new(DS3231Module { rtc, storage }) as Box; let hal = match config { @@ -487,32 +485,35 @@ impl PlantHal { } }; - let board_hal: Box = //match config.hardware.board { - //BoardVersion::INITIAL => { + let board_hal: Box = match config.hardware.board { + BoardVersion::INITIAL => { initial_hal::create_initial_board(free_pins, config, esp)? - ; - //} + } // BoardVersion::V3 => { // v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)? // } - //BoardVersion::V4 => { - // v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)? - //} - //_ => { - // todo!() - //} - //}; + BoardVersion::V4 => { + v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)? + } + _ => { + todo!() + } + }; HAL { board_hal } } Err(err) => { - LOG_ACCESS.lock().await.log( - LogMessage::ConfigModeMissingConfig, - 0, - 0, - "", - &err.to_string(), - ).await; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::ConfigModeMissingConfig, + 0, + 0, + "", + &err.to_string(), + ) + .await; HAL { board_hal: initial_hal::create_initial_board( free_pins, @@ -527,11 +528,13 @@ impl PlantHal { } } - pub async fn esp_time() -> DateTime { DateTime::from_timestamp_micros(TIME_ACCESS.get().await.current_time_us() as i64).unwrap() } pub async fn esp_set_time(time: DateTime) { - TIME_ACCESS.get().await.set_current_time_us(time.timestamp_micros() as u64); + TIME_ACCESS + .get() + .await + .set_current_time_us(time.timestamp_micros() as u64); } diff --git a/rust/src/hal/rtc.rs b/rust/src/hal/rtc.rs index 154dc61..d923c0a 100644 --- a/rust/src/hal/rtc.rs +++ b/rust/src/hal/rtc.rs @@ -1,4 +1,5 @@ use crate::hal::Box; +use crate::FatError::FatResult; use alloc::vec::Vec; use async_trait::async_trait; use chrono::{DateTime, Utc}; @@ -24,11 +25,11 @@ use chrono::{DateTime, Utc}; // #[async_trait] pub trait RTCModuleInteraction { - async fn get_backup_info(&mut self) -> anyhow::Result; - async fn get_backup_config(&mut self) -> anyhow::Result>; - async fn backup_config(&mut self, bytes: &[u8]) -> anyhow::Result<()>; - async fn get_rtc_time(&mut self) -> anyhow::Result>; - async fn set_rtc_time(&mut self, time: &DateTime) -> anyhow::Result<()>; + async fn get_backup_info(&mut self) -> FatResult; + async fn get_backup_config(&mut self) -> FatResult>; + async fn backup_config(&mut self, bytes: &[u8]) -> FatResult<()>; + async fn get_rtc_time(&mut self) -> FatResult>; + async fn set_rtc_time(&mut self, time: &DateTime) -> FatResult<()>; } // // const BACKUP_HEADER_MAX_SIZE: usize = 64; diff --git a/rust/src/hal/v4_hal.rs b/rust/src/hal/v4_hal.rs new file mode 100644 index 0000000..bc95a88 --- /dev/null +++ b/rust/src/hal/v4_hal.rs @@ -0,0 +1,426 @@ +use crate::config::PlantControllerConfig; +use crate::hal::battery::BatteryInteraction; +use crate::hal::esp::Esp; +use crate::hal::rtc::RTCModuleInteraction; +use crate::hal::water::TankSensor; +use crate::hal::{BoardInteraction, FreePeripherals, Sensor}; +use alloc::boxed::Box; +use async_trait::async_trait; +//use embedded_hal_bus::i2c::MutexDevice; +use crate::bail; +use crate::FatError::FatError; +use esp_hal::gpio::{Flex, Level, Output, OutputConfig}; +use measurements::{Current, Voltage}; +// pub enum Charger<'a> { +// SolarMpptV1 { +// mppt_ina: SyncIna219>, UnCalibrated>, +// solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>, +// charge_indicator: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>, +// }, +// ErrorInit {}, +// } +// +// impl Charger<'_> { +// pub(crate) fn power_save(&mut self) { +// match self { +// Charger::SolarMpptV1 { mppt_ina, .. } => { +// let _ = mppt_ina +// .set_configuration(Configuration { +// reset: Default::default(), +// bus_voltage_range: Default::default(), +// shunt_voltage_range: Default::default(), +// bus_resolution: Default::default(), +// shunt_resolution: Default::default(), +// operating_mode: OperatingMode::PowerDown, +// }) +// .map_err(|e| { +// log::info!( +// "Error setting ina mppt configuration during deep sleep preparation{:?}", +// e +// ); +// }); +// } +// _ => {} +// } +// } +// fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> { +// match self { +// Self::SolarMpptV1 { +// charge_indicator, .. +// } => { +// charge_indicator.set_state(charging.into())?; +// } +// _ => {} +// } +// Ok(()) +// } +// +// fn is_day(&self) -> bool { +// match self { +// Charger::SolarMpptV1 { solar_is_day, .. } => solar_is_day.get_level().into(), +// _ => true, +// } +// } +// +// fn get_mptt_voltage(&mut self) -> anyhow::Result { +// let voltage = match self { +// Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina +// .bus_voltage() +// .map(|v| Voltage::from_millivolts(v.voltage_mv() as f64))?, +// _ => { +// bail!("hardware error during init") +// } +// }; +// Ok(voltage) +// } +// +// fn get_mptt_current(&mut self) -> anyhow::Result { +// let current = match self { +// Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina.shunt_voltage().map(|v| { +// let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64); +// let shut_value = Resistance::from_ohms(0.05_f64); +// let current = shunt_voltage.as_volts() / shut_value.as_ohms(); +// Current::from_amperes(current) +// })?, +// _ => { +// bail!("hardware error during init") +// } +// }; +// Ok(current) +// } +// } + +pub struct V4<'a> { + esp: Esp<'a>, + tank_sensor: TankSensor<'a>, + //charger: Charger<'a>, + rtc_module: Box, + battery_monitor: Box, + config: PlantControllerConfig, + + awake: Output<'a>, + light: Output<'a>, + general_fault: Output<'a>, + //pump_expander: Pca9535Immediate>>, + //pump_ina: Option>, UnCalibrated>>, + //sensor: SensorImpl<'a>, + extra1: Output<'a>, + extra2: Output<'a>, +} + +struct InputOutput<'a> { + pin: Flex<'a>, +} + +pub(crate) fn create_v4( + peripherals: FreePeripherals<'static>, + esp: Esp<'static>, + config: PlantControllerConfig, + battery_monitor: Box, + rtc_module: Box, +) -> Result + Send + 'static>, FatError> { + log::info!("Start v4"); + let mut awake = Output::new(peripherals.gpio21, Level::High, OutputConfig::default()); + awake.set_high(); + + let mut general_fault = Output::new(peripherals.gpio23, Level::Low, OutputConfig::default()); + general_fault.set_low(); + + let mut extra1 = Output::new(peripherals.gpio6, Level::Low, OutputConfig::default()); + let mut extra2 = Output::new(peripherals.gpio15, Level::Low, OutputConfig::default()); + + let one_wire_pin = Flex::new(peripherals.gpio18); + let tank_power_pin = peripherals.gpio11; + let flow_sensor_pin = peripherals.gpio4; + + let tank_sensor = TankSensor::create( + one_wire_pin, + //peripherals.adc1, + //peripherals.gpio5, + //tank_power_pin, + //flow_sensor_pin, + //peripherals.pcnt1, + )?; + // + // let mut sensor_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 34); + // let sensor = match sensor_expander.pin_into_output(GPIOBank::Bank0, 0) { + // Ok(_) => { + // log::info!("SensorExpander answered"); + // //pulse counter version + // let mut signal_counter = PcntDriver::new( + // peripherals.pcnt0, + // Some(peripherals.gpio22), + // Option::::None, + // Option::::None, + // Option::::None, + // )?; + // + // signal_counter.channel_config( + // PcntChannel::Channel0, + // PinIndex::Pin0, + // PinIndex::Pin1, + // &PcntChannelConfig { + // lctrl_mode: PcntControlMode::Keep, + // hctrl_mode: PcntControlMode::Keep, + // pos_mode: PcntCountMode::Increment, + // neg_mode: PcntCountMode::Hold, + // counter_h_lim: i16::MAX, + // counter_l_lim: 0, + // }, + // )?; + // + // for pin in 0..8 { + // let _ = sensor_expander.pin_into_output(GPIOBank::Bank0, pin); + // let _ = sensor_expander.pin_into_output(GPIOBank::Bank1, pin); + // let _ = sensor_expander.pin_set_low(GPIOBank::Bank0, pin); + // let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin); + // } + // + // SensorImpl::PulseCounter { + // signal_counter, + // sensor_expander, + // } + // } + // Err(_) => { + // log::info!("Can bus mode "); + // let timing = can::config::Timing::B25K; + // let config = can::config::Config::new().timing(timing); + // let can = can::CanDriver::new( + // peripherals.can, + // peripherals.gpio0, + // peripherals.gpio2, + // &config, + // ) + // .unwrap(); + // + // let frame = StandardId::new(0x042).unwrap(); + // let tx_frame = Frame::new(frame, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap(); + // can.transmit(&tx_frame, 1000).unwrap(); + // + // if let Ok(rx_frame) = can.receive(1000) { + // log::info!("rx {:}:", rx_frame); + // } + // //can bus version + // SensorImpl::CanBus { can } + // } + // }; + + let mut solar_is_day = Output::new(peripherals.gpio7, Level::Low, Default::default()); + let mut light = Output::new(peripherals.gpio10, Level::Low, Default::default()); + let mut charge_indicator = Output::new(peripherals.gpio3, Level::Low, Default::default()); + + // let mut pump_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 32); + // for pin in 0..8 { + // let _ = pump_expander.pin_into_output(GPIOBank::Bank0, pin); + // let _ = pump_expander.pin_into_output(GPIOBank::Bank1, pin); + // let _ = pump_expander.pin_set_low(GPIOBank::Bank0, pin); + // let _ = pump_expander.pin_set_low(GPIOBank::Bank1, pin); + // } + // + // let mppt_ina = SyncIna219::new( + // MutexDevice::new(&I2C_DRIVER), + // Address::from_pins(Pin::Vcc, Pin::Gnd), + // ); + // + // let charger = match mppt_ina { + // Ok(mut mppt_ina) => { + // mppt_ina.set_configuration(Configuration { + // reset: Default::default(), + // bus_voltage_range: Default::default(), + // shunt_voltage_range: Default::default(), + // bus_resolution: Default::default(), + // shunt_resolution: ina219::configuration::Resolution::Avg128, + // operating_mode: Default::default(), + // })?; + // + // Charger::SolarMpptV1 { + // mppt_ina, + // solar_is_day, + // charge_indicator, + // } + // } + // Err(_) => Charger::ErrorInit {}, + // }; + // + // let pump_ina = match SyncIna219::new( + // MutexDevice::new(&I2C_DRIVER), + // Address::from_pins(Pin::Gnd, Pin::Sda), + // ) { + // Ok(pump_ina) => Some(pump_ina), + // Err(err) => { + // log::info!("Error creating pump ina: {:?}", err); + // None + // } + // }; + + let v = V4 { + rtc_module, + esp, + awake, + tank_sensor, + light, + general_fault, + //pump_ina, + //pump_expander, + config, + battery_monitor, + //charger, + extra1, + extra2, + //sensor, + }; + Ok(Box::new(v)) +} + +#[async_trait] +impl<'a> BoardInteraction<'a> for V4<'a> { + fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> { + Ok(&mut self.tank_sensor) + } + + fn get_esp(&mut self) -> &mut Esp<'a> { + &mut self.esp + } + + fn get_config(&mut self) -> &PlantControllerConfig { + &self.config + } + + fn get_battery_monitor(&mut self) -> &mut Box { + &mut self.battery_monitor + } + + fn get_rtc_module(&mut self) -> &mut Box { + &mut self.rtc_module + } + + fn set_charge_indicator(&mut self, charging: bool) -> Result<(), FatError> { + bail!("not implemented"); + // self.charger.set_charge_indicator(charging) + } + + async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! { + self.awake.set_low(); + //self.charger.power_save(); + self.esp.deep_sleep(duration_in_ms).await; + } + + fn is_day(&self) -> bool { + false + //self.charger.is_day() + } + + fn light(&mut self, enable: bool) -> Result<(), FatError> { + bail!("not implemented"); + // unsafe { gpio_hold_dis(self.light.pin()) }; + // self.light.set_state(enable.into())?; + // unsafe { gpio_hold_en(self.light.pin()) }; + // anyhow::Ok(()) + } + + async fn pump(&mut self, plant: usize, enable: bool) -> Result<(), FatError> { + bail!("not implemented"); + // if enable { + // self.pump_expander + // .pin_set_high(GPIOBank::Bank0, plant.try_into()?)?; + // } else { + // self.pump_expander + // .pin_set_low(GPIOBank::Bank0, plant.try_into()?)?; + // } + // anyhow::Ok(()) + } + + async fn pump_current(&mut self, _plant: usize) -> Result { + bail!("not implemented"); + // //sensore is shared for all pumps, ignore plant id + // match self.pump_ina.as_mut() { + // None => { + // bail!("pump current sensor not available"); + // } + // Some(pump_ina) => { + // let v = pump_ina.shunt_voltage().map(|v| { + // let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64); + // let shut_value = Resistance::from_ohms(0.05_f64); + // let current = shunt_voltage.as_volts() / shut_value.as_ohms(); + // Current::from_amperes(current) + // })?; + // Ok(v) + // } + // } + } + + async fn fault(&mut self, plant: usize, enable: bool) -> Result<(), FatError> { + bail!("not implemented"); + // if enable { + // self.pump_expander + // .pin_set_high(GPIOBank::Bank1, plant.try_into()?)? + // } else { + // self.pump_expander + // .pin_set_low(GPIOBank::Bank1, plant.try_into()?)? + // } + // anyhow::Ok(()) + } + + async fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result { + bail!("not implemented"); + //self.sensor.measure_moisture_hz(plant, sensor) + } + + async fn general_fault(&mut self, enable: bool) { + //FIXME unsafe { gpio_hold_dis(self.general_fault.pin()) }; + self.general_fault.set_level(enable.into()); + //FIXME unsafe { gpio_hold_en(self.general_fault.pin()) }; + } + + async fn test(&mut self) -> Result<(), FatError> { + // self.general_fault(true); + // self.esp.delay.delay_ms(100); + // self.general_fault(false); + // self.esp.delay.delay_ms(500); + // self.light(true)?; + // self.esp.delay.delay_ms(500); + // self.light(false)?; + // self.esp.delay.delay_ms(500); + // for i in 0..PLANT_COUNT { + // self.fault(i, true)?; + // self.esp.delay.delay_ms(500); + // self.fault(i, false)?; + // self.esp.delay.delay_ms(500); + // } + // for i in 0..PLANT_COUNT { + // self.pump(i, true)?; + // self.esp.delay.delay_ms(100); + // self.pump(i, false)?; + // self.esp.delay.delay_ms(100); + // } + // for plant in 0..PLANT_COUNT { + // let a = self.measure_moisture_hz(plant, Sensor::A); + // let b = self.measure_moisture_hz(plant, Sensor::B); + // let aa = match a { + // OkStd(a) => a as u32, + // Err(_) => u32::MAX, + // }; + // let bb = match b { + // OkStd(b) => b as u32, + // Err(_) => u32::MAX, + // }; + // log(LogMessage::TestSensor, aa, bb, &plant.to_string(), ""); + // } + // self.esp.delay.delay_ms(10); + Ok(()) + } + + fn set_config(&mut self, config: PlantControllerConfig) { + self.config = config; + } + + async fn get_mptt_voltage(&mut self) -> Result { + bail!("not implemented"); + //self.charger.get_mptt_voltage() + } + + async fn get_mptt_current(&mut self) -> Result { + bail!("not implemented"); + //self.charger.get_mptt_current() + } +} diff --git a/rust/src/hal/water.rs b/rust/src/hal/water.rs new file mode 100644 index 0000000..80c66bc --- /dev/null +++ b/rust/src/hal/water.rs @@ -0,0 +1,172 @@ +use crate::bail; +use crate::FatError::FatError; +use embassy_time::Timer; +use esp_hal::delay::Delay; +use esp_hal::gpio::{Flex, OutputConfig, Pull}; +use esp_println::println; +use onewire::{ds18b20, Device, DeviceSearch, OneWire, DS18B20}; + +pub struct TankSensor<'a> { + one_wire_bus: OneWire>, + // tank_channel: AdcChannelDriver<'a, Gpio5, AdcDriver<'a, ADC1>>, + // tank_power: PinDriver<'a, AnyIOPin, InputOutput>, + // flow_counter: PcntDriver<'a>, + // delay: Delay, +} + +impl<'a> TankSensor<'a> { + pub(crate) fn create( + mut one_wire_pin: Flex, + // adc1: ADC1, + // gpio5: Gpio5, + // tank_power_pin: AnyIOPin, + // flow_sensor_pin: AnyIOPin, + // pcnt1: PCNT1, + ) -> Result { + one_wire_pin.apply_output_config(&OutputConfig::default().with_pull(Pull::None)); + + // let adc_config = AdcChannelConfig { + // attenuation: attenuation::DB_11, + // resolution: Resolution::Resolution12Bit, + // calibration: esp_idf_hal::adc::oneshot::config::Calibration::Curve, + // }; + // let tank_driver = AdcDriver::new(adc1).expect("Failed to configure ADC"); + // let tank_channel = AdcChannelDriver::new(tank_driver, gpio5, &adc_config) + // .expect("Failed to configure ADC channel"); + // + // let mut tank_power = + // PinDriver::input_output(tank_power_pin).expect("Failed to configure pin"); + // tank_power + // .set_pull(Pull::Floating) + // .expect("Failed to set pull"); + // + + let one_wire_bus = OneWire::new(one_wire_pin, false); + + // + // let mut flow_counter = PcntDriver::new( + // pcnt1, + // Some(flow_sensor_pin), + // Option::::None, + // Option::::None, + // Option::::None, + // )?; + // + // flow_counter.channel_config( + // PcntChannel::Channel1, + // PinIndex::Pin0, + // PinIndex::Pin1, + // &PcntChannelConfig { + // lctrl_mode: PcntControlMode::Keep, + // hctrl_mode: PcntControlMode::Keep, + // pos_mode: PcntCountMode::Increment, + // neg_mode: PcntCountMode::Hold, + // counter_h_lim: i16::MAX, + // counter_l_lim: 0, + // }, + // )?; + // + Ok(TankSensor { + one_wire_bus, + // tank_channel, + // tank_power, + // flow_counter, + // delay: Default::default(), + }) + } + + pub fn reset_flow_meter(&mut self) { + // self.flow_counter.counter_pause().unwrap(); + // self.flow_counter.counter_clear().unwrap(); + } + + pub fn start_flow_meter(&mut self) { + //self.flow_counter.counter_resume().unwrap(); + } + + pub fn get_flow_meter_value(&mut self) -> i16 { + //self.flow_counter.get_counter_value().unwrap() + 5_i16 + } + + pub fn stop_flow_meter(&mut self) -> i16 { + //self.flow_counter.counter_pause().unwrap(); + self.get_flow_meter_value() + } + + pub async fn water_temperature_c(&mut self) -> Result { + //multisample should be moved to water_temperature_c + let mut attempt = 1; + let mut delay = Delay::new(); + self.one_wire_bus.reset(&mut delay)?; + let mut search = DeviceSearch::new(); + let mut water_temp_sensor: Option = None; + while let Some(device) = self.one_wire_bus.search_next(&mut search, &mut delay)? { + if device.address[0] == ds18b20::FAMILY_CODE { + water_temp_sensor = Some(device); + break; + } + } + match water_temp_sensor { + Some(device) => { + println!("Found one wire device: {:?}", device); + let mut water_temp_sensor = DS18B20::new(device)?; + + let water_temp: Result = loop { + let temp = self + .single_temperature_c(&mut water_temp_sensor, &mut delay) + .await; + match &temp { + Ok(res) => { + println!("Water temp is {}", res); + break temp; + } + Err(err) => { + println!("Could not get water temp {} attempt {}", err, attempt) + } + } + if attempt == 5 { + break temp; + } + attempt += 1; + }; + water_temp + } + None => { + bail!("Not found any one wire Ds18b20"); + } + } + } + + async fn single_temperature_c( + &mut self, + sensor: &mut DS18B20, + delay: &mut Delay, + ) -> Result { + let resolution = sensor.measure_temperature(&mut self.one_wire_bus, delay)?; + Timer::after_millis(resolution.time_ms() as u64).await; + let temperature = sensor.read_temperature(&mut self.one_wire_bus, delay)? as f32; + if temperature == 85_f32 { + bail!("Ds18b20 dummy temperature returned"); + } + Ok(temperature / 10_f32) + } + + pub async fn tank_sensor_voltage(&mut self) -> Result { + // self.tank_power.set_high()?; + // //let stabilize + // self.delay.delay_ms(100); + // + // let mut store = [0_u16; TANK_MULTI_SAMPLE]; + // for multisample in 0..TANK_MULTI_SAMPLE { + // let value = self.tank_channel.read()?; + // store[multisample] = value; + // } + // self.tank_power.set_low()?; + // + // store.sort(); + // let median_mv = store[6] as f32 / 1000_f32; + let median_mv = 10_f32; + Ok(median_mv) + } +} diff --git a/rust/src/log/mod.rs b/rust/src/log/mod.rs index 2241f83..9425a1b 100644 --- a/rust/src/log/mod.rs +++ b/rust/src/log/mod.rs @@ -1,39 +1,48 @@ +use crate::hal::TIME_ACCESS; use crate::vec; use alloc::string::ToString; use alloc::vec::Vec; -use bytemuck::{AnyBitPattern, Contiguous, Pod, Zeroable}; +use bytemuck::{AnyBitPattern, Pod, Zeroable}; +use deranged::RangedU8; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; -use embassy_time::Instant; use esp_hal::Persistable; use log::info; use serde::Serialize; use strum_macros::IntoStaticStr; use unit_enum::UnitEnum; -use crate::hal::TIME_ACCESS; +const LOG_ARRAY_SIZE: u8 = 220; +const MAX_LOG_ARRAY_INDEX: u8 = LOG_ARRAY_SIZE - 1; #[esp_hal::ram(rtc_fast, persistent)] static mut LOG_ARRAY: LogArray = LogArray { - buffer: [LogEntryInner { timestamp: 0, message_id: 0, a: 0, b: 0, txt_short: [0;TXT_SHORT_LENGTH], txt_long: [0;TXT_LONG_LENGTH] }; 256], + buffer: [LogEntryInner { + timestamp: 0, + message_id: 0, + a: 0, + b: 0, + txt_short: [0; TXT_SHORT_LENGTH], + txt_long: [0; TXT_LONG_LENGTH], + }; LOG_ARRAY_SIZE as usize], head: 0, }; -pub static LOG_ACCESS: Mutex = Mutex::new(unsafe { LOG_ARRAY }); +pub static LOG_ACCESS: Mutex = + unsafe { Mutex::new(&mut *&raw mut LOG_ARRAY) }; const TXT_SHORT_LENGTH: usize = 8; const TXT_LONG_LENGTH: usize = 32; - #[derive(Debug, Clone, Copy, AnyBitPattern)] #[repr(C)] -pub struct LogArray{ - buffer: [LogEntryInner; (u8::MAX_VALUE as usize) +1], - head: u8 +pub struct LogArray { + buffer: [LogEntryInner; LOG_ARRAY_SIZE as usize], + head: u8, } unsafe impl Persistable for LogArray {} unsafe impl Zeroable for LogEntryInner {} -unsafe impl Pod for LogEntryInner{} +unsafe impl Pod for LogEntryInner {} #[derive(Debug, Clone, Copy)] struct LogEntryInner { @@ -57,7 +66,7 @@ pub struct LogEntry { impl From for LogEntry { fn from(value: LogEntryInner) -> Self { - LogEntry{ + LogEntry { timestamp: value.timestamp, message_id: value.message_id, a: value.a, @@ -70,10 +79,13 @@ impl From for LogEntry { impl LogArray { pub fn get(&mut self) -> Vec { + let head: RangedU8<0, MAX_LOG_ARRAY_INDEX> = + RangedU8::new(self.head).unwrap_or(RangedU8::new(0).unwrap()); + let mut rv: Vec = Vec::new(); - let mut index = self.head.wrapping_sub(1); + let mut index = head.wrapping_sub(1); for _ in 0..self.buffer.len() { - let entry = self.buffer[index as usize]; + let entry = self.buffer[index.get() as usize]; if (entry.message_id as usize) != LogMessage::Empty.ordinal() { rv.push(entry.into()); } @@ -90,13 +102,16 @@ impl LogArray { txt_short: &str, txt_long: &str, ) { + let mut head: RangedU8<0, MAX_LOG_ARRAY_INDEX> = + RangedU8::new(self.head).unwrap_or(RangedU8::new(0).unwrap()); + let mut txt_short_stack: heapless::String = heapless::String::new(); let mut txt_long_stack: heapless::String = heapless::String::new(); limit_length(txt_short, &mut txt_short_stack); limit_length(txt_long, &mut txt_long_stack); - let time = TIME_ACCESS.get().await.current_time_us()/1000; + let time = TIME_ACCESS.get().await.current_time_us() / 1000; let ordinal = message_key.ordinal() as u16; let template: &str = message_key.into(); @@ -108,14 +123,19 @@ impl LogArray { info!("{}", template_string); - let to_modify = &mut self.buffer[self.head as usize]; + let to_modify = &mut self.buffer[head.get() as usize]; to_modify.timestamp = time; to_modify.message_id = ordinal; to_modify.a = number_a; to_modify.b = number_b; - to_modify.txt_short.clone_from_slice(&txt_short_stack.as_bytes()); - to_modify.txt_long.clone_from_slice(&txt_long_stack.as_bytes()); - self.head = self.head.wrapping_add(1); + to_modify + .txt_short + .clone_from_slice(&txt_short_stack.as_bytes()); + to_modify + .txt_long + .clone_from_slice(&txt_long_stack.as_bytes()); + head = head.wrapping_add(1); + self.head = head.get(); } } @@ -140,13 +160,9 @@ fn limit_length(input: &str, target: &mut heapless::String ! { @@ -56,6 +58,7 @@ extern "C" fn custom_halt() -> ! { } //use tank::*; +mod FatError; mod config; mod hal; mod log; @@ -146,7 +149,7 @@ enum NetworkMode { OFFLINE, } -async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { +async fn safe_main(spawner: Spawner) -> FatResult<()> { info!("Startup Rust"); let mut to_config = false; @@ -183,28 +186,34 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { let _ota_state_string = "unknown"; board.board_hal.general_fault(false).await; - let time = esp_time().await; - let cur = board - .board_hal - .get_rtc_module() - .get_rtc_time() - .await - .or_else(|err| { + let cur = match board.board_hal.get_rtc_module().get_rtc_time().await { + Ok(value) => value, + Err(err) => { info!("rtc module error: {:?}", err); - board.board_hal.general_fault(true); - anyhow::Ok(time) - })?; + board.board_hal.general_fault(true).await; + esp_time().await + } + }; + //check if we know the time current > 2020 (plausibility checks, this code is newer than 2020) if cur.year() < 2020 { to_config = true; - LOG_ACCESS.lock().await.log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "").await; + LOG_ACCESS + .lock() + .await + .log(LogMessage::YearInplausibleForceConfig, 0, 0, "", "") + .await; } info!("cur is {}", cur); update_charge_indicator(&mut board).await; println!("faul led3"); if board.board_hal.get_esp().get_restart_to_conf() { - LOG_ACCESS.lock().await.log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "").await; + LOG_ACCESS + .lock() + .await + .log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "") + .await; for _i in 0..2 { board.board_hal.general_fault(true).await; Timer::after_millis(100).await; @@ -216,7 +225,11 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { board.board_hal.get_esp().set_restart_to_conf(false); } else if board.board_hal.get_esp().mode_override_pressed() { board.board_hal.general_fault(true).await; - LOG_ACCESS.lock().await.log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await; + LOG_ACCESS + .lock() + .await + .log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "") + .await; for _i in 0..5 { board.board_hal.general_fault(true).await; Timer::after_millis(100).await; @@ -297,22 +310,25 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { let _ = publish_mppt_state(&mut board).await; } - LOG_ACCESS.lock().await.log( - LogMessage::StartupInfo, - matches!(network_mode, NetworkMode::WIFI { .. }) as u32, - matches!( - network_mode, - NetworkMode::WIFI { - sntp: SntpMode::SYNC { .. }, - .. - } - ) as u32, - matches!(network_mode, NetworkMode::WIFI { mqtt: true, .. }) - .to_string() - .as_str(), - "", - ).await - ; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::StartupInfo, + matches!(network_mode, NetworkMode::WIFI { .. }) as u32, + matches!( + network_mode, + NetworkMode::WIFI { + sntp: SntpMode::SYNC { .. }, + .. + } + ) as u32, + matches!(network_mode, NetworkMode::WIFI { mqtt: true, .. }) + .to_string() + .as_str(), + "", + ) + .await; if to_config { //check if client or ap mode and init Wi-Fi @@ -323,7 +339,11 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { let board = BOARD_ACCESS.get().await.lock().await; wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await; } else { - LOG_ACCESS.lock().await.log(LogMessage::NormalRun, 0, 0, "", "").await; + LOG_ACCESS + .lock() + .await + .log(LogMessage::NormalRun, 0, 0, "", "") + .await; } let _dry_run = false; @@ -364,13 +384,10 @@ async fn safe_main(spawner: Spawner) -> anyhow::Result<()> { // } let mut _water_frozen = false; - //TODO - let water_temp = anyhow::Ok(12_f32); - // board - // .board_hal - // .get_tank_sensor() - // .context("no sensor") - // .and_then(async |f| f.water_temperature_c().await); + let water_temp = board + .board_hal + .get_tank_sensor() + .and_then(async |sensor| sensor.water_temperature_c().await); if let Ok(res) = water_temp { if res < WATER_FROZEN_THRESH { @@ -615,7 +632,7 @@ pub async fn do_secure_pump( plant_id: usize, plant_config: &PlantConfig, dry_run: bool, -) -> anyhow::Result { +) -> FatResult { let mut current_collector = vec![0_u16; plant_config.pump_time_s.into()]; let mut flow_collector = vec![0_i16; plant_config.pump_time_s.into()]; let mut error = false; @@ -662,14 +679,17 @@ pub async fn do_secure_pump( let high_current = current_ma > plant_config.max_pump_current_ma; if high_current { if first_error { - LOG_ACCESS.lock().await.log( - LogMessage::PumpOverCurrent, - plant_id as u32 + 1, - current_ma as u32, - plant_config.max_pump_current_ma.to_string().as_str(), - step.to_string().as_str(), - ).await - ; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::PumpOverCurrent, + plant_id as u32 + 1, + current_ma as u32, + plant_config.max_pump_current_ma.to_string().as_str(), + step.to_string().as_str(), + ) + .await; board.board_hal.general_fault(true).await; board.board_hal.fault(plant_id, true).await?; if !plant_config.ignore_current_error { @@ -682,14 +702,17 @@ pub async fn do_secure_pump( let low_current = current_ma < plant_config.min_pump_current_ma; if low_current { if first_error { - LOG_ACCESS.lock().await.log( - LogMessage::PumpOpenLoopCurrent, - plant_id as u32 + 1, - current_ma as u32, - plant_config.min_pump_current_ma.to_string().as_str(), - step.to_string().as_str(), - ).await - ; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::PumpOpenLoopCurrent, + plant_id as u32 + 1, + current_ma as u32, + plant_config.min_pump_current_ma.to_string().as_str(), + step.to_string().as_str(), + ) + .await; board.board_hal.general_fault(true).await; board.board_hal.fault(plant_id, true).await?; if !plant_config.ignore_current_error { @@ -703,14 +726,17 @@ pub async fn do_secure_pump( Err(err) => { if !plant_config.ignore_current_error { info!("Error getting pump current: {}", err); - LOG_ACCESS.lock().await.log( - LogMessage::PumpMissingSensorCurrent, - plant_id as u32, - 0, - "", - "", - ).await - ; + LOG_ACCESS + .lock() + .await + .log( + LogMessage::PumpMissingSensorCurrent, + plant_id as u32, + 0, + "", + "", + ) + .await; error = true; break; } else { @@ -957,7 +983,7 @@ async fn pump_info( async fn publish_mppt_state( board: &mut MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>, -) -> anyhow::Result<()> { +) -> FatResult<()> { let current = board.board_hal.get_mptt_current().await?; let voltage = board.board_hal.get_mptt_voltage().await?; let solar_state = Solar { @@ -983,13 +1009,18 @@ async fn publish_battery_state( .get_battery_monitor() .get_battery_state() .await; - if let Ok(serialized_battery_state_bytes) = - serde_json::to_string(&state).map(|s| s.into_bytes()) + let value = match state { + Ok(state) => { + let json = serde_json::to_string(&state).unwrap().to_owned(); + json.as_bytes().to_owned() + } + Err(_) => "error".as_bytes().to_owned(), + }; { - board + let _ = board .board_hal .get_esp() - .mqtt_publish("/battery", &serialized_battery_state_bytes) + .mqtt_publish("/battery", &*value) .await; } } @@ -1062,13 +1093,14 @@ async fn wait_infinity( .lock() .await .board_hal - .deep_sleep(0).await; + .deep_sleep(0) + .await; } } } #[esp_hal_embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner) -> ! { // intialize embassy logger::init_logger_from_env(); //force init here! @@ -1082,21 +1114,13 @@ async fn main(spawner: Spawner) { println!("Hal init done, starting logic"); match safe_main(spawner).await { - // this should not get triggered, safe_main should not return but go into deep sleep with sensible - // timeout, this is just a fallback + // this should not get triggered, safe_main should not return but go into deep sleep or reboot Ok(_) => { - warn!("Main app finished, but should never do, restarting"); - let board = &mut BOARD_ACCESS.get().await.lock().await.board_hal; - - board.get_esp().set_restart_to_conf(false); - board.deep_sleep(1); + panic!("Main app finished, but should never do, restarting"); } // if safe_main exists with an error, rollback to a known good ota version Err(err) => { - error!("Failed main {}", err); - //TODO - //let _rollback_successful = rollback_and_reboot(); - //panic!("Failed to rollback :("); + panic!("Failed main {}", err); } } } diff --git a/rust/src/tank.rs b/rust/src/tank.rs index 0416302..f9dc4a0 100644 --- a/rust/src/tank.rs +++ b/rust/src/tank.rs @@ -1,5 +1,9 @@ use crate::alloc::string::{String, ToString}; use crate::config::TankConfig; +use crate::hal::HAL; +use crate::FatError::FatResult; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::mutex::MutexGuard; use serde::Serialize; const OPEN_TANK_VOLTAGE: f32 = 3.0; @@ -113,7 +117,7 @@ impl TankState { } } - pub fn as_mqtt_info(&self, config: &TankConfig, water_temp: &anyhow::Result) -> TankInfo { + pub fn as_mqtt_info(&self, config: &TankConfig, water_temp: &FatResult) -> TankInfo { let mut tank_err: Option = None; let left_ml = match self.left_ml(config) { Err(err) => { @@ -150,40 +154,41 @@ impl TankState { } } -// pub fn determine_tank_state(board: &mut std::sync::MutexGuard<'_, HAL<'_>>) -> TankState { -// if board.board_hal.get_config().tank.tank_sensor_enabled { -// match board -// .board_hal -// .get_tank_sensor() -// .context("no sensor") -// .and_then(|f| f.tank_sensor_voltage()) -// { -// Ok(raw_sensor_value_mv) => TankState::Present(raw_sensor_value_mv), -// Err(err) => TankState::Error(TankError::BoardError(err.to_string())), -// } -// } else { -// TankState::Disabled -// } -// } +pub async fn determine_tank_state( + board: &mut MutexGuard<'static, CriticalSectionRawMutex, HAL<'static>>, +) -> TankState { + if board.board_hal.get_config().tank.tank_sensor_enabled { + match board + .board_hal + .get_tank_sensor() + .and_then(|f| core::prelude::v1::Ok(f.tank_sensor_voltage())) + { + Ok(raw_sensor_value_mv) => TankState::Present(raw_sensor_value_mv.await.unwrap()), + Err(err) => TankState::Error(TankError::BoardError(err.to_string())), + } + } else { + TankState::Disabled + } +} #[derive(Debug, Serialize)] /// Information structure send to mqtt for monitoring purposes pub struct TankInfo { /// there is enough water in the tank - enough_water: bool, + pub(crate) enough_water: bool, /// warning that water needs to be refilled soon - warn_level: bool, + pub(crate) warn_level: bool, /// estimation how many ml are still in the tank - left_ml: Option, + pub(crate) left_ml: Option, /// if there is an issue with the water level sensor - sensor_error: Option, + pub(crate) sensor_error: Option, /// raw water sensor value - raw: Option, + pub(crate) raw: Option, /// percent value - percent: Option, + pub(crate) percent: Option, /// water in the tank might be frozen - water_frozen: bool, + pub(crate) water_frozen: bool, /// water temperature - water_temp: Option, - temp_sensor_error: Option, + pub(crate) water_temp: Option, + pub(crate) temp_sensor_error: Option, } diff --git a/rust/src/webserver/mod.rs b/rust/src/webserver/mod.rs index 35017c5..de43276 100644 --- a/rust/src/webserver/mod.rs +++ b/rust/src/webserver/mod.rs @@ -1,23 +1,25 @@ //offer ota and config mode use crate::config::PlantControllerConfig; -use crate::{get_version, log::LogMessage, BOARD_ACCESS}; +use crate::hal::{esp_set_time, esp_time}; +use crate::log::LOG_ACCESS; +use crate::tank::{determine_tank_state, TankInfo}; +use crate::FatError::{FatError, FatResult}; +use crate::{bail, get_version, log::LogMessage, BOARD_ACCESS}; use alloc::borrow::ToOwned; use alloc::format; use alloc::string::{String, ToString}; use alloc::sync::Arc; use alloc::vec::Vec; -use anyhow::{bail}; +use chrono::DateTime; use core::fmt::{Debug, Display}; use core::net::{IpAddr, Ipv4Addr, SocketAddr}; use core::result::Result::Ok; use core::str::from_utf8; use core::sync::atomic::{AtomicBool, Ordering}; -use chrono::DateTime; use edge_http::io::server::{Connection, Handler, Server}; -use edge_http::io::Error; use edge_http::Method; -use edge_nal::{TcpBind}; +use edge_nal::TcpBind; use edge_nal_embassy::{Tcp, TcpBuffers}; use embassy_net::Stack; use embassy_time::Instant; @@ -25,8 +27,6 @@ use embedded_io_async::{Read, Write}; use esp_println::println; use log::info; use serde::{Deserialize, Serialize}; -use crate::hal::{esp_set_time, esp_time}; -use crate::log::{LOG_ACCESS}; #[derive(Serialize, Debug)] struct SSIDList { @@ -191,23 +191,6 @@ pub struct NightLampCommand { // anyhow::Ok(Some(serde_json::to_string(&pump_result)?)) // } // -// fn tank_info( -// _request: &mut Request<&mut EspHttpConnection>, -// ) -> Result, anyhow::Error> { -// let mut board = BOARD_ACCESS.lock().unwrap(); -// let tank_info = determine_tank_state(&mut board); -// //should be multsampled -// -// let water_temp = board -// .board_hal -// .get_tank_sensor() -// .context("no sensor") -// .and_then(|f| f.water_temperature_c()); -// Ok(Some(serde_json::to_string(&tank_info.as_mqtt_info( -// &board.board_hal.get_config().tank, -// &water_temp, -// ))?)) -// } // // fn night_lamp_test( // request: &mut Request<&mut EspHttpConnection>, @@ -285,12 +268,12 @@ struct HttpHandler { } impl Handler for HttpHandler { - type Error = Error; + type Error = FatError; async fn handle<'a, T, const N: usize>( &self, _task_id: impl Display + Copy, conn: &mut Connection<'a, T, N>, - ) -> anyhow::Result<(), Self::Error> + ) -> Result<(), FatError> where T: Read + Write, { @@ -303,46 +286,55 @@ impl Handler for HttpHandler { let prefix = "/file?filename="; let status = if path.starts_with(prefix) { let filename = &path[prefix.len()..]; - let mut board = BOARD_ACCESS.get().await.lock().await; info!("file request for {} with method {}", filename, method); match method { Method::Delete => { + let mut board = BOARD_ACCESS.get().await.lock().await; board .board_hal .get_esp() .delete_file(filename.to_owned()) - .await - .unwrap(); + .await?; Some(200) } Method::Get => { let disp = format!("attachment; filename=\"{filename}\""); + let size = { + let mut board = BOARD_ACCESS.get().await.lock().await; + board + .board_hal + .get_esp() + .get_size(filename.to_owned()) + .await? + }; + conn.initiate_response( 200, Some("OK"), &[ ("Content-Type", "application/octet-stream"), ("Content-Disposition", disp.as_str()), + ("Content-Length", &format!("{}", size)), ], ) .await?; + let mut chunk = 0; loop { + let mut board = BOARD_ACCESS.get().await.lock().await; let read_chunk = board .board_hal .get_esp() .get_file(filename.to_owned(), chunk) - .await - .unwrap(); + .await?; let length = read_chunk.1; - info!("read {} bytes for file request for {}", length, filename); if length == 0 { info!("file request for {} finished", filename); break; } let data = &read_chunk.0[0..length]; conn.write_all(data).await?; - if length < 128 { + if length < read_chunk.0.len() { info!("file request for {} finished", filename); break; } @@ -351,12 +343,16 @@ impl Handler for HttpHandler { Some(200) } Method::Post => { - //ensure file is deleted, otherwise we would need to truncate the file which will not work with streaming - let _ = board - .board_hal - .get_esp() - .delete_file(filename.to_owned()) - .await; + { + let mut board = BOARD_ACCESS.get().await.lock().await; + //ensure file is deleted, otherwise we would need to truncate the file which will not work with streaming + let _ = board + .board_hal + .get_esp() + .delete_file(filename.to_owned()) + .await; + } + let mut offset = 0_usize; loop { let mut buf = [0_u8; 1024]; @@ -365,16 +361,12 @@ impl Handler for HttpHandler { info!("file request for {} finished", filename); break; } else { - info!( - "writing {} bytes for file request for {}", - to_write, filename - ); + let mut board = BOARD_ACCESS.get().await.lock().await; board .board_hal .get_esp() .write_file(filename.to_owned(), offset as u32, &buf[0..to_write]) - .await - .unwrap(); + .await?; } offset = offset + to_write } @@ -397,25 +389,32 @@ impl Handler for HttpHandler { Some(200) } "/" => { - conn.initiate_response(200, Some("OK"), &[("Content-Type", "text/html")]) - .await?; - conn.write_all(include_bytes!("index.html")).await?; + conn.initiate_response( + 200, + Some("OK"), + &[("Content-Type", "text/html"), ("Content-Encoding", "gzip")], + ) + .await?; + conn.write_all(include_bytes!("index.html.gz")).await?; Some(200) } "/bundle.js" => { conn.initiate_response( 200, Some("OK"), - &[("Content-Type", "text/javascript")], + &[ + ("Content-Type", "text/javascript"), + ("Content-Encoding", "gzip"), + ], ) .await?; - conn.write_all(include_bytes!("bundle.js")).await?; + conn.write_all(include_bytes!("bundle.js.gz")).await?; Some(200) } "/log" => { let buf = get_log(conn).await; Some(200) - }, + } &_ => { let json = match path { "/version" => Some(get_version_web(conn).await), @@ -554,23 +553,40 @@ impl Handler for HttpHandler { // }) // .unwrap(); +async fn tank_info( + request: &mut Connection<'_, T, N>, +) -> Result, FatError> +where + T: Read + Write, +{ + let mut board = BOARD_ACCESS.get().await.lock().await; + determine_tank_state(&mut board); + //should be multsampled + let sensor = board.board_hal.get_tank_sensor()?; + + let water_temp = sensor.water_temperature_c().await?; + Ok(Some(serde_json::to_string(&tank_info.as_mqtt_info( + &board.board_hal.get_config().tank, + &water_temp, + ))?)) +} + async fn write_time( request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> +) -> FatResult> where - T: Read + Write + T: Read + Write, { let actual_data = read_up_to_bytes_from_request(request, None).await?; let time: SetTime = serde_json::from_slice(&actual_data)?; let parsed = DateTime::parse_from_rfc3339(time.time).unwrap(); esp_set_time(parsed).await; - anyhow::Ok(None) + Ok(None) } - async fn set_config( request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> +) -> FatResult> where T: Read + Write, { @@ -582,13 +598,13 @@ where board.board_hal.get_esp().save_config(all).await?; log::info!("Wrote config config {:?} with size {}", config, length); board.board_hal.set_config(config); - anyhow::Ok(Some("saved".to_string())) + Ok(Some("saved".to_string())) } async fn read_up_to_bytes_from_request( request: &mut Connection<'_, T, N>, limit: Option, -) -> Result, anyhow::Error> +) -> FatResult> where T: Read + Write, { @@ -597,10 +613,7 @@ where let mut total_read = 0; loop { let mut buf = [0_u8; 64]; - let read = match request.read(&mut buf).await { - Ok(read) => read, - Err(e) => bail!("Error reading request {:?}", e), - }; + let read = request.read(&mut buf).await?; if read == 0 { break; } @@ -618,7 +631,7 @@ where async fn wifi_scan( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; info!("start wifi scan"); //let scan_result = board.board_hal.get_esp().wifi_scan().await? @@ -629,93 +642,87 @@ async fn wifi_scan( //.for_each(|s| ssids.push(s.ssid.to_string())); let ssid_json = serde_json::to_string(&SSIDList { ssids })?; info!("Sending ssid list {}", &ssid_json); - anyhow::Ok(Some(ssid_json)) + Ok(Some(ssid_json)) } -async fn get_log( - conn: &mut Connection<'_, T, N>, -) -> anyhow::Result<()> +async fn get_log(conn: &mut Connection<'_, T, N>) -> FatResult<()> where - T: Read + Write,{ + T: Read + Write, +{ let log = LOG_ACCESS.lock().await.get(); - conn.initiate_response( - 200, - Some("OK"), - &[("Content-Type", "text/javascript")], - ) - .await - .unwrap(); - conn.write_all("[".as_bytes()).await.unwrap(); + conn.initiate_response(200, Some("OK"), &[("Content-Type", "text/javascript")]) + .await?; + conn.write_all("[".as_bytes()).await?; let mut append = false; - for entry in log { + for entry in log { if append { - conn.write_all(",".as_bytes()).await.unwrap(); + conn.write_all(",".as_bytes()).await?; } append = true; let json = serde_json::to_string(&entry)?; - conn.write_all(json.as_bytes()).await.unwrap(); + conn.write_all(json.as_bytes()).await?; } - conn.write_all("]".as_bytes()).await.unwrap(); + conn.write_all("]".as_bytes()).await?; Ok(()) } async fn get_log_localization_config( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { - anyhow::Ok(Some(serde_json::to_string( +) -> FatResult> { + Ok(Some(serde_json::to_string( &LogMessage::to_log_localisation_config(), )?)) } async fn list_files( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; let result = board.board_hal.get_esp().list_files().await?; let file_list_json = serde_json::to_string(&result)?; - anyhow::Ok(Some(file_list_json)) + Ok(Some(file_list_json)) } async fn get_config( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; let json = serde_json::to_string(&board.board_hal.get_config())?; - anyhow::Ok(Some(json)) + Ok(Some(json)) } async fn get_solar_state( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; let state = SolarState { mppt_voltage: board.board_hal.get_mptt_voltage().await?.as_millivolts() as f32, mppt_current: board.board_hal.get_mptt_current().await?.as_milliamperes() as f32, is_day: board.board_hal.is_day(), }; - anyhow::Ok(Some(serde_json::to_string(&state)?)) + Ok(Some(serde_json::to_string(&state)?)) } async fn get_battery_state( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; let battery_state = board .board_hal .get_battery_monitor() .get_battery_state() .await?; - anyhow::Ok(Some(serde_json::to_string(&battery_state)?)) + Ok(Some(serde_json::to_string(&battery_state)?)) } async fn get_version_web( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; - anyhow::Ok(Some(serde_json::to_string(&get_version(&mut board).await)?)) + Ok(Some(serde_json::to_string(&get_version(&mut board).await)?)) } async fn get_time( _request: &mut Connection<'_, T, N>, -) -> Result, anyhow::Error> { +) -> FatResult> { let mut board = BOARD_ACCESS.get().await.lock().await; //TODO do not fail if rtc module is missing let native = esp_time().await.to_rfc3339(); @@ -733,7 +740,7 @@ async fn get_time( }; let json = serde_json::to_string(&data)?; - anyhow::Ok(Some(json)) + Ok(Some(json)) } #[embassy_executor::task] @@ -943,8 +950,8 @@ pub async fn httpd(reboot_now: Arc, stack: Stack<'static>) { async fn handle_json<'a, T, const N: usize>( conn: &mut Connection<'a, T, N>, - chain: anyhow::Result>, -) -> anyhow::Result> + chain: FatResult>, +) -> FatResult where T: Read + Write, ::Error: Debug, diff --git a/rust/src_webpack/package-lock.json b/rust/src_webpack/package-lock.json index 4ff941a..26340b5 100644 --- a/rust/src_webpack/package-lock.json +++ b/rust/src_webpack/package-lock.json @@ -10,6 +10,7 @@ "source-map-loader": "^4.0.1" }, "devDependencies": { + "compression-webpack-plugin": "^11.1.0", "html-webpack-harddisk-plugin": "^2.0.0", "html-webpack-plugin": "^5.6.3", "raw-loader": "^4.0.2", @@ -25,22 +26,19 @@ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -52,19 +50,10 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -72,15 +61,15 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -104,17 +93,75 @@ "tslib": "2" } }, + "node_modules/@jsonjoy.com/buffers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.0.0.tgz", + "integrity": "sha512-NDigYR3PHqCnQLXYyoLbnEdzMMvzeiCWo1KOut7Q0CoIqg9tUAPKJ1iq/2nFhc5kZtexzutNY0LFjdwWL3Dw3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, "node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", - "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.14.0.tgz", + "integrity": "sha512-LpWbYgVnKzphN5S6uss4M25jJ/9+m6q6UJoeN6zTkK4xAGhKsiBRPVeF7OYMWonn5repMQbE5vieRXcMUrKDKw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.1", + "@jsonjoy.com/util": "^1.9.0", "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" }, "engines": { "node": ">=10.0" @@ -128,11 +175,15 @@ } }, "node_modules/@jsonjoy.com/util": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz", - "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, "engines": { "node": ">=10.0" }, @@ -199,9 +250,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, "license": "MIT", "dependencies": { @@ -241,9 +292,10 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -253,21 +305,22 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -278,19 +331,6 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", - "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/express/node_modules/@types/express-serve-static-core": { "version": "4.19.6", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", @@ -311,16 +351,16 @@ "license": "MIT" }, "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, "license": "MIT" }, "node_modules/@types/http-proxy": { - "version": "1.17.15", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz", - "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==", + "version": "1.17.16", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", + "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", "dev": true, "license": "MIT", "dependencies": { @@ -330,7 +370,8 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" }, "node_modules/@types/mime": { "version": "1.3.5", @@ -340,17 +381,18 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", - "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "version": "24.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", + "integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~7.12.0" } }, "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", "dev": true, "license": "MIT", "dependencies": { @@ -358,9 +400,9 @@ } }, "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "dev": true, "license": "MIT" }, @@ -379,9 +421,9 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", "dev": true, "license": "MIT", "dependencies": { @@ -400,9 +442,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -422,9 +464,9 @@ } }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { @@ -582,6 +624,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.15.0" }, @@ -595,6 +638,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.15.0" }, @@ -608,6 +652,7 @@ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.15.0" }, @@ -633,12 +678,6 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "license": "Apache-2.0" }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead" - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -664,9 +703,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -675,15 +714,28 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", "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" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -707,34 +759,16 @@ } } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "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" + "ajv": "^8.8.2" } }, "node_modules/ansi-html-community": { @@ -797,6 +831,15 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", + "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -884,20 +927,21 @@ "license": "ISC" }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "funding": [ { "type": "opencollective", @@ -914,10 +958,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -958,18 +1003,29 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -990,9 +1046,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001687", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", - "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", + "version": "1.0.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "funding": [ { "type": "opencollective", @@ -1051,10 +1107,24 @@ "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", "engines": { "node": ">=6.0" } @@ -1072,21 +1142,12 @@ "node": ">= 10.0" } }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, + "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -1120,13 +1181,18 @@ "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } }, "node_modules/compressible": { "version": "2.0.18", @@ -1142,9 +1208,9 @@ } }, "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "dev": true, "license": "MIT", "dependencies": { @@ -1152,7 +1218,7 @@ "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -1160,6 +1226,27 @@ "node": ">= 0.8.0" } }, + "node_modules/compression-webpack-plugin": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-11.1.0.tgz", + "integrity": "sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -1234,71 +1321,6 @@ "webpack": "^5.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/copy-webpack-plugin/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==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -1307,10 +1329,11 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1338,9 +1361,9 @@ } }, "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -1390,24 +1413,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -1542,6 +1547,21 @@ "tslib": "^2.0.3" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1550,9 +1570,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.72", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz", - "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==", + "version": "1.5.222", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", + "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", "license": "ISC" }, "node_modules/emojis-list": { @@ -1576,9 +1596,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -1599,10 +1619,11 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", "dev": true, + "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, @@ -1611,14 +1632,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -1634,9 +1652,23 @@ } }, "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/escalade": { "version": "3.2.0", @@ -1658,6 +1690,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -1670,6 +1703,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1681,6 +1715,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1689,6 +1724,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1714,14 +1750,15 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "license": "MIT", "dependencies": { @@ -1744,7 +1781,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -1759,12 +1796,17 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" }, "node_modules/fast-equals": { "version": "5.2.2", @@ -1776,30 +1818,54 @@ } }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { @@ -1807,14 +1873,15 @@ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.9.1" } }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -1834,9 +1901,10 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1868,6 +1936,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1881,14 +1950,15 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "dev": true, "funding": [ { @@ -1926,27 +1996,48 @@ "node": ">= 0.6" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1955,16 +2046,47 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + } + }, + "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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regex.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.0.1.tgz", + "integrity": "sha512-CG/iEvgQqfzoVsMUbxSJcwbG2JwyZ3naEqPkeltwl0BSS8Bp83k3xlGms+0QdWFUAwV+uvo80wNswKF6FWEkKg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, "node_modules/glob-to-regexp": { @@ -1974,17 +2096,17 @@ "license": "BSD-2-Clause" }, "node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" + "unicorn-magic": "^0.3.0" }, "engines": { "node": ">=18" @@ -2009,7 +2131,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/handle-thing": { "version": "2.0.1", @@ -2022,39 +2145,11 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", - "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -2069,10 +2164,11 @@ } }, "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -2136,23 +2232,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, "node_modules/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -2175,16 +2254,6 @@ "node": ">=12" } }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/html-webpack-harddisk-plugin": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-webpack-harddisk-plugin/-/html-webpack-harddisk-plugin-2.0.0.tgz", @@ -2200,9 +2269,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", - "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.4.tgz", + "integrity": "sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==", "dev": true, "license": "MIT", "dependencies": { @@ -2277,9 +2346,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", "dev": true, "license": "MIT" }, @@ -2299,9 +2368,9 @@ } }, "node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2337,6 +2406,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -2345,19 +2415,20 @@ } }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, + "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -2384,6 +2455,7 @@ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -2412,12 +2484,16 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2480,9 +2556,9 @@ } }, "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", "dev": true, "license": "MIT", "engines": { @@ -2496,6 +2572,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -2518,6 +2595,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, + "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, @@ -2552,13 +2630,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -2595,12 +2675,14 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", @@ -2620,25 +2702,27 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", + "integrity": "sha512-SEET7oNfgSaB6Ym0jufAdCeo3meJVeCaaDyzRygy0xsp2BFKCprcfHljTq4QkzTLUxEKkFK6OK4811YM2oSrRg==", "dev": true, "license": "MIT", "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" } }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", "engines": { "node": ">=6.11.5" } @@ -2663,6 +2747,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -2687,6 +2772,16 @@ "tslib": "^2.0.3" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -2698,15 +2793,17 @@ } }, "node_modules/memfs": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.14.1.tgz", - "integrity": "sha512-Fq5CMEth+2iprLJ5mNizRcWuiwRZYjNkUD0zKk224jZunE9CRacTRDK8QLALbMBlNX2y3nY6lKZbesCwDwacig==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.42.0.tgz", + "integrity": "sha512-RG+4HMGyIVp6UWDWbFmZ38yKrSzblPnfJu0PyPt0hw52KW4PPlPp+HdV4qZBG0hLDuYVnf8wfQT4NymKXnlQjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.3.0", - "tree-dump": "^1.0.1", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", "tslib": "^2.0.0" }, "engines": { @@ -2753,11 +2850,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -2781,6 +2879,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2789,6 +2888,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2837,7 +2937,8 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" }, "node_modules/no-case": { "version": "3.0.4", @@ -2861,9 +2962,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "license": "MIT" }, "node_modules/normalize-path": { @@ -2889,9 +2990,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { @@ -2922,9 +3023,9 @@ } }, "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, "license": "MIT", "engines": { @@ -2932,16 +3033,16 @@ } }, "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "dev": true, "license": "MIT", "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" + "wsl-utils": "^0.1.0" }, "engines": { "node": ">=18" @@ -2955,6 +3056,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -2970,6 +3072,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -3000,6 +3103,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3041,6 +3145,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3050,6 +3155,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3058,22 +3164,23 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, "license": "MIT" }, "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3089,6 +3196,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -3101,6 +3209,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, + "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, @@ -3154,6 +3263,8 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -3198,6 +3309,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -3262,6 +3374,59 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "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/raw-loader/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==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -3295,6 +3460,7 @@ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, + "license": "MIT", "dependencies": { "resolve": "^1.20.0" }, @@ -3343,18 +3509,22 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3364,6 +3534,7 @@ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, + "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, @@ -3376,6 +3547,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3391,9 +3563,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -3401,9 +3573,9 @@ } }, "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "dev": true, "license": "MIT", "engines": { @@ -3453,21 +3625,25 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 10.13.0" @@ -3499,9 +3675,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -3647,24 +3823,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3677,6 +3835,7 @@ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, + "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, @@ -3689,6 +3848,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -3701,14 +3861,15 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { @@ -3719,16 +3880,73 @@ } }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -3762,13 +3980,12 @@ } }, "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, "node_modules/source-map-js": { @@ -3781,11 +3998,11 @@ } }, "node_modules/source-map-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", - "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.2.tgz", + "integrity": "sha512-oYwAqCuL0OZhBoSgmdrLa7mv9MjommVMiQIWgcztf+eS4+8BfcUee6nenFnDhKOhzAVnk5gpZdfnz1iiBv+5sg==", + "license": "MIT", "dependencies": { - "abab": "^2.0.6", "iconv-lite": "^0.6.3", "source-map-js": "^1.0.2" }, @@ -3810,15 +4027,6 @@ "source-map": "^0.6.0" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -3852,9 +4060,9 @@ } }, "node_modules/spdy-transport/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -3877,9 +4085,9 @@ "license": "MIT" }, "node_modules/spdy/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -3952,6 +4160,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3960,21 +4169,26 @@ } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", + "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { - "version": "5.37.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", - "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", + "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -3986,16 +4200,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -4019,15 +4233,25 @@ } } }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, "node_modules/thingies": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", - "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", "dev": true, - "license": "Unlicense", + "license": "MIT", "engines": { "node": ">=10.18" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, "peerDependencies": { "tslib": "^2" } @@ -4043,6 +4267,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -4061,9 +4286,9 @@ } }, "node_modules/tree-dump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", - "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4078,9 +4303,9 @@ } }, "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "version": "9.5.4", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.4.tgz", + "integrity": "sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4098,6 +4323,16 @@ "webpack": "^5.0.0" } }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -4120,10 +4355,11 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", + "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4133,14 +4369,15 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", + "license": "MIT" }, "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "license": "MIT", "engines": { "node": ">=18" @@ -4160,9 +4397,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -4180,7 +4417,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -4193,6 +4430,8 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } @@ -4242,9 +4481,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", @@ -4265,20 +4504,22 @@ } }, "node_modules/webpack": { - "version": "5.97.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", - "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "version": "5.101.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", + "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", + "enhanced-resolve": "^5.17.3", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", @@ -4288,11 +4529,11 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", + "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -4315,6 +4556,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", "dev": true, + "license": "MIT", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^2.1.1", @@ -4360,20 +4602,21 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, + "license": "MIT", "engines": { "node": ">=14" } }, "node_modules/webpack-dev-middleware": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", - "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.3.tgz", + "integrity": "sha512-5kA/PzpZzDz5mNOkcNLmU1UdjGeSSxd7rt1akWpI70jMNHLASiBPRaQZn0hgyhvhawfIwSnnLfDABIxL3ueyFg==", "dev": true, "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^4.6.0", - "mime-types": "^2.1.31", + "mime-types": "^3.0.1", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" @@ -4394,73 +4637,40 @@ } } }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 0.6" } }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 0.6" } }, "node_modules/webpack-dev-server": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", - "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", "dependencies": { "@types/bonjour": "^3.5.13", "@types/connect-history-api-fallback": "^1.5.4", "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", "@types/serve-index": "^1.9.4", "@types/serve-static": "^1.15.5", "@types/sockjs": "^0.3.36", @@ -4471,10 +4681,9 @@ "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "express": "^4.19.2", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", + "http-proxy-middleware": "^2.0.9", "ipaddr.js": "^2.1.0", "launch-editor": "^2.6.1", "open": "^10.0.3", @@ -4509,68 +4718,12 @@ } } }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, + "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", @@ -4581,9 +4734,10 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", "engines": { "node": ">=10.13.0" } @@ -4618,6 +4772,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -4632,12 +4787,13 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, "license": "MIT", "engines": { @@ -4655,6 +4811,22 @@ "optional": true } } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/rust/src_webpack/package.json b/rust/src_webpack/package.json index 9deae38..df2ab8f 100644 --- a/rust/src_webpack/package.json +++ b/rust/src_webpack/package.json @@ -1,5 +1,6 @@ { "devDependencies": { + "compression-webpack-plugin": "^11.1.0", "html-webpack-harddisk-plugin": "^2.0.0", "html-webpack-plugin": "^5.6.3", "raw-loader": "^4.0.2", diff --git a/rust/src_webpack/webpack.config.js b/rust/src_webpack/webpack.config.js index 61466fa..762059b 100644 --- a/rust/src_webpack/webpack.config.js +++ b/rust/src_webpack/webpack.config.js @@ -3,54 +3,60 @@ const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin'); const CopyPlugin = require("copy-webpack-plugin"); +const CompressionPlugin = require("compression-webpack-plugin"); const isDevServer = process.env.WEBPACK_SERVE; console.log("Dev server is " + isDevServer); var host; -if (isDevServer){ - //ensure no trailing / - host = 'http://10.23.44.186'; +if (isDevServer) { + //ensure no trailing / + host = 'http://10.23.44.186'; } else { - host = ''; + host = ''; } module.exports = { - mode: "development", - entry: ['./src/main.ts'], - devtool: 'inline-source-map', - plugins: [ - new webpack.DefinePlugin({ - PUBLIC_URL: JSON.stringify(host), - }), - new webpack.EnvironmentPlugin({ - redirect: 'true' - }), - new HtmlWebpackPlugin({ - alwaysWriteToDisk: true, - title: "PlantCtrl", - }), - new HtmlWebpackHarddiskPlugin(), - ], - module: { - rules: [ - { - test: /\.html$/, - type: 'asset/source', - }, - { - test: /\.tsx?$/, - use: 'ts-loader', - exclude: /node_modules/, - } - ] - }, - resolve: { - extensions: ['.tsx', '.ts', '.js', '.html'], - }, - output: { - filename: 'bundle.js', - path: path.resolve(__dirname, '.'), - }, - devServer: { - } + mode: "development", + entry: ['./src/main.ts'], + devtool: 'inline-source-map', + plugins: [ + new webpack.DefinePlugin({ + PUBLIC_URL: JSON.stringify(host), + }), + new webpack.EnvironmentPlugin({ + redirect: 'true' + }), + new HtmlWebpackPlugin({ + alwaysWriteToDisk: true, + title: "PlantCtrl", + }), + new HtmlWebpackHarddiskPlugin(), + new CompressionPlugin({ + algorithm: "gzip", + test: /\.js$|\.css$|\.html$/, + threshold: 0, + minRatio: 0.8 + }) + ], + module: { + rules: [ + { + test: /\.html$/, + type: 'asset/source', + }, + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + } + ] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js', '.html'], + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, '.'), + }, + devServer: {} };