diff --git a/.sqlx/query-0648b5c0e4d4a4cd922ccaef80e06ff43f8ff063a6772586b79f1c524a848554.json b/.sqlx/query-0648b5c0e4d4a4cd922ccaef80e06ff43f8ff063a6772586b79f1c524a848554.json new file mode 100644 index 000000000..8afd59ce0 --- /dev/null +++ b/.sqlx/query-0648b5c0e4d4a4cd922ccaef80e06ff43f8ff063a6772586b79f1c524a848554.json @@ -0,0 +1,52 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, \"network_id\",\"url\",\"hostname\",\"connected_at\",\"disconnected_at\" FROM \"gateway\" WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "network_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "url", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "connected_at", + "type_info": "Timestamp" + }, + { + "ordinal": 5, + "name": "disconnected_at", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + true, + true, + true + ] + }, + "hash": "0648b5c0e4d4a4cd922ccaef80e06ff43f8ff063a6772586b79f1c524a848554" +} diff --git a/.sqlx/query-0cd356bb88839bcc76d1fe3ed26719811a7c80e0954d6024f00b5ef883aeab3d.json b/.sqlx/query-0cd356bb88839bcc76d1fe3ed26719811a7c80e0954d6024f00b5ef883aeab3d.json new file mode 100644 index 000000000..9476d09d1 --- /dev/null +++ b/.sqlx/query-0cd356bb88839bcc76d1fe3ed26719811a7c80e0954d6024f00b5ef883aeab3d.json @@ -0,0 +1,50 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, \"network_id\",\"url\",\"hostname\",\"connected_at\",\"disconnected_at\" FROM \"gateway\"", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "network_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "url", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "connected_at", + "type_info": "Timestamp" + }, + { + "ordinal": 5, + "name": "disconnected_at", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false, + false, + true, + true, + true + ] + }, + "hash": "0cd356bb88839bcc76d1fe3ed26719811a7c80e0954d6024f00b5ef883aeab3d" +} diff --git a/.sqlx/query-1403aba7198c132812aa5642166e70c14b3c40a969b496972d499a975fb7b0b4.json b/.sqlx/query-140ed5c4dfb4e42aea2e349f73ae8645c9d47dd5b5810ac32aae572d58d39a5e.json similarity index 80% rename from .sqlx/query-1403aba7198c132812aa5642166e70c14b3c40a969b496972d499a975fb7b0b4.json rename to .sqlx/query-140ed5c4dfb4e42aea2e349f73ae8645c9d47dd5b5810ac32aae572d58d39a5e.json index b753d65e6..2419b35b6 100644 --- a/.sqlx/query-1403aba7198c132812aa5642166e70c14b3c40a969b496972d499a975fb7b0b4.json +++ b/.sqlx/query-140ed5c4dfb4e42aea2e349f73ae8645c9d47dd5b5810ac32aae572d58d39a5e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "WITH stats AS ( SELECT DISTINCT ON (network) network, endpoint, latest_handshake FROM wireguard_peer_stats WHERE device_id = $2 ORDER BY network, collected_at DESC ) SELECT n.id network_id, n.name network_name, n.endpoint gateway_endpoint, wnd.wireguard_ip \"device_wireguard_ip: IpAddr\", stats.endpoint device_endpoint, stats.latest_handshake \"latest_handshake?\", COALESCE (((NOW() - stats.latest_handshake) < $1 * interval '1 minute'), false) as \"is_active!\" FROM wireguard_network_device wnd JOIN wireguard_network n ON n.id = wnd.wireguard_network_id LEFT JOIN stats on n.id = stats.network WHERE wnd.device_id = $2", + "query": "WITH stats AS ( SELECT DISTINCT ON (network) network, endpoint, latest_handshake FROM wireguard_peer_stats WHERE device_id = $2 ORDER BY network, collected_at DESC ) SELECT n.id network_id, n.name network_name, n.endpoint gateway_endpoint, wnd.wireguard_ip \"device_wireguard_ip: IpAddr\", stats.endpoint device_endpoint, stats.latest_handshake \"latest_handshake?\", COALESCE (((NOW() - stats.latest_handshake) < $1 * interval '1m'), false) as \"is_active!\" FROM wireguard_network_device wnd JOIN wireguard_network n ON n.id = wnd.wireguard_network_id LEFT JOIN stats on n.id = stats.network WHERE wnd.device_id = $2", "describe": { "columns": [ { @@ -55,5 +55,5 @@ null ] }, - "hash": "1403aba7198c132812aa5642166e70c14b3c40a969b496972d499a975fb7b0b4" + "hash": "140ed5c4dfb4e42aea2e349f73ae8645c9d47dd5b5810ac32aae572d58d39a5e" } diff --git a/.sqlx/query-15ba55bedd1260fe39d7190aa75bb1070bc4977a20e89042385fbc55711075c3.json b/.sqlx/query-15ba55bedd1260fe39d7190aa75bb1070bc4977a20e89042385fbc55711075c3.json new file mode 100644 index 000000000..48067fcd2 --- /dev/null +++ b/.sqlx/query-15ba55bedd1260fe39d7190aa75bb1070bc4977a20e89042385fbc55711075c3.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT name FROM wireguard_network WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false + ] + }, + "hash": "15ba55bedd1260fe39d7190aa75bb1070bc4977a20e89042385fbc55711075c3" +} diff --git a/.sqlx/query-1a4f2c99da8a0db6208abdfaf7e21950b9cb440f20904802a56cdebf2339d481.json b/.sqlx/query-1a4f2c99da8a0db6208abdfaf7e21950b9cb440f20904802a56cdebf2339d481.json new file mode 100644 index 000000000..e02b54b47 --- /dev/null +++ b/.sqlx/query-1a4f2c99da8a0db6208abdfaf7e21950b9cb440f20904802a56cdebf2339d481.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE wireguard_network SET connected_at = $2 WHERE name = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "1a4f2c99da8a0db6208abdfaf7e21950b9cb440f20904802a56cdebf2339d481" +} diff --git a/.sqlx/query-5c0fd685bdb1c165d74a62f64824948da760fa885ececf72a624f859f73fb38c.json b/.sqlx/query-5c0fd685bdb1c165d74a62f64824948da760fa885ececf72a624f859f73fb38c.json new file mode 100644 index 000000000..522e152b8 --- /dev/null +++ b/.sqlx/query-5c0fd685bdb1c165d74a62f64824948da760fa885ececf72a624f859f73fb38c.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM \"gateway\" WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "5c0fd685bdb1c165d74a62f64824948da760fa885ececf72a624f859f73fb38c" +} diff --git a/.sqlx/query-5d00c03eccbe17efc023bd0c6006e24f24239df0ba778666ca1751c9436aec8e.json b/.sqlx/query-5d00c03eccbe17efc023bd0c6006e24f24239df0ba778666ca1751c9436aec8e.json new file mode 100644 index 000000000..58a9bd507 --- /dev/null +++ b/.sqlx/query-5d00c03eccbe17efc023bd0c6006e24f24239df0ba778666ca1751c9436aec8e.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO \"gateway\" (\"network_id\",\"url\",\"hostname\",\"connected_at\",\"disconnected_at\") VALUES ($1,$2,$3,$4,$5) RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Text", + "Text", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [ + false + ] + }, + "hash": "5d00c03eccbe17efc023bd0c6006e24f24239df0ba778666ca1751c9436aec8e" +} diff --git a/.sqlx/query-0e9a8c2395d43898748c176db0d89fa20784cd93ca1dfd00b2755934937d8270.json b/.sqlx/query-89c6cd12cbf91f5b504df0dd8861f87c3d6eec3665cfb338df1b45f0822fc1ce.json similarity index 82% rename from .sqlx/query-0e9a8c2395d43898748c176db0d89fa20784cd93ca1dfd00b2755934937d8270.json rename to .sqlx/query-89c6cd12cbf91f5b504df0dd8861f87c3d6eec3665cfb338df1b45f0822fc1ce.json index 25c3f61e0..25e8b614c 100644 --- a/.sqlx/query-0e9a8c2395d43898748c176db0d89fa20784cd93ca1dfd00b2755934937d8270.json +++ b/.sqlx/query-89c6cd12cbf91f5b504df0dd8861f87c3d6eec3665cfb338df1b45f0822fc1ce.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "WITH stats AS ( SELECT DISTINCT ON (device_id) device_id, endpoint, latest_handshake FROM wireguard_peer_stats WHERE network = $1 ORDER BY device_id, collected_at DESC ) SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created FROM device d JOIN wireguard_network_device wnd ON wnd.device_id = d.id LEFT JOIN stats on d.id = stats.device_id WHERE wnd.wireguard_network_id = $1 AND wnd.is_authorized = true AND (wnd.authorized_at IS NULL OR (NOW() - wnd.authorized_at) > $2 * interval '1 second') AND (stats.latest_handshake IS NULL OR (NOW() - stats.latest_handshake) > $2 * interval '1 second')", + "query": "WITH stats AS ( SELECT DISTINCT ON (device_id) device_id, endpoint, latest_handshake FROM wireguard_peer_stats WHERE network = $1 ORDER BY device_id, collected_at DESC ) SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created FROM device d JOIN wireguard_network_device wnd ON wnd.device_id = d.id LEFT JOIN stats on d.id = stats.device_id WHERE wnd.wireguard_network_id = $1 AND wnd.is_authorized = true AND (wnd.authorized_at IS NULL OR (NOW() - wnd.authorized_at) > $2 * interval '1s') AND (stats.latest_handshake IS NULL OR (NOW() - stats.latest_handshake) > $2 * interval '1s')", "describe": { "columns": [ { @@ -43,5 +43,5 @@ false ] }, - "hash": "0e9a8c2395d43898748c176db0d89fa20784cd93ca1dfd00b2755934937d8270" + "hash": "89c6cd12cbf91f5b504df0dd8861f87c3d6eec3665cfb338df1b45f0822fc1ce" } diff --git a/.sqlx/query-06d1ac982dc99c5dae010089cfb73a044397c5cb6bb9654dc5df420bf00d2955.json b/.sqlx/query-9cc07a695832c444bbc66fe38c49638b98025f0471a34c949f3e0935818e080b.json similarity index 74% rename from .sqlx/query-06d1ac982dc99c5dae010089cfb73a044397c5cb6bb9654dc5df420bf00d2955.json rename to .sqlx/query-9cc07a695832c444bbc66fe38c49638b98025f0471a34c949f3e0935818e080b.json index e2fcfb80f..53cd365de 100644 --- a/.sqlx/query-06d1ac982dc99c5dae010089cfb73a044397c5cb6bb9654dc5df420bf00d2955.json +++ b/.sqlx/query-9cc07a695832c444bbc66fe38c49638b98025f0471a34c949f3e0935818e080b.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT latest_handshake \"latest_handshake: NaiveDateTime\" FROM wireguard_peer_stats_view WHERE device_id = $1 AND latest_handshake IS NOT NULL AND (latest_handshake_diff > $2 * interval '1 minute' OR latest_handshake_diff IS NULL) AND network = $3 ORDER BY collected_at DESC LIMIT 1", + "query": "SELECT latest_handshake \"latest_handshake: NaiveDateTime\" FROM wireguard_peer_stats_view WHERE device_id = $1 AND latest_handshake IS NOT NULL AND (latest_handshake_diff > $2 * interval '1m' OR latest_handshake_diff IS NULL) AND network = $3 ORDER BY collected_at DESC LIMIT 1", "describe": { "columns": [ { @@ -20,5 +20,5 @@ true ] }, - "hash": "06d1ac982dc99c5dae010089cfb73a044397c5cb6bb9654dc5df420bf00d2955" + "hash": "9cc07a695832c444bbc66fe38c49638b98025f0471a34c949f3e0935818e080b" } diff --git a/.sqlx/query-b3cae8e4b2468e9b0ae88ef135729532ee95c54bc1343706bc61d9e4bceed4d4.json b/.sqlx/query-b3cae8e4b2468e9b0ae88ef135729532ee95c54bc1343706bc61d9e4bceed4d4.json new file mode 100644 index 000000000..85b60b0fb --- /dev/null +++ b/.sqlx/query-b3cae8e4b2468e9b0ae88ef135729532ee95c54bc1343706bc61d9e4bceed4d4.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE gateway SET hostname = $2, connected_at = $3 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Text", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "b3cae8e4b2468e9b0ae88ef135729532ee95c54bc1343706bc61d9e4bceed4d4" +} diff --git a/.sqlx/query-c0b17ec0369d1286c82515cef2e2db17b3b9754bb28b66bf001f0a3aa2655839.json b/.sqlx/query-c0b17ec0369d1286c82515cef2e2db17b3b9754bb28b66bf001f0a3aa2655839.json new file mode 100644 index 000000000..1c9ce0004 --- /dev/null +++ b/.sqlx/query-c0b17ec0369d1286c82515cef2e2db17b3b9754bb28b66bf001f0a3aa2655839.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE gateway SET disconnected_at = $2 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "c0b17ec0369d1286c82515cef2e2db17b3b9754bb28b66bf001f0a3aa2655839" +} diff --git a/.sqlx/query-d10c9a7b0b391aeb8b4869f6bddf997807b66e0b532da747b146513c34e15c5c.json b/.sqlx/query-d10c9a7b0b391aeb8b4869f6bddf997807b66e0b532da747b146513c34e15c5c.json new file mode 100644 index 000000000..6fa095298 --- /dev/null +++ b/.sqlx/query-d10c9a7b0b391aeb8b4869f6bddf997807b66e0b532da747b146513c34e15c5c.json @@ -0,0 +1,52 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT * FROM gateway WHERE network_id = $1 ORDER BY id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "network_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "url", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "hostname", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "connected_at", + "type_info": "Timestamp" + }, + { + "ordinal": 5, + "name": "disconnected_at", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + false, + false, + false, + true, + true, + true + ] + }, + "hash": "d10c9a7b0b391aeb8b4869f6bddf997807b66e0b532da747b146513c34e15c5c" +} diff --git a/.sqlx/query-dbcf7be91c6a4c92e865e35d565cf3da8e12f7179da8cb42fa0446b224f9dec4.json b/.sqlx/query-dbcf7be91c6a4c92e865e35d565cf3da8e12f7179da8cb42fa0446b224f9dec4.json new file mode 100644 index 000000000..f5f9307d7 --- /dev/null +++ b/.sqlx/query-dbcf7be91c6a4c92e865e35d565cf3da8e12f7179da8cb42fa0446b224f9dec4.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE \"gateway\" SET \"network_id\" = $2,\"url\" = $3,\"hostname\" = $4,\"connected_at\" = $5,\"disconnected_at\" = $6 WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8", + "Int8", + "Text", + "Text", + "Timestamp", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "dbcf7be91c6a4c92e865e35d565cf3da8e12f7179da8cb42fa0446b224f9dec4" +} diff --git a/Cargo.lock b/Cargo.lock index 0a8671c16..8a5320a62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -111,49 +111,49 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] @@ -234,7 +234,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -245,7 +245,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -257,6 +257,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "auto_impl" version = "1.2.0" @@ -265,7 +271,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -274,34 +280,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower 0.4.13", - "tower-layer", - "tower-service", -] - [[package]] name = "axum" version = "0.7.7" @@ -309,13 +287,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" dependencies = [ "async-trait", - "axum-core 0.4.5", + "axum-core", "bytes", "futures-util", "http 1.1.0", "http-body 1.0.1", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "itoa", "matchit", @@ -342,28 +320,11 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e7c467bdcd2bd982ce5c8742a1a178aba7b03db399fd18f5d5d438f5aa91cb4" dependencies = [ - "axum 0.7.7", + "axum", "forwarded-header-value", "serde", ] -[[package]] -name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.12", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "axum-core" version = "0.4.5" @@ -391,8 +352,8 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73c3220b188aea709cf1b6c5f9b01c3bd936bb08bd2b5184a12b35ac8131b1f9" dependencies = [ - "axum 0.7.7", - "axum-core 0.4.5", + "axum", + "axum-core", "bytes", "cookie 0.18.1", "futures-util", @@ -591,9 +552,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" dependencies = [ "serde", ] @@ -619,9 +580,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.24" +version = "1.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" +checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" dependencies = [ "jobserver", "libc", @@ -711,9 +672,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -721,9 +682,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -740,7 +701,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -762,9 +723,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "compact_jwt" @@ -1031,7 +992,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1055,7 +1016,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1066,7 +1027,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1090,7 +1051,7 @@ version = "1.0.0" dependencies = [ "anyhow", "argon2", - "axum 0.7.7", + "axum", "axum-client-ip", "axum-extra", "base32", @@ -1102,6 +1063,7 @@ dependencies = [ "dotenvy", "ethers-core", "humantime", + "hyper-util", "ipnetwork", "jsonwebtoken", "ldap3", @@ -1118,7 +1080,7 @@ dependencies = [ "rand", "rand_core", "regex", - "reqwest 0.11.27", + "reqwest", "rsa", "rust-embed", "rust-ini", @@ -1143,6 +1105,7 @@ dependencies = [ "tonic-build", "tonic-health", "totp-lite", + "tower 0.5.1", "tower-http", "tracing", "tracing-subscriber", @@ -1194,44 +1157,44 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "derive_builder" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "derive_builder_macro" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1244,7 +1207,27 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.79", + "syn 2.0.87", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] @@ -1282,7 +1265,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -1421,9 +1404,9 @@ checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] @@ -1593,9 +1576,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -1650,9 +1633,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1665,9 +1648,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1675,15 +1658,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1703,38 +1686,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1793,9 +1776,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git2" @@ -1864,6 +1847,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.3" @@ -1888,9 +1890,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hashlink" @@ -2072,15 +2074,15 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.30" +version = "0.14.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2096,13 +2098,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.1", "httparse", @@ -2122,40 +2125,23 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.30", + "hyper 0.14.31", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", ] -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http 1.1.0", - "hyper 1.4.1", - "hyper-util", - "rustls 0.23.13", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.0", - "tower-service", - "webpki-roots 0.26.6", -] - [[package]] name = "hyper-timeout" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 0.14.30", + "hyper 1.5.0", + "hyper-util", "pin-project-lite", "tokio", - "tokio-io-timeout", + "tower-service", ] [[package]] @@ -2165,7 +2151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.30", + "hyper 0.14.31", "native-tls", "tokio", "tokio-native-tls", @@ -2173,16 +2159,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.1", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite", "socket2", "tokio", @@ -2328,7 +2314,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2358,24 +2344,23 @@ dependencies = [ [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "idna" -version = "1.0.2" +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd69211b9b519e98303c015e21a007e293db403b6c85b9b124e133d25e242cdd" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", - "smallvec", - "utf8_iter", ] [[package]] @@ -2450,7 +2435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.1", "serde", ] @@ -2465,9 +2450,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "ipnetwork" @@ -2501,9 +2486,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2525,9 +2510,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -2615,9 +2600,9 @@ dependencies = [ [[package]] name = "lettre" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f204773bab09b150320ea1c83db41dc6ee606a4bc36dc1f43005fe7b58ce06" +checksum = "0161e452348e399deb685ba05e55ee116cae9410f4f51fe42d597361444521d9" dependencies = [ "async-trait", "base64 0.22.1", @@ -2629,7 +2614,7 @@ dependencies = [ "futures-util", "hostname", "httpdate", - "idna 1.0.2", + "idna 1.0.3", "mime", "native-tls", "nom", @@ -2643,9 +2628,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libgit2-sys" @@ -2661,9 +2646,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libsqlite3-sys" @@ -2710,6 +2695,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "log" version = "0.4.22" @@ -2810,7 +2801,7 @@ name = "model_derive" version = "0.2.0" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2955,7 +2946,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -2978,7 +2969,7 @@ dependencies = [ "getrandom", "http 0.2.12", "rand", - "reqwest 0.11.27", + "reqwest", "serde", "serde_json", "serde_path_to_error", @@ -2989,9 +2980,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] @@ -3019,12 +3010,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -3091,9 +3079,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -3112,7 +3100,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3123,9 +3111,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -3304,9 +3292,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -3315,9 +3303,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -3325,22 +3313,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "pest_meta" -version = "2.7.13" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -3461,29 +3449,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3530,12 +3518,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - [[package]] name = "powerfmt" version = "0.2.0" @@ -3553,12 +3535,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -3593,35 +3575,11 @@ dependencies = [ "toml_edit", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -3644,9 +3602,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" dependencies = [ "bytes", "prost-derive", @@ -3654,13 +3612,13 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", "heck", - "itertools 0.12.1", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -3669,28 +3627,28 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.79", + "syn 2.0.87", "tempfile", ] [[package]] name = "prost-derive" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "prost-types" -version = "0.12.6" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" dependencies = [ "prost", ] @@ -3722,9 +3680,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.11.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" dependencies = [ "bitflags 2.6.0", "getopts", @@ -3739,54 +3697,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" -[[package]] -name = "quinn" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls 0.23.13", - "socket2", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls 0.23.13", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" -dependencies = [ - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - [[package]] name = "quote" version = "1.0.37" @@ -3858,9 +3768,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -3913,11 +3823,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.30", - "hyper-rustls 0.24.2", + "hyper 0.14.31", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -3945,53 +3855,10 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.4", + "webpki-roots", "winreg", ] -[[package]] -name = "reqwest" -version = "0.12.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http 1.1.0", - "http-body 1.0.1", - "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.3", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls 0.23.13", - "rustls-pemfile 2.2.0", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 1.0.1", - "tokio", - "tokio-rustls 0.26.0", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.26.6", - "windows-registry", -] - [[package]] name = "rfc6979" version = "0.4.0" @@ -4089,7 +3956,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.79", + "syn 2.0.87", "walkdir", ] @@ -4120,12 +3987,6 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - [[package]] name = "rustc-hex" version = "2.1.0" @@ -4152,9 +4013,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.37" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags 2.6.0", "errno", @@ -4177,24 +4038,11 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" dependencies = [ "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" -version = "0.23.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" -dependencies = [ "once_cell", "ring", "rustls-pki-types", @@ -4205,9 +4053,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", "rustls-pemfile 2.2.0", @@ -4236,9 +4084,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-webpki" @@ -4263,9 +4111,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -4284,33 +4132,33 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.3" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +checksum = "1aa7ffc1c0ef49b0452c6e2986abf2b07743320641ffd5fc63d552458e3b779b" dependencies = [ "cfg-if", - "derive_more", + "derive_more 1.0.0", "parity-scale-codec", "scale-info-derive", ] [[package]] name = "scale-info-derive" -version = "2.11.3" +version = "2.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +checksum = "46385cc24172cf615450267463f937c10072516359b3ff1cb24228a4a08bf951" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -4405,9 +4253,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] @@ -4443,20 +4291,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -4508,9 +4356,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9720086b3357bcb44fce40117d769a4d068c70ecfa190850a980a71755f66fcc" +checksum = "8e28bdad6db2b8340e449f7108f020b3b092e8583a9e3fb82713e1d4e71fe817" dependencies = [ "base64 0.22.1", "chrono", @@ -4526,14 +4374,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f1abbfe725f27678f4663bcacb75a83e829fd464c25d78dd038a3a29e307cec" +checksum = "9d846214a9854ef724f3da161b426242d8de7c1fc7de2f89bb1efcb154dca79d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -4627,6 +4475,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simple_asn1" version = "0.6.2" @@ -4778,7 +4632,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -4801,7 +4655,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.79", + "syn 2.0.87", "tempfile", "tokio", "url", @@ -4940,9 +4794,9 @@ dependencies = [ [[package]] name = "ssh-key" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc" +checksum = "3b86f5297f0f04d08cabaa0f6bff7cb6aec4d9c3b49d87990d63da9d9156a8c3" dependencies = [ "p256", "p384", @@ -5017,7 +4871,7 @@ checksum = "4596646090f0d724e6c7f3b65d694f99a0daa1a5893a78ef83887025e041405c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5039,7 +4893,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5061,9 +4915,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -5081,9 +4935,6 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] [[package]] name = "synstructure" @@ -5105,7 +4956,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5172,22 +5023,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5269,9 +5120,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", @@ -5284,16 +5135,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "2.4.0" @@ -5302,7 +5143,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5325,24 +5166,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.13", + "rustls 0.23.16", "rustls-pki-types", "tokio", ] @@ -5391,29 +5221,31 @@ dependencies = [ [[package]] name = "tonic" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" dependencies = [ "async-stream", "async-trait", - "axum 0.6.20", - "base64 0.21.7", + "axum", + "base64 0.22.1", "bytes", "flate2", - "h2", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", + "h2 0.4.6", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.5.0", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", "prost", "rustls-native-certs", "rustls-pemfile 2.2.0", - "rustls-pki-types", + "socket2", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-stream", "tower 0.4.13", "tower-layer", @@ -5423,22 +5255,23 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" dependencies = [ "prettyplease", "proc-macro2", "prost-build", + "prost-types", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "tonic-health" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cef6e24bc96871001a7e48e820ab240b3de2201e59b517cf52835df2f1d2350" +checksum = "1eaf34ddb812120f5c601162d5429933c9b527d901ab0e7f930d3147e33a09b2" dependencies = [ "async-stream", "prost", @@ -5497,9 +5330,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" dependencies = [ "bitflags 2.6.0", "bytes", @@ -5552,7 +5385,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -5621,7 +5454,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c9e1c3f893758f154004195fc2d2c52fbda462df725220ceaef830ac29affa" dependencies = [ - "derive_more", + "derive_more 0.99.18", "lazy_static", "regex", "serde", @@ -5705,12 +5538,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -5781,12 +5611,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", - "idna 0.5.0", + "idna 1.0.3", "percent-encoding", "serde", ] @@ -5811,9 +5641,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "utoipa" -version = "4.2.3" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +checksum = "514a48569e4e21c86d0b84b5612b5e73c0b2cf09db63260134ba426d4e8ea714" dependencies = [ "indexmap 2.6.0", "serde", @@ -5823,27 +5653,25 @@ dependencies = [ [[package]] name = "utoipa-gen" -version = "4.3.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf0e16c02bc4bf5322ab65f10ab1149bdbcaa782cba66dc7057370a3f8190be" +checksum = "5629efe65599d0ccd5d493688cbf6e03aa7c1da07fe59ff97cf5977ed0637f66" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", "regex", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "utoipa-swagger-ui" -version = "7.1.0" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" +checksum = "a5c80b4dd79ea382e8374d67dcce22b5c6663fa13a82ad3886441d1bbede5e35" dependencies = [ - "axum 0.7.7", + "axum", "mime_guess", "regex", - "reqwest 0.12.8", "rust-embed", "serde", "serde_json", @@ -5854,9 +5682,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", @@ -5952,9 +5780,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -5963,24 +5791,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -5990,9 +5818,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6000,28 +5828,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -6032,9 +5860,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -6144,15 +5972,6 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" -[[package]] -name = "webpki-roots" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "whoami" version = "1.5.2" @@ -6213,36 +6032,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -6481,7 +6270,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure 0.13.1", ] @@ -6503,7 +6292,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -6523,7 +6312,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", "synstructure 0.13.1", ] @@ -6544,7 +6333,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] @@ -6566,14 +6355,14 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.87", ] [[package]] name = "zip" -version = "1.1.4" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" dependencies = [ "arbitrary", "crc32fast", @@ -6581,6 +6370,21 @@ dependencies = [ "displaydoc", "flate2", "indexmap 2.6.0", - "num_enum", + "memchr", "thiserror", + "zopfli", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", ] diff --git a/Cargo.toml b/Cargo.toml index 7e53e12ec..a72140e27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,8 +42,8 @@ openidconnect = { version = "3.5", default-features = false, optional = true, fe "reqwest", ] } pgp = "0.13" -prost = "0.12" -pulldown-cmark = "0.11" +prost = "0.13" +pulldown-cmark = "0.12" rand = "0.8" rand_core = { version = "0.6", default-features = false, features = [ "getrandom", @@ -88,17 +88,17 @@ tokio = { version = "1", features = [ "time", ] } tokio-stream = "0.1" -tonic = { version = "0.11", features = ["gzip", "tls", "tls-roots"] } -tonic-health = "0.11" +tonic = { version = "0.12", features = ["gzip", "tls", "tls-roots"] } +tonic-health = "0.12" totp-lite = { version = "2.0" } -tower-http = { version = "0.5", features = ["fs", "trace"] } +tower-http = { version = "0.6", features = ["fs", "trace"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } uaparser = "0.6" -# openapi -utoipa = { version = "4", features = ["axum_extras"] } -utoipa-swagger-ui = { version = "7", features = ["axum"] } -uuid = { version = "1.9", features = ["v4"] } +# OpenAPI +utoipa = { version = "5.1", features = ["axum_extras", "chrono"] } +utoipa-swagger-ui = { version = "8.0", features = ["axum"] } +uuid = { version = "1.11", features = ["v4"] } webauthn-authenticator-rs = { version = "0.5" } webauthn-rs = { version = "0.5", features = [ "danger-allow-state-serialisation", @@ -107,23 +107,25 @@ webauthn-rs-proto = "0.5" x25519-dalek = { version = "2.0", features = ["static_secrets"] } [dev-dependencies] -bytes = "1.6" +bytes = "1.8" claims = "0.7" +hyper-util = "0.1" matches = "0.1" -regex = "1.10" +regex = "1.11" reqwest = { version = "0.11", features = [ - "json", "cookies", - "stream", + "json", "multipart", "rustls-tls", + "stream", ], default-features = false } serde_qs = "0.13" webauthn-authenticator-rs = { version = "0.5", features = ["softpasskey"] } +tower = { version = "0.5", features = ["util"] } [build-dependencies] -prost-build = "0.12" -tonic-build = "0.11" +prost-build = "0.13" +tonic-build = "0.12" vergen-git2 = { version = "1.0", features = ["build"] } [features] diff --git a/build.rs b/build.rs index 43c2aa4dd..fbd3cdfae 100644 --- a/build.rs +++ b/build.rs @@ -7,25 +7,25 @@ fn main() -> Result<(), Box> { let mut config = prost_build::Config::new(); config.protoc_arg("--experimental_allow_proto3_optional"); - tonic_build::configure().compile_with_config( + tonic_build::configure().compile_protos_with_config( config, &[ "proto/core/auth.proto", "proto/core/proxy.proto", - "proto/core/vpn.proto", "src/enterprise/proto/license.proto", - "proto/worker/worker.proto", "proto/wireguard/gateway.proto", + "proto/worker/worker.proto", ], &[ "proto/core", - "proto/worker", "proto/wireguard", + "proto/worker", "src/enterprise/proto", ], )?; println!("cargo:rerun-if-changed=migrations"); println!("cargo:rerun-if-changed=proto"); println!("cargo:rerun-if-changed=web/dist"); + Ok(()) } diff --git a/migrations/20241015074303_network_gateways.down.sql b/migrations/20241015074303_network_gateways.down.sql new file mode 100644 index 000000000..5e727c02c --- /dev/null +++ b/migrations/20241015074303_network_gateways.down.sql @@ -0,0 +1,3 @@ +DROP TRIGGER gateway ON gateway; +DROP FUNCTION row_change(); +DROP TABLE gateway; diff --git a/migrations/20241015074303_network_gateways.up.sql b/migrations/20241015074303_network_gateways.up.sql new file mode 100644 index 000000000..3db149fd6 --- /dev/null +++ b/migrations/20241015074303_network_gateways.up.sql @@ -0,0 +1,20 @@ +CREATE TABLE gateway ( + id bigserial PRIMARY KEY, + network_id bigint NOT NULL, + url text NOT NULL, + hostname text NULL, + connected_at timestamp without time zone NULL, + disconnected_at timestamp without time zone NULL, + FOREIGN KEY(network_id) REFERENCES wireguard_network(id) +); +CREATE FUNCTION row_change() RETURNS trigger AS $$ +BEGIN + PERFORM pg_notify(TG_TABLE_NAME || '_change', + json_build_object('operation', TG_OP, 'old', row_to_json(OLD), 'new', row_to_json(NEW))::text + ); + RETURN NULL; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER gateway + AFTER INSERT OR UPDATE OR DELETE ON gateway + FOR ROW EXECUTE FUNCTION row_change(); diff --git a/src/appstate.rs b/src/appstate.rs index 78556a756..a85b62e25 100644 --- a/src/appstate.rs +++ b/src/appstate.rs @@ -18,20 +18,24 @@ use webauthn_rs::prelude::*; use crate::{ auth::failed_login::FailedLoginMap, - db::{AppEvent, GatewayEvent, WebHook}, + db::models::{ + webhook::{AppEvent, WebHook}, + wireguard::ChangeEvent, + }, mail::Mail, server_config, }; #[derive(Clone)] -pub struct AppState { +pub(crate) struct AppState { pub pool: PgPool, tx: UnboundedSender, - wireguard_tx: Sender, + events_tx: Sender, pub mail_tx: UnboundedSender, pub webauthn: Arc, pub user_agent_parser: Arc, pub failed_logins: Arc>, + // A key for secret cookies. key: Key, } @@ -44,27 +48,25 @@ impl AppState { } } - /// Handle webhook events + /// Handle webhook events. This is ran on a separate asynchronous task. async fn handle_triggers(pool: PgPool, mut rx: UnboundedReceiver) { let reqwest_client = Client::builder().user_agent("reqwest").build().unwrap(); while let Some(msg) = rx.recv().await { - debug!("WebHook triggered"); - debug!("Retrieving webhooks"); + debug!("Webhook triggered. Retrieving webhooks."); if let Ok(webhooks) = WebHook::all_enabled(&pool, &msg).await { info!("Found webhooks: {webhooks:#?}"); - let (payload, event) = match msg { - AppEvent::UserCreated(user) => (json!(user), "user_created"), - AppEvent::UserModified(user) => (json!(user), "user_modified"), - AppEvent::UserDeleted(username) => { - (json!({ "username": username }), "user_deleted") + let payload = match msg { + AppEvent::UserCreated(ref user) | AppEvent::UserModified(ref user) => { + json!(user) } - AppEvent::HWKeyProvision(data) => (json!(data), "user_keys"), + AppEvent::UserDeleted(ref username) => json!({ "username": username }), + AppEvent::HWKeyProvision(ref data) => json!(data), }; for webhook in webhooks { match reqwest_client .post(&webhook.url) .bearer_auth(&webhook.token) - .header("x-defguard-event", event) + .header("x-defguard-event", msg.name()) .json(&payload) .send() .await @@ -81,18 +83,18 @@ impl AppState { } } - /// Sends given `GatewayEvent` to be handled by gateway GRPC server - pub fn send_wireguard_event(&self, event: GatewayEvent) { - if let Err(err) = self.wireguard_tx.send(event) { - error!("Error sending WireGuard event {err}"); + /// Sends given `ChangeEvent` to be handled by gateway (over gRPC). + pub(crate) fn send_change_event(&self, event: ChangeEvent) { + if let Err(err) = self.events_tx.send(event) { + error!("Error sending change event {err}"); } } - /// Sends multiple events to be handled by gateway GRPC server - pub fn send_multiple_wireguard_events(&self, events: Vec) { - debug!("Sending {} wireguard events", events.len()); + /// Sends multiple events to be handled by gateway (over gRPC). + pub(crate) fn send_multiple_change_events(&self, events: Vec) { + debug!("Sending {} change events", events.len()); for event in events { - self.send_wireguard_event(event); + self.send_change_event(event); } } @@ -101,7 +103,7 @@ impl AppState { pool: PgPool, tx: UnboundedSender, rx: UnboundedReceiver, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, user_agent_parser: Arc, failed_logins: Arc>, @@ -128,7 +130,7 @@ impl AppState { Self { pool, tx, - wireguard_tx, + events_tx, mail_tx, webauthn, user_agent_parser, diff --git a/src/auth/failed_login.rs b/src/auth/failed_login.rs index c926b815c..35c3fe597 100644 --- a/src/auth/failed_login.rs +++ b/src/auth/failed_login.rs @@ -1,16 +1,17 @@ use std::{collections::HashMap, sync::Mutex}; -use chrono::{DateTime, Duration, Local}; +use chrono::{DateTime, Local, TimeDelta}; use thiserror::Error; +use utoipa::ToSchema; // Time window in seconds -const FAILED_LOGIN_WINDOW: i64 = 60; +const FAILED_LOGIN_WINDOW: TimeDelta = TimeDelta::seconds(60); // Failed login count threshold const FAILED_LOGIN_COUNT: u32 = 5; // How long (in seconds) to lock users out after crossing the threshold -const FAILED_LOGIN_TIMEOUT: i64 = 5 * 60; +const FAILED_LOGIN_TIMEOUT: TimeDelta = TimeDelta::seconds(5 * 60); -#[derive(Error, Debug)] +#[derive(Debug, Error, ToSchema)] #[error("Too many login attempts")] pub struct FailedLoginError; @@ -34,12 +35,12 @@ impl Default for FailedLogin { impl FailedLogin { // How much time has elapsed since first failed login attempt - fn time_since_first_attempt(&self) -> Duration { + fn time_since_first_attempt(&self) -> TimeDelta { Local::now().signed_duration_since(self.first_attempt) } // How much time has elapsed since last failed login attempt - fn time_since_last_attempt(&self) -> Duration { + fn time_since_last_attempt(&self) -> TimeDelta { Local::now().signed_duration_since(self.last_attempt) } @@ -57,16 +58,16 @@ impl FailedLogin { // Check if user login attempt should be stopped fn should_prevent_login(&self) -> bool { self.attempt_count >= FAILED_LOGIN_COUNT - && self.time_since_last_attempt() <= Duration::seconds(FAILED_LOGIN_TIMEOUT) + && self.time_since_last_attempt() <= FAILED_LOGIN_TIMEOUT } // Check if attempt counter can be reset. // Counter can be reset after enough time has passed since the initial attempt. // If user was blocked we also check if enough time (timeout) has passed since last attempt. fn should_reset_counter(&self) -> bool { - self.time_since_first_attempt() > Duration::seconds(FAILED_LOGIN_WINDOW) + self.time_since_first_attempt() > FAILED_LOGIN_WINDOW && self.attempt_count < FAILED_LOGIN_COUNT - || self.time_since_last_attempt() > Duration::seconds(FAILED_LOGIN_TIMEOUT) + || self.time_since_last_attempt() > FAILED_LOGIN_TIMEOUT } } diff --git a/src/auth/mod.rs b/src/auth/mod.rs index d1d0d0336..c08cb68fb 100644 --- a/src/auth/mod.rs +++ b/src/auth/mod.rs @@ -18,7 +18,16 @@ use serde::{Deserialize, Serialize}; use crate::{ appstate::AppState, - db::{Group, Id, OAuth2AuthorizedApp, OAuth2Token, Session, SessionState, User}, + db::{ + models::{ + group::Group, + oauth2authorizedapp::OAuth2AuthorizedApp, + oauth2token::OAuth2Token, + session::{Session, SessionState}, + user::User, + }, + Id, + }, error::WebError, handlers::SESSION_COOKIE_NAME, server_config, @@ -44,7 +53,7 @@ pub enum ClaimsType { /// Standard claims: https://www.iana.org/assignments/jwt/jwt.xhtml #[derive(Deserialize, Serialize)] pub struct Claims { - #[serde(skip_serializing, skip_deserializing)] + #[serde(skip)] secret: String, // issuer pub iss: String, @@ -126,23 +135,22 @@ where async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { let appstate = AppState::from_ref(state); - if let Ok(cookies) = CookieJar::from_request_parts(parts, state).await { - if let Some(session_cookie) = cookies.get(SESSION_COOKIE_NAME) { - return { - match Session::find_by_id(&appstate.pool, session_cookie.value()).await { - Ok(Some(session)) => { - if session.expired() { - let _result = session.delete(&appstate.pool).await; - Err(WebError::Authorization("Session expired".into())) - } else { - Ok(session) - } + let Ok(cookies) = CookieJar::from_request_parts(parts, state).await; + if let Some(session_cookie) = cookies.get(SESSION_COOKIE_NAME) { + return { + match Session::find_by_id(&appstate.pool, session_cookie.value()).await { + Ok(Some(session)) => { + if session.expired() { + let _result = session.delete(&appstate.pool).await; + Err(WebError::Authorization("Session expired".into())) + } else { + Ok(session) } - Ok(None) => Err(WebError::Authorization("Session not found".into())), - Err(err) => Err(err.into()), } - }; - } + Ok(None) => Err(WebError::Authorization("Session not found".into())), + Err(err) => Err(err.into()), + } + }; } Err(WebError::Authorization("Session is required".into())) } diff --git a/src/bin/defguard.rs b/src/bin/defguard.rs index a25f50a83..ec7c73fed 100644 --- a/src/bin/defguard.rs +++ b/src/bin/defguard.rs @@ -6,9 +6,12 @@ use std::{ use defguard::{ auth::failed_login::FailedLoginMap, config::{Command, DefGuardConfig}, - db::{init_db, AppEvent, GatewayEvent, Settings, User}, + db::{ + init_db, + models::{settings::Settings, user::User, webhook::AppEvent, wireguard::ChangeEvent}, + }, enterprise::license::{run_periodic_license_check, set_cached_license, License}, - grpc::{run_grpc_bidi_stream, run_grpc_server, GatewayMap, WorkerState}, + grpc::{run_grpc_bidi_stream, run_grpc_gateway_stream, run_grpc_server, WorkerState}, headers::create_user_agent_parser, init_dev_env, init_vpn_location, mail::{run_mail_handler, Mail}, @@ -75,10 +78,9 @@ async fn main() -> Result<(), anyhow::Error> { } let (webhook_tx, webhook_rx) = unbounded_channel::(); - let (wireguard_tx, _wireguard_rx) = broadcast::channel::(256); + let (events_tx, _events_rx) = broadcast::channel::(256); let (mail_tx, mail_rx) = unbounded_channel::(); let worker_state = Arc::new(Mutex::new(WorkerState::new(webhook_tx.clone()))); - let gateway_state = Arc::new(Mutex::new(GatewayMap::new())); let user_agent_parser = create_user_agent_parser(); // initialize admin user @@ -114,13 +116,15 @@ async fn main() -> Result<(), anyhow::Error> { // run services tokio::select! { - res = run_grpc_bidi_stream(pool.clone(), wireguard_tx.clone(), mail_tx.clone(), user_agent_parser.clone()), if config.proxy_url.is_some() => error!("Proxy gRPC stream returned early: {res:#?}"), - res = run_grpc_server(Arc::clone(&worker_state), pool.clone(), Arc::clone(&gateway_state), wireguard_tx.clone(), mail_tx.clone(), grpc_cert, grpc_key, failed_logins.clone()) => error!("gRPC server returned early: {res:#?}"), - res = run_web_server(worker_state, gateway_state, webhook_tx, webhook_rx, wireguard_tx.clone(), mail_tx, pool.clone(), user_agent_parser, failed_logins) => error!("Web server returned early: {res:#?}"), + res = run_grpc_gateway_stream(pool.clone(), events_tx.clone(), mail_tx.clone()) => error!("Gateway gRPC stream returned early: {res:#?}"), + res = run_grpc_bidi_stream(pool.clone(), events_tx.clone(), mail_tx.clone(), user_agent_parser.clone()), if config.proxy_url.is_some() => error!("Proxy gRPC stream returned early: {res:#?}"), + res = run_grpc_server(Arc::clone(&worker_state), pool.clone(), grpc_cert, grpc_key, failed_logins.clone()) => error!("gRPC server returned early: {res:#?}"), + res = run_web_server(worker_state, webhook_tx, webhook_rx, events_tx.clone(), mail_tx, pool.clone(), user_agent_parser, failed_logins) => error!("Web server returned early: {res:#?}"), res = run_mail_handler(mail_rx, pool.clone()) => error!("Mail handler returned early: {res:#?}"), - res = run_periodic_peer_disconnect(pool.clone(), wireguard_tx) => error!("Periodic peer disconnect task returned early: {res:#?}"), + res = run_periodic_peer_disconnect(pool.clone(), events_tx) => error!("Periodic peer disconnect task returned early: {res:#?}"), res = run_periodic_stats_purge(pool.clone(), config.stats_purge_frequency.into(), config.stats_purge_threshold.into()), if !config.disable_stats_purge => error!("Periodic stats purge task returned early: {res:#?}"), res = run_periodic_license_check(pool) => error!("Periodic license check task returned early: {res:#?}"), } + Ok(()) } diff --git a/src/config.rs b/src/config.rs index 3b66f28b2..e6ab894a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,5 @@ +use std::{fs::read_to_string, io}; + use clap::{Args, Parser, Subcommand}; use humantime::Duration; use ipnetwork::IpNetwork; @@ -10,6 +12,7 @@ use rsa::{ RsaPrivateKey, }; use secrecy::{ExposeSecret, Secret}; +use tonic::transport::{Certificate, ClientTlsConfig, Identity}; #[derive(Clone, Parser, Serialize, Debug)] #[command(version)] @@ -51,9 +54,11 @@ pub struct DefGuardConfig { #[arg(long, env = "DEFGUARD_GRPC_PORT", default_value_t = 50055)] pub grpc_port: u16, + // Certificate authority (CA), certificate, and key for gRPC communication over HTTPS. + #[arg(long, env = "DEFGUARD_GRPC_CA")] + pub grpc_ca: Option, #[arg(long, env = "DEFGUARD_GRPC_CERT")] pub grpc_cert: Option, - #[arg(long, env = "DEFGUARD_GRPC_KEY")] pub grpc_key: Option, @@ -151,10 +156,6 @@ pub struct DefGuardConfig { #[arg(long, env = "DEFGUARD_PROXY_URL")] pub proxy_url: Option, - // path to certificate `.pem` file used if connecting to proxy over HTTPS - #[arg(long, env = "DEFGUARD_PROXY_GRPC_CA")] - pub proxy_grpc_ca: Option, - #[arg( long, env = "DEFGUARD_GATEWAY_DISCONNECTION_NOTIFICATION_TIMEOUT", @@ -265,7 +266,7 @@ impl DefGuardConfig { } #[must_use] - pub fn openid_key(&self) -> Option { + pub(crate) fn openid_key(&self) -> Option { let key = self.openid_signing_key.as_ref()?; if let Ok(pem) = key.to_pkcs1_pem(LineEnding::default()) { let key_id = JsonWebKeyId::new(key.n().to_str_radix(36)); @@ -274,6 +275,25 @@ impl DefGuardConfig { None } } + + /// Provide [`ClientTlsConfig`] from paths to cerfiticate, key, and cerfiticate authority (CA). + pub(crate) fn grpc_client_tls_config(&self) -> Result, io::Error> { + if self.grpc_ca.is_none() && (self.grpc_cert.is_none() || self.grpc_key.is_none()) { + return Ok(None); + } + let mut tls = ClientTlsConfig::new(); + if let (Some(cert_path), Some(key_path)) = (&self.grpc_cert, &self.grpc_key) { + let cert = read_to_string(cert_path)?; + let key = read_to_string(key_path)?; + tls = tls.identity(Identity::from_pem(cert, key)); + } + if let Some(ca_path) = &self.grpc_ca { + let ca = read_to_string(ca_path)?; + tls = tls.ca_certificate(Certificate::from_pem(ca)); + } + + Ok(Some(tls)) + } } impl Default for DefGuardConfig { diff --git a/src/db/mod.rs b/src/db/mod.rs index c444023ab..9c1587acb 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,14 +1,31 @@ pub mod models; use sqlx::postgres::{PgConnectOptions, PgPool}; +use utoipa::ToSchema; -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, ToSchema)] pub struct NoId; pub type Id = i64; -/// Initializes and migrates postgres database. Returns DB pool object. +#[derive(Debug, Deserialize)] +#[serde(rename_all = "UPPERCASE")] +pub(crate) enum TriggerOperation { + Insert, + Update, + Delete, +} + +#[derive(Deserialize)] +pub(crate) struct ChangeNotification { + pub operation: TriggerOperation, + pub old: Option, + pub new: Option, +} + +/// Initializes PostgreSQL database and runs the migrations. +/// Returns database pool object. pub async fn init_db(host: &str, port: u16, name: &str, user: &str, password: &str) -> PgPool { - info!("Initializing DB pool"); + info!("Initializing pool of database connections"); let opts = PgConnectOptions::new() .host(host) .port(port) @@ -24,19 +41,3 @@ pub async fn init_db(host: &str, port: u16, name: &str, user: &str, password: &s .expect("Cannot run database migrations."); pool } - -pub use models::{ - device::{AddDevice, Device}, - group::Group, - oauth2authorizedapp::OAuth2AuthorizedApp, - oauth2token::OAuth2Token, - session::{Session, SessionState}, - settings::Settings, - user::{MFAMethod, User}, - wallet::Wallet, - webauthn::WebAuthn, - webhook::{AppEvent, HWKeyUserData, WebHook}, - wireguard::{GatewayEvent, WireguardNetwork, WireguardPeerStats}, - yubikey::YubiKey, - MFAInfo, UserDetails, UserInfo, -}; diff --git a/src/db/models/device.rs b/src/db/models/device.rs index 6dd9028d7..37d233ed5 100644 --- a/src/db/models/device.rs +++ b/src/db/models/device.rs @@ -17,13 +17,15 @@ use crate::{ KEY_LENGTH, }; -#[derive(Serialize)] +#[derive(Serialize, ToSchema)] pub struct DeviceConfig { pub(crate) network_id: Id, pub(crate) network_name: String, pub(crate) config: String, + #[schema(value_type = String)] pub(crate) address: IpAddr, pub(crate) endpoint: String, + #[schema(value_type = Vec)] pub(crate) allowed_ips: Vec, pub(crate) pubkey: String, pub(crate) dns: Option, @@ -31,7 +33,7 @@ pub struct DeviceConfig { pub(crate) keepalive_interval: i32, } -#[derive(Clone, Deserialize, Model, Serialize, Debug, ToSchema)] +#[derive(Clone, Debug, Deserialize, Model, Serialize, ToSchema)] pub struct Device { pub id: I, pub name: String, @@ -101,7 +103,7 @@ pub struct UserDevice { pub networks: Vec, } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] pub struct UserDeviceNetworkInfo { pub network_id: Id, pub network_name: String, @@ -127,7 +129,7 @@ impl UserDevice { n.id network_id, n.name network_name, n.endpoint gateway_endpoint, \ wnd.wireguard_ip \"device_wireguard_ip: IpAddr\", stats.endpoint device_endpoint, \ stats.latest_handshake \"latest_handshake?\", \ - COALESCE (((NOW() - stats.latest_handshake) < $1 * interval '1 minute'), false) as \"is_active!\" \ + COALESCE (((NOW() - stats.latest_handshake) < $1 * interval '1m'), false) as \"is_active!\" \ FROM wireguard_network_device wnd \ JOIN wireguard_network n ON n.id = wnd.wireguard_network_id \ LEFT JOIN stats on n.id = stats.network \ @@ -605,7 +607,7 @@ mod test { use claims::{assert_err, assert_ok}; use super::*; - use crate::db::User; + use crate::db::models::user::User; impl Device { /// Create new device and assign IP in a given network diff --git a/src/db/models/enrollment.rs b/src/db/models/enrollment.rs index c4b871adb..460d8c3e1 100644 --- a/src/db/models/enrollment.rs +++ b/src/db/models/enrollment.rs @@ -1,4 +1,6 @@ -use chrono::{Duration, NaiveDateTime, Utc}; +use std::time::Duration; + +use chrono::{NaiveDateTime, TimeDelta, Utc}; use reqwest::Url; use sqlx::{query, query_as, Error as SqlxError, PgConnection, PgExecutor, PgPool}; use tera::{Context, Tera}; @@ -16,8 +18,8 @@ use crate::{ VERSION, }; -pub static ENROLLMENT_TOKEN_TYPE: &str = "ENROLLMENT"; -pub static PASSWORD_RESET_TOKEN_TYPE: &str = "PASSWORD_RESET"; +pub(crate) static ENROLLMENT_TOKEN_TYPE: &str = "ENROLLMENT"; +pub(crate) static PASSWORD_RESET_TOKEN_TYPE: &str = "PASSWORD_RESET"; static ENROLLMENT_START_MAIL_SUBJECT: &str = "Defguard user enrollment"; static DESKTOP_START_MAIL_SUBJECT: &str = "Defguard desktop client configuration"; @@ -78,7 +80,7 @@ impl From for Status { } // Representation of a user enrollment session -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Token { pub id: String, pub user_id: Id, @@ -106,7 +108,7 @@ impl Token { admin_id, email, created_at: now.naive_utc(), - expires_at: (now + Duration::seconds(token_timeout_seconds as i64)).naive_utc(), + expires_at: (now + TimeDelta::seconds(token_timeout_seconds as i64)).naive_utc(), used_at: None, token_type, } @@ -145,10 +147,10 @@ impl Token { // check if enrollment session is still valid // after using the token user has 10 minutes to complete enrollment #[must_use] - pub fn is_session_valid(&self, session_timeout_seconds: u64) -> bool { + pub fn is_session_valid(&self, session_timeout: Duration) -> bool { if let Some(used_at) = self.used_at { let now = Utc::now(); - return now.naive_utc() < (used_at + Duration::seconds(session_timeout_seconds as i64)); + return now.naive_utc() < (used_at + session_timeout); } false } @@ -159,7 +161,7 @@ impl Token { pub async fn start_session( &mut self, transaction: &mut PgConnection, - session_timeout_seconds: u64, + session_timeout: Duration, ) -> Result { // check if token can be used debug!("Creating a new session."); @@ -169,9 +171,9 @@ impl Token { } match self.used_at { // session started but still valid - Some(used_at) if self.is_session_valid(session_timeout_seconds) => { + Some(used_at) if self.is_session_valid(session_timeout) => { debug!("Session already exists yet it is still valid."); - Ok(used_at + Duration::seconds(session_timeout_seconds as i64)) + Ok(used_at + session_timeout) } // session expired Some(_) => { @@ -187,7 +189,7 @@ impl Token { self.used_at = Some(now); debug!("Generate a new session successfully."); - Ok(now + Duration::seconds(session_timeout_seconds as i64)) + Ok(now + session_timeout) } } } @@ -381,7 +383,7 @@ impl User { /// Start user enrollment process /// This creates a new enrollment token valid for 24h /// and optionally sends enrollment email notification to user - pub async fn start_enrollment( + pub(crate) async fn start_enrollment( &self, transaction: &mut PgConnection, admin: &User, @@ -454,9 +456,8 @@ impl User { ) .map_err(|err| { debug!( - "Cannot send an email to the user {} due to the error {}.", + "Cannot send an email to the user {} due to the error {err}", self.username, - err.to_string() ); TokenError::NotificationError(err.to_string()) })?, @@ -598,14 +599,14 @@ impl User { } impl Settings { - pub fn enrollment_welcome_message(&self) -> Result { + pub(crate) fn enrollment_welcome_message(&self) -> Result { self.enrollment_welcome_message.clone().ok_or_else(|| { error!("Enrollment welcome message not configured"); TokenError::WelcomeMsgNotConfigured }) } - pub fn enrollment_welcome_email(&self) -> Result { + pub(crate) fn enrollment_welcome_email(&self) -> Result { if self.enrollment_use_welcome_message_as_email { return self.enrollment_welcome_message(); } diff --git a/src/db/models/gateway.rs b/src/db/models/gateway.rs new file mode 100644 index 000000000..564b01f34 --- /dev/null +++ b/src/db/models/gateway.rs @@ -0,0 +1,105 @@ +use std::fmt; + +use chrono::{NaiveDateTime, Utc}; +use model_derive::Model; +use sqlx::{query, query_as, PgExecutor}; + +use crate::db::{Id, NoId}; + +#[derive(Clone, Debug, Deserialize, Model, PartialEq, Serialize)] +pub(crate) struct Gateway { + pub id: I, + pub network_id: Id, + pub url: String, + pub hostname: Option, + pub connected_at: Option, + pub disconnected_at: Option, +} + +impl Gateway { + #[must_use] + pub(crate) fn new>(network_id: Id, url: S) -> Self { + Self { + id: NoId, + network_id, + url: url.into(), + hostname: None, + connected_at: None, + disconnected_at: None, + } + } +} + +impl Gateway { + pub(crate) async fn find_by_network_id<'e, E>( + executor: E, + network_id: Id, + ) -> Result, sqlx::Error> + where + E: PgExecutor<'e>, + { + query_as!( + Self, + "SELECT * FROM gateway WHERE network_id = $1 ORDER BY id", + network_id + ) + .fetch_all(executor) + .await + } + + /// Update `hostname` and set `connected_at` to the current time and save it to the database. + pub(crate) async fn touch_connected<'e, E>( + &mut self, + executor: E, + hostname: String, + ) -> Result<(), sqlx::Error> + where + E: PgExecutor<'e>, + { + self.hostname = Some(hostname); + self.connected_at = Some(Utc::now().naive_utc()); + query!( + "UPDATE gateway SET hostname = $2, connected_at = $3 WHERE id = $1", + self.id, + self.hostname, + self.connected_at + ) + .execute(executor) + .await?; + + Ok(()) + } + + /// Set `disconnected_at` to the current time and save it to the database. + pub(crate) async fn touch_disconnected<'e, E>(&mut self, executor: E) -> Result<(), sqlx::Error> + where + E: PgExecutor<'e>, + { + self.disconnected_at = Some(Utc::now().naive_utc()); + query!( + "UPDATE gateway SET disconnected_at = $2 WHERE id = $1", + self.id, + self.disconnected_at + ) + .execute(executor) + .await?; + + Ok(()) + } + + pub(crate) fn is_connected(&self) -> bool { + if let (Some(connected_at), Some(disconnected_at)) = + (self.connected_at, self.disconnected_at) + { + disconnected_at <= connected_at + } else { + self.connected_at.is_some() + } + } +} + +impl fmt::Display for Gateway { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Gateway(ID {}; URL {})", self.id, self.url) + } +} diff --git a/src/db/models/group.rs b/src/db/models/group.rs index 99ece048e..6d550ed13 100644 --- a/src/db/models/group.rs +++ b/src/db/models/group.rs @@ -3,7 +3,10 @@ use sqlx::{query, query_as, query_scalar, Error as SqlxError, PgConnection, PgEx use utoipa::ToSchema; use crate::{ - db::{models::error::ModelError, Id, NoId, User, WireguardNetwork}, + db::{ + models::{error::ModelError, user::User, wireguard::WireguardNetwork}, + Id, NoId, + }, server_config, }; @@ -83,7 +86,7 @@ impl Group { impl WireguardNetwork { /// Fetch a list of all allowed groups for a given network from DB - pub async fn fetch_allowed_groups<'e, E>(&self, executor: E) -> Result, ModelError> + pub async fn fetch_allowed_groups<'e, E>(&self, executor: E) -> Result, sqlx::Error> where E: PgExecutor<'e>, { @@ -108,7 +111,7 @@ impl WireguardNetwork { pub async fn get_allowed_groups( &self, transaction: &mut PgConnection, - ) -> Result>, ModelError> { + ) -> Result>, sqlx::Error> { debug!("Returning a list of allowed groups for network {self}"); let admin_group_name = &server_config().admin_groupname; // get allowed groups from DB @@ -218,7 +221,7 @@ impl WireguardNetwork { #[cfg(test)] mod test { use super::*; - use crate::db::{PgPool, User}; + use crate::db::{models::user::User, PgPool}; #[sqlx::test] async fn test_group(pool: PgPool) { diff --git a/src/db/models/mod.rs b/src/db/models/mod.rs index d13db81b3..a6cef0057 100644 --- a/src/db/models/mod.rs +++ b/src/db/models/mod.rs @@ -5,6 +5,7 @@ pub mod device; pub mod device_login; pub mod enrollment; pub mod error; +pub mod gateway; pub mod group; #[cfg(feature = "openid")] pub mod oauth2authorizedapp; @@ -27,9 +28,10 @@ use utoipa::ToSchema; use self::{ device::UserDevice, + group::Group, user::{MFAMethod, User}, }; -use super::{Group, Id}; +use super::Id; #[cfg(feature = "openid")] #[derive(Deserialize, Serialize)] @@ -40,7 +42,7 @@ pub struct NewOpenIDClient { pub enabled: bool, } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, ToSchema)] pub struct WalletInfo { pub address: String, pub name: String, @@ -48,7 +50,7 @@ pub struct WalletInfo { pub use_for_mfa: bool, } -#[derive(Deserialize, Serialize, Debug, Clone)] +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] pub struct OAuth2AuthorizedAppInfo { pub oauth2client_id: Id, pub user_id: Id, @@ -56,7 +58,7 @@ pub struct OAuth2AuthorizedAppInfo { } /// Only `id` and `name` from [`WebAuthn`]. -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, ToSchema)] pub struct SecurityKey { pub id: Id, pub name: String, @@ -82,7 +84,7 @@ pub struct UserInfo { } impl UserInfo { - pub async fn from_user(pool: &PgPool, user: &User) -> Result { + pub(crate) async fn from_user(pool: &PgPool, user: &User) -> Result { let groups = user.member_of_names(pool).await?; let authorized_apps = user.oauth2authorizedapps(pool).await?; @@ -167,22 +169,18 @@ impl UserInfo { } /// Copy fields to [`User`]. This function is safe to call by a non-admin user. - pub fn into_user_safe_fields(self, user: &mut User) -> Result<(), SqlxError> { + pub(crate) fn into_user_safe_fields(self, user: &mut User) { user.phone = self.phone; user.mfa_method = self.mfa_method; - - Ok(()) } /// Copy fields to [`User`]. This function should be used by administrators. - pub fn into_user_all_fields(self, user: &mut User) -> Result<(), SqlxError> { + pub(crate) fn into_user_all_fields(self, user: &mut User) { user.phone = self.phone; user.username = self.username; user.last_name = self.last_name; user.first_name = self.first_name; user.email = self.email; - - Ok(()) } } @@ -235,7 +233,7 @@ impl MFAInfo { } #[must_use] - pub fn mfa_available(&self) -> bool { + pub(crate) fn mfa_available(&self) -> bool { self.webauthn_available || self.totp_available || self.web3_available @@ -248,7 +246,7 @@ impl MFAInfo { } #[must_use] - pub fn list_available_methods(&self) -> Option> { + pub(crate) fn list_available_methods(&self) -> Option> { if !self.mfa_available() { return None; } @@ -310,7 +308,7 @@ mod test { .handle_user_groups(&mut transaction, &mut user) .await .unwrap(); - user_info.into_user_all_fields(&mut user).unwrap(); + user_info.into_user_all_fields(&mut user); transaction.commit().await.unwrap(); assert_eq!(group1.member_usernames(&pool).await.unwrap(), ["hpotter"]); diff --git a/src/db/models/oauth2token.rs b/src/db/models/oauth2token.rs index ad4b9624c..f65fdf1dd 100644 --- a/src/db/models/oauth2token.rs +++ b/src/db/models/oauth2token.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, Utc}; +use chrono::{TimeDelta, Utc}; use sqlx::{query, query_as, Error as SqlxError, PgPool}; use crate::{db::Id, random::gen_alphanumeric, server_config}; @@ -16,7 +16,7 @@ impl OAuth2Token { #[must_use] pub fn new(oauth2authorizedapp_id: Id, redirect_uri: String, scope: String) -> Self { let timeout = server_config().session_timeout; - let expiration = Utc::now() + Duration::seconds(timeout.as_secs() as i64); + let expiration = Utc::now() + TimeDelta::seconds(timeout.as_secs() as i64); Self { oauth2authorizedapp_id, access_token: gen_alphanumeric(24), @@ -32,7 +32,7 @@ impl OAuth2Token { let timeout = server_config().session_timeout; let new_access_token = gen_alphanumeric(24); let new_refresh_token = gen_alphanumeric(24); - let expiration = Utc::now() + Duration::seconds(timeout.as_secs() as i64); + let expiration = Utc::now() + TimeDelta::seconds(timeout.as_secs() as i64); self.expires_in = expiration.timestamp(); query!( diff --git a/src/db/models/polling_token.rs b/src/db/models/polling_token.rs index cd20e62ee..f2cd09226 100644 --- a/src/db/models/polling_token.rs +++ b/src/db/models/polling_token.rs @@ -1,6 +1,6 @@ use chrono::{NaiveDateTime, Utc}; use model_derive::Model; -use sqlx::{query_as, Error as SqlxError, PgExecutor, PgPool}; +use sqlx::{query_as, PgExecutor}; use crate::{ db::{Id, NoId}, @@ -29,18 +29,24 @@ impl PollingToken { } impl PollingToken { - pub async fn find(pool: &PgPool, token: &str) -> Result, SqlxError> { + pub(crate) async fn find<'e, E>(executor: E, token: &str) -> Result, sqlx::Error> + where + E: PgExecutor<'e>, + { query_as!( Self, "SELECT id, token, device_id, created_at \ FROM pollingtoken WHERE token = $1", token ) - .fetch_optional(pool) + .fetch_optional(executor) .await } - pub async fn delete_for_device_id<'e, E>(executor: E, device_id: Id) -> Result<(), SqlxError> + pub(crate) async fn delete_for_device_id<'e, E>( + executor: E, + device_id: Id, + ) -> Result<(), sqlx::Error> where E: PgExecutor<'e>, { diff --git a/src/db/models/session.rs b/src/db/models/session.rs index 4b11068f7..461efd723 100644 --- a/src/db/models/session.rs +++ b/src/db/models/session.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime, TimeDelta, Utc}; use sqlx::{query, query_as, Error as SqlxError, PgExecutor, PgPool, Type}; use webauthn_rs::prelude::{PasskeyAuthentication, PasskeyRegistration}; @@ -42,7 +42,7 @@ impl Session { user_id, state, created: now.naive_utc(), - expires: (now + Duration::seconds(timeout.as_secs() as i64)).naive_utc(), + expires: (now + TimeDelta::seconds(timeout.as_secs() as i64)).naive_utc(), webauthn_challenge: None, web3_challenge: None, ip_address, diff --git a/src/db/models/user.rs b/src/db/models/user.rs index 21fee1ac1..af6a46e92 100644 --- a/src/db/models/user.rs +++ b/src/db/models/user.rs @@ -11,6 +11,7 @@ use axum::http::StatusCode; use model_derive::Model; use sqlx::{query, query_as, query_scalar, Error as SqlxError, PgExecutor, PgPool, Type}; use totp_lite::{totp_custom, Sha1}; +use utoipa::ToSchema; use super::{ device::{Device, UserDevice}, @@ -21,7 +22,7 @@ use super::{ }; use crate::{ auth::{EMAIL_CODE_DIGITS, TOTP_CODE_DIGITS, TOTP_CODE_VALIDITY_PERIOD}, - db::{Id, NoId, Session}, + db::{models::session::Session, Id, NoId}, error::WebError, random::{gen_alphanumeric, gen_totp_secret}, server_config, @@ -29,7 +30,7 @@ use crate::{ const RECOVERY_CODES_COUNT: usize = 8; -#[derive(Clone, Deserialize, Serialize, PartialEq, Type, Debug)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, ToSchema, Type)] #[sqlx(type_name = "mfa_method", rename_all = "snake_case")] pub enum MFAMethod { None, @@ -137,15 +138,12 @@ impl User { } pub fn verify_password(&self, password: &str) -> Result<(), HashError> { - match &self.password_hash { - Some(hash) => { - let parsed_hash = PasswordHash::new(hash)?; - Argon2::default().verify_password(password.as_bytes(), &parsed_hash) - } - None => { - error!("Password not set for user {}", self.username); - Err(HashError::Password) - } + if let Some(hash) = &self.password_hash { + let parsed_hash = PasswordHash::new(hash)?; + Argon2::default().verify_password(password.as_bytes(), &parsed_hash) + } else { + error!("Password not set for user {}", self.username); + Err(HashError::Password) } } @@ -802,7 +800,7 @@ impl User { pub async fn remove_oauth2_authorized_apps<'e, E>( &self, executor: E, - app_client_ids: &[i64], + app_client_ids: &[Id], ) -> Result<(), SqlxError> where E: PgExecutor<'e>, diff --git a/src/db/models/webhook.rs b/src/db/models/webhook.rs index c9eda286c..856d08f95 100644 --- a/src/db/models/webhook.rs +++ b/src/db/models/webhook.rs @@ -12,7 +12,8 @@ pub enum AppEvent { UserDeleted(String), HWKeyProvision(HWKeyUserData), } -/// User data send on HWKeyProvision AppEvent + +/// User data sent on HWKeyProvision AppEvent #[derive(Debug, Serialize)] pub struct HWKeyUserData { pub username: String, @@ -27,16 +28,16 @@ impl AppEvent { #[must_use] pub fn name(&self) -> &str { match self { - Self::UserCreated(_) => "user created", - Self::UserModified(_) => "user modified", - Self::UserDeleted(_) => "user deleted", - Self::HWKeyProvision(_) => "hwkey provisioned", + Self::UserCreated(_) => "user_created", + Self::UserModified(_) => "user_modified", + Self::UserDeleted(_) => "user_deleted", + Self::HWKeyProvision(_) => "user_keys", } } /// Database column name. #[must_use] - pub fn column_name(&self) -> &str { + pub(crate) fn column_name(&self) -> &str { match self { Self::UserCreated(_) => "on_user_created", Self::UserModified(_) => "on_user_modified", diff --git a/src/db/models/wireguard.rs b/src/db/models/wireguard.rs index 5bc14aa9e..979670d62 100644 --- a/src/db/models/wireguard.rs +++ b/src/db/models/wireguard.rs @@ -6,11 +6,13 @@ use std::{ }; use base64::prelude::{Engine, BASE64_STANDARD}; -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{NaiveDateTime, TimeDelta, Utc}; use ipnetwork::{IpNetwork, IpNetworkError, NetworkSize}; use model_derive::Model; use rand_core::OsRng; -use sqlx::{query_as, query_scalar, Error as SqlxError, FromRow, PgConnection, PgExecutor, PgPool}; +use sqlx::{ + query, query_as, query_scalar, Error as SqlxError, FromRow, PgConnection, PgExecutor, PgPool, +}; use thiserror::Error; use utoipa::ToSchema; use x25519_dalek::{PublicKey, StaticSecret}; @@ -18,7 +20,8 @@ use x25519_dalek::{PublicKey, StaticSecret}; use super::{ device::{Device, DeviceError, DeviceInfo, DeviceNetworkInfo, WireguardNetworkDevice}, error::ModelError, - User, UserInfo, + user::User, + UserInfo, }; use crate::{ appstate::AppState, @@ -30,8 +33,8 @@ use crate::{ pub const DEFAULT_KEEPALIVE_INTERVAL: i32 = 25; pub const DEFAULT_DISCONNECT_THRESHOLD: i32 = 180; -// Used in process of importing network from wireguard config -#[derive(Clone, Debug, Deserialize, Serialize)] +// Used in process of importing network from WireGuard config +#[derive(Debug, Deserialize, Serialize)] pub struct MappedDevice { pub user_id: Id, pub name: String, @@ -39,8 +42,8 @@ pub struct MappedDevice { pub wireguard_ip: IpAddr, } -pub static WIREGUARD_MAX_HANDSHAKE_MINUTES: i64 = 5; -pub static PEER_STATS_LIMIT: i64 = 6 * 60; +pub(super) static WIREGUARD_MAX_HANDSHAKE_MINUTES: i64 = 5; +static PEER_STATS_LIMIT: i64 = 6 * 60; /// Defines datetime aggregation levels pub enum DateTimeAggregation { @@ -59,9 +62,10 @@ impl DateTimeAggregation { } #[derive(Clone, Debug)] -pub enum GatewayEvent { - NetworkCreated(Id, WireguardNetwork), - NetworkModified(Id, WireguardNetwork, Vec), +#[non_exhaustive] +pub enum ChangeEvent { + NetworkCreated(WireguardNetwork), + NetworkModified(WireguardNetwork, Vec), NetworkDeleted(Id, String), DeviceCreated(DeviceInfo), DeviceModified(DeviceInfo), @@ -75,6 +79,7 @@ pub struct WireguardNetwork { pub id: I, pub name: String, #[model(enum)] + #[schema(value_type = String)] pub address: IpNetwork, pub port: i32, pub pubkey: String, @@ -83,6 +88,7 @@ pub struct WireguardNetwork { pub endpoint: String, pub dns: Option, #[model(ref)] + #[schema(value_type = String)] pub allowed_ips: Vec, pub connected_at: Option, pub mfa_enabled: bool, @@ -90,9 +96,9 @@ pub struct WireguardNetwork { pub peer_disconnect_threshold: i32, } -pub struct WireguardKey { - pub private: String, - pub public: String, +pub(crate) struct WireguardKey { + pub(crate) _private: String, + pub(crate) public: String, } impl fmt::Display for WireguardNetwork { @@ -128,6 +134,7 @@ pub enum WireguardNetworkError { } impl WireguardNetwork { + #[must_use] pub fn new( name: String, address: IpNetwork, @@ -138,10 +145,10 @@ impl WireguardNetwork { mfa_enabled: bool, keepalive_interval: i32, peer_disconnect_threshold: i32, - ) -> Result { + ) -> Self { let prvkey = StaticSecret::random_from_rng(OsRng); let pubkey = PublicKey::from(&prvkey); - Ok(Self { + Self { id: NoId, name, address, @@ -155,7 +162,7 @@ impl WireguardNetwork { mfa_enabled, keepalive_interval, peer_disconnect_threshold, - }) + } } /// Try to set `address` from `&str`. @@ -166,58 +173,94 @@ impl WireguardNetwork { } } +impl WireguardNetwork { + /// Helper to fetch a name for a given network ID. + pub(crate) async fn name_for_id<'e, E>(executor: E, id: Id) -> Result + where + E: PgExecutor<'e>, + { + query_scalar!("SELECT name FROM wireguard_network WHERE id = $1", id) + .fetch_one(executor) + .await + } +} + impl WireguardNetwork { - pub async fn find_by_name<'e, E>( + /// Find all networks with a given name. + pub(crate) async fn find_by_name<'e, E>( executor: E, name: &str, - ) -> Result>, WireguardNetworkError> + ) -> Result>, SqlxError> where E: PgExecutor<'e>, { let networks = query_as!( - WireguardNetwork, - "SELECT \ - id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, mfa_enabled, keepalive_interval, peer_disconnect_threshold \ + Self, + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ + connected_at, mfa_enabled, keepalive_interval, peer_disconnect_threshold \ FROM wireguard_network WHERE name = $1", name ) .fetch_all(executor) .await?; - if networks.is_empty() { - return Ok(None); - } + Ok(if networks.is_empty() { + None + } else { + Some(networks) + }) + } - Ok(Some(networks)) + /// Fetch all networks with MFA protection turned on. + pub(crate) async fn all_mfa_enabled<'e, E>(executor: E) -> Result, SqlxError> + where + E: PgExecutor<'e>, + { + query_as!( + Self, + "SELECT id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ + connected_at, mfa_enabled, keepalive_interval, peer_disconnect_threshold \ + FROM wireguard_network WHERE mfa_enabled = true", + ) + .fetch_all(executor) + .await } - // run sync_allowed_devices on all wireguard networks - pub async fn sync_all_networks(app: &AppState) -> Result<(), WireguardNetworkError> { + /// Run `sync_allowed_devices()` on all WireGuard networks. + pub(crate) async fn sync_all_networks(app: &AppState) -> Result<(), WireguardNetworkError> { info!("Syncing allowed devices for all WireGuard locations"); let mut transaction = app.pool.begin().await?; let networks = Self::all(&mut *transaction).await?; for network in networks { let gateway_events = network.sync_allowed_devices(&mut transaction, None).await?; - app.send_multiple_wireguard_events(gateway_events); + app.send_multiple_change_events(gateway_events); } transaction.commit().await?; Ok(()) } /// Return number of devices that use this network. + #[cfg(test)] async fn device_count( &self, transaction: &mut PgConnection, ) -> Result { - let count = query_scalar!("SELECT count(*) \"count!\" FROM wireguard_network_device WHERE wireguard_network_id = $1", self.id) - .fetch_one(transaction) - .await?; + let count = query_scalar!( + "SELECT count(*) \"count!\" FROM wireguard_network_device \ + WHERE wireguard_network_id = $1", + self.id + ) + .fetch_one(transaction) + .await?; Ok(count) } - pub fn validate_network_size(&self, device_count: usize) -> Result<(), WireguardNetworkError> { + /// Check if given number of devices could fit the network. + pub(crate) fn validate_network_size( + &self, + device_count: usize, + ) -> Result<(), WireguardNetworkError> { debug!("Checking if {device_count} devices can fit in network {self}"); let network_size = self.address.size(); // include address, network, and broadcast in the calculation @@ -237,19 +280,20 @@ impl WireguardNetwork { Ok(()) } - /// Utility method to create WireGuard keypair + /// Utility method to create WireGuard keypair. #[must_use] - pub fn genkey() -> WireguardKey { + pub(crate) fn genkey() -> WireguardKey { let private = StaticSecret::random_from_rng(OsRng); let public = PublicKey::from(&private); WireguardKey { - private: BASE64_STANDARD.encode(private.to_bytes()), + _private: BASE64_STANDARD.encode(private.to_bytes()), public: BASE64_STANDARD.encode(public.to_bytes()), } } /// Try to change network address, changing device addresses if necessary. - pub async fn change_address( + #[cfg(test)] + pub(crate) async fn change_address( &mut self, transaction: &mut PgConnection, new_address: IpNetwork, @@ -353,7 +397,7 @@ impl WireguardNetwork { /// Generate network IPs for all existing devices /// If `allowed_groups` is set, devices should be filtered accordingly - pub async fn add_all_allowed_devices( + pub(crate) async fn add_all_allowed_devices( &self, transaction: &mut PgConnection, ) -> Result<(), ModelError> { @@ -371,7 +415,7 @@ impl WireguardNetwork { } /// Generate network IPs for a device if it's allowed in network - pub async fn add_device_to_network( + pub(crate) async fn add_device_to_network( &self, transaction: &mut PgConnection, device: &Device, @@ -387,18 +431,18 @@ impl WireguardNetwork { Ok(wireguard_network_device) } else { info!("Device {device} not allowed in network {self}"); - Err(WireguardNetworkError::DeviceNotAllowed(format!("{device}"))) + Err(WireguardNetworkError::DeviceNotAllowed(device.to_string())) } } /// Refresh network IPs for all relevant devices /// If the list of allowed devices has changed add/remove devices accordingly /// If the network address has changed readdress existing devices - pub async fn sync_allowed_devices( + pub(crate) async fn sync_allowed_devices( &self, transaction: &mut PgConnection, reserved_ips: Option<&[IpAddr]>, - ) -> Result, WireguardNetworkError> { + ) -> Result, WireguardNetworkError> { info!("Synchronizing IPs in network {self} for all allowed devices "); // list all allowed devices let allowed_devices = self.get_allowed_devices(&mut *transaction).await?; @@ -428,7 +472,7 @@ impl WireguardNetwork { let wireguard_network_device = device .assign_network_ip(&mut *transaction, self, reserved_ips) .await?; - events.push(GatewayEvent::DeviceModified(DeviceInfo { + events.push(ChangeEvent::DeviceModified(DeviceInfo { device, network_info: vec![DeviceNetworkInfo { network_id: self.id, @@ -448,7 +492,7 @@ impl WireguardNetwork { if let Some(device) = Device::find_by_id(&mut *transaction, device_network_config.device_id).await? { - events.push(GatewayEvent::DeviceDeleted(DeviceInfo { + events.push(ChangeEvent::DeviceDeleted(DeviceInfo { device, network_info: vec![DeviceNetworkInfo { network_id: self.id, @@ -470,7 +514,7 @@ impl WireguardNetwork { let wireguard_network_device = device .assign_network_ip(&mut *transaction, self, reserved_ips) .await?; - events.push(GatewayEvent::DeviceCreated(DeviceInfo { + events.push(ChangeEvent::DeviceCreated(DeviceInfo { device, network_info: vec![DeviceNetworkInfo { network_id: self.id, @@ -488,11 +532,11 @@ impl WireguardNetwork { /// if they do assign a specified IP. /// Return a list of imported devices which need to be manually mapped to a user /// and a list of WireGuard events to be sent out. - pub async fn handle_imported_devices( + pub(crate) async fn handle_imported_devices( &self, transaction: &mut PgConnection, imported_devices: Vec, - ) -> Result<(Vec, Vec), WireguardNetworkError> { + ) -> Result<(Vec, Vec), WireguardNetworkError> { let allowed_devices = self.get_allowed_devices(&mut *transaction).await?; // convert to a map for easier processing let allowed_devices: HashMap> = allowed_devices @@ -525,7 +569,7 @@ impl WireguardNetwork { // store ID of device with already generated config assigned_device_ids.push(existing_device.id); // send device to connected gateways - events.push(GatewayEvent::DeviceModified(DeviceInfo { + events.push(ChangeEvent::DeviceModified(DeviceInfo { device: existing_device, network_info: vec![DeviceNetworkInfo { network_id: self.id, @@ -551,11 +595,11 @@ impl WireguardNetwork { } /// Handle device -> user mapping in second step of network import wizard - pub async fn handle_mapped_devices( + pub(crate) async fn handle_mapped_devices( &self, transaction: &mut PgConnection, - mapped_devices: Vec, - ) -> Result, WireguardNetworkError> { + mapped_devices: &[MappedDevice], + ) -> Result, WireguardNetworkError> { info!("Mapping user devices for network {}", self); // get allowed groups for network let allowed_groups = self.get_allowed_groups(&mut *transaction).await?; @@ -563,7 +607,7 @@ impl WireguardNetwork { let mut events = Vec::new(); // use a helper hashmap to avoid repeated queries let mut user_groups = HashMap::new(); - for mapped_device in &mapped_devices { + for mapped_device in mapped_devices { debug!("Mapping device {}", mapped_device.name); // validate device pubkey Device::validate_pubkey(&mapped_device.wireguard_pubkey).map_err(|_| { @@ -636,7 +680,7 @@ impl WireguardNetwork { // send device to connected gateways if !network_info.is_empty() { - events.push(GatewayEvent::DeviceCreated(DeviceInfo { + events.push(ChangeEvent::DeviceCreated(DeviceInfo { device, network_info, })); @@ -653,8 +697,9 @@ impl WireguardNetwork { ) -> Result>, SqlxError> { let stats = query_as!( WireguardPeerStats, - "SELECT id, device_id \"device_id!\", collected_at \"collected_at!\", network \"network!\", \ - endpoint, upload \"upload!\", download \"download!\", latest_handshake \"latest_handshake!\", allowed_ips \ + "SELECT id, device_id \"device_id!\", collected_at \"collected_at!\", \ + network \"network!\", endpoint, upload \"upload!\", download \"download!\", \ + latest_handshake \"latest_handshake!\", allowed_ips \ FROM wireguard_peer_stats \ WHERE device_id = $1 AND network = $2 \ ORDER BY collected_at DESC \ @@ -684,6 +729,62 @@ impl WireguardNetwork { .and_then(|ep| Some(ep.split(':').next()?.to_owned())) } + /// Get a list of all allowed peers + /// + /// Each device is marked as allowed or not allowed in a given network, + /// which enables enforcing peer disconnect in MFA-protected networks. + pub async fn get_peers<'e, E>(&self, executor: E) -> Result, SqlxError> + where + E: PgExecutor<'e>, + { + debug!("Fetching all peers for network {}", self.id); + let rows = query!( + "SELECT d.wireguard_pubkey pubkey, preshared_key, \ + array[host(wnd.wireguard_ip)] \"allowed_ips!: Vec\" \ + FROM wireguard_network_device wnd \ + JOIN device d ON wnd.device_id = d.id \ + JOIN \"user\" u ON d.user_id = u.id \ + WHERE wireguard_network_id = $1 AND (is_authorized = true OR NOT $2) \ + AND u.is_active = true \ + ORDER BY d.id ASC", + self.id, + self.mfa_enabled + ) + .fetch_all(executor) + .await?; + + // keepalive has to be added manually because Postgres + // doesn't support unsigned integers + let result = rows + .into_iter() + .map(|row| Peer { + pubkey: row.pubkey, + allowed_ips: row.allowed_ips, + preshared_key: row.preshared_key, + keepalive_interval: Some(self.keepalive_interval as u32), + }) + .collect(); + + Ok(result) + } + + /// Update `connected_at` to the current time and save it to the database. + pub(crate) async fn touch_connected<'e, E>(&mut self, executor: E) -> Result<(), SqlxError> + where + E: PgExecutor<'e>, + { + self.connected_at = Some(Utc::now().naive_utc()); + query!( + "UPDATE wireguard_network SET connected_at = $2 WHERE name = $1", + self.name, + self.connected_at + ) + .execute(executor) + .await?; + + Ok(()) + } + /// Finds when the device connected based on handshake timestamps async fn connected_at( &self, @@ -696,7 +797,7 @@ impl WireguardNetwork { FROM wireguard_peer_stats_view \ WHERE device_id = $1 \ AND latest_handshake IS NOT NULL \ - AND (latest_handshake_diff > $2 * interval '1 minute' OR latest_handshake_diff IS NULL) \ + AND (latest_handshake_diff > $2 * interval '1m' OR latest_handshake_diff IS NULL) \ AND network = $3 \ ORDER BY collected_at DESC \ LIMIT 1", @@ -771,7 +872,7 @@ impl WireguardNetwork { } /// Retrieves network stats grouped by currently active users since `from` timestamp - pub async fn user_stats( + pub(crate) async fn user_stats( &self, conn: &PgPool, from: &NaiveDateTime, @@ -779,7 +880,7 @@ impl WireguardNetwork { ) -> Result, SqlxError> { let mut user_map: HashMap> = HashMap::new(); let oldest_handshake = - (Utc::now() - Duration::minutes(WIREGUARD_MAX_HANDSHAKE_MINUTES)).naive_utc(); + (Utc::now() - TimeDelta::minutes(WIREGUARD_MAX_HANDSHAKE_MINUTES)).naive_utc(); // Retrieve connected devices from database let devices = query_as!( Device, @@ -847,7 +948,7 @@ impl WireguardNetwork { &self, conn: &PgPool, ) -> Result { - let from = (Utc::now() - Duration::minutes(WIREGUARD_MAX_HANDSHAKE_MINUTES)).naive_utc(); + let from = (Utc::now() - TimeDelta::minutes(WIREGUARD_MAX_HANDSHAKE_MINUTES)).naive_utc(); let activity_stats = query_as!( WireguardNetworkActivityStats, "SELECT \ @@ -896,7 +997,7 @@ impl WireguardNetwork { } /// Retrieves network stats - pub async fn network_stats( + pub(crate) async fn network_stats( &self, conn: &PgPool, from: &NaiveDateTime, @@ -938,8 +1039,8 @@ impl Default for WireguardNetwork { } } -#[derive(Serialize, Clone, Debug)] -pub struct WireguardNetworkInfo { +#[derive(Serialize)] +pub(crate) struct WireguardNetworkInfo { #[serde(flatten)] pub network: WireguardNetwork, pub connected: bool, @@ -947,14 +1048,14 @@ pub struct WireguardNetworkInfo { pub allowed_groups: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] pub struct WireguardStatsRow { pub collected_at: Option, pub upload: Option, pub download: Option, } -#[derive(FromRow, Serialize, Deserialize, Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Deserialize, FromRow, PartialEq, Serialize)] pub struct WireguardDeviceTransferRow { pub device_id: Id, pub collected_at: Option, @@ -1017,7 +1118,7 @@ pub struct WireguardNetworkStats { #[cfg(test)] mod test { - use chrono::{Duration, SubsecRound}; + use chrono::{SubsecRound, TimeDelta}; use super::*; use crate::db::models::device::WireguardNetworkDevice; @@ -1125,12 +1226,12 @@ mod test { WireguardPeerStats { id: NoId, device_id: device.id, - collected_at: now - Duration::minutes(i), + collected_at: now - TimeDelta::minutes(i), network: network.id, endpoint: Some("11.22.33.44".into()), upload: (samples - i) * 10, download: (samples - i) * 20, - latest_handshake: now - Duration::minutes(handshake_minutes), + latest_handshake: now - TimeDelta::minutes(handshake_minutes), allowed_ips: Some("10.1.1.0/24".into()), } .save(&pool) @@ -1146,7 +1247,7 @@ mod test { assert_eq!( connected_at, // Postgres stores 6 sub-second digits while chrono stores 9 - (now - Duration::minutes(30)).trunc_subsecs(6), + (now - TimeDelta::minutes(30)).trunc_subsecs(6), ); } @@ -1179,12 +1280,12 @@ mod test { WireguardPeerStats { id: NoId, device_id: device.id, - collected_at: now - Duration::minutes(i), + collected_at: now - TimeDelta::minutes(i), network: network.id, endpoint: Some("11.22.33.44".into()), upload: (samples - i) * 10, download: (samples - i) * 20, - latest_handshake: now - Duration::minutes(i), // handshake every minute + latest_handshake: now - TimeDelta::minutes(i), // handshake every minute allowed_ips: Some("10.1.1.0/24".into()), } .save(&pool) @@ -1200,7 +1301,7 @@ mod test { assert_eq!( connected_at, // Postgres stores 6 sub-second digits while chrono stores 9 - (now - Duration::minutes(samples)).trunc_subsecs(6), + (now - TimeDelta::minutes(samples)).trunc_subsecs(6), ); } } diff --git a/src/enterprise/grpc/polling.rs b/src/enterprise/grpc/polling.rs index 1bf322566..13727856a 100644 --- a/src/enterprise/grpc/polling.rs +++ b/src/enterprise/grpc/polling.rs @@ -2,7 +2,10 @@ use sqlx::PgPool; use tonic::Status; use crate::{ - db::{models::polling_token::PollingToken, Device, Id, User}, + db::{ + models::{device::Device, polling_token::PollingToken, user::User}, + Id, + }, enterprise::license::{get_cached_license, validate_license}, grpc::{ proto::{InstanceInfoRequest, InstanceInfoResponse}, diff --git a/src/enterprise/handlers/enterprise_settings.rs b/src/enterprise/handlers/enterprise_settings.rs index 07442b9b3..369c6bcdf 100644 --- a/src/enterprise/handlers/enterprise_settings.rs +++ b/src/enterprise/handlers/enterprise_settings.rs @@ -7,13 +7,14 @@ use crate::{ appstate::AppState, auth::{AdminRole, SessionInfo}, enterprise::db::models::enterprise_settings::{EnterpriseSettings, EnterpriseSettingsPatch}, - handlers::{ApiResponse, ApiResult}, + error::WebError, + handlers::ApiResponse, }; -pub async fn get_enterprise_settings( +pub(crate) async fn get_enterprise_settings( session: SessionInfo, State(appstate): State, -) -> ApiResult { +) -> Result { debug!( "User {} retrieving enterprise settings", session.user.username @@ -23,19 +24,16 @@ pub async fn get_enterprise_settings( "User {} retrieved enterprise settings", session.user.username ); - Ok(ApiResponse { - json: json!(settings), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(settings), StatusCode::OK)) } -pub async fn patch_enterprise_settings( +pub(crate) async fn patch_enterprise_settings( _license: LicenseInfo, _admin: AdminRole, State(appstate): State, session: SessionInfo, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "Admin {} patching enterprise settings.", session.user.username, diff --git a/src/enterprise/handlers/mod.rs b/src/enterprise/handlers/mod.rs index fb5bba483..edeb0984e 100644 --- a/src/enterprise/handlers/mod.rs +++ b/src/enterprise/handlers/mod.rs @@ -1,8 +1,4 @@ -use crate::{ - auth::SessionInfo, - enterprise::license::validate_license, - handlers::{ApiResponse, ApiResult}, -}; +use crate::{auth::SessionInfo, enterprise::license::validate_license, handlers::ApiResponse}; pub mod enterprise_settings; pub mod openid_login; @@ -13,6 +9,7 @@ use axum::{ extract::{FromRef, FromRequestParts}, http::{request::Parts, StatusCode}, }; +use serde_json::json; use super::{db::models::enterprise_settings::EnterpriseSettings, license::get_cached_license}; use crate::{appstate::AppState, error::WebError}; @@ -43,7 +40,7 @@ where } } -pub async fn check_enterprise_status() -> ApiResult { +pub(crate) async fn check_enterprise_status() -> Result { let license = get_cached_license(); let valid = validate_license((license).as_ref()).is_ok(); let license_info = license.as_ref().map(|license| { @@ -54,12 +51,12 @@ pub async fn check_enterprise_status() -> ApiResult { } ) }); - Ok(ApiResponse { - json: serde_json::json!({ "enabled": valid, + Ok(ApiResponse::new( + json!({ "enabled": valid, "license_info": license_info }), - status: StatusCode::OK, - }) + StatusCode::OK, + )) } #[async_trait] diff --git a/src/enterprise/handlers/openid_login.rs b/src/enterprise/handlers/openid_login.rs index d07150353..92d529013 100644 --- a/src/enterprise/handlers/openid_login.rs +++ b/src/enterprise/handlers/openid_login.rs @@ -24,7 +24,12 @@ use time::Duration; use super::LicenseInfo; use crate::{ appstate::AppState, - db::{MFAInfo, Session, SessionState, Settings, User, UserInfo}, + db::models::{ + session::{Session, SessionState}, + settings::Settings, + user::User, + MFAInfo, UserInfo, + }, enterprise::db::models::openid_provider::OpenIdProvider, error::WebError, handlers::{ @@ -98,7 +103,7 @@ async fn make_oidc_client(pool: &PgPool) -> Result { ) } -pub async fn get_auth_info( +pub(crate) async fn get_auth_info( _license: LicenseInfo, private_cookies: PrivateCookieJar, State(appstate): State, @@ -148,14 +153,7 @@ pub async fn get_auth_info( Ok(( private_cookies, - ApiResponse { - json: json!( - { - "url": authorize_url, - } - ), - status: StatusCode::OK, - }, + ApiResponse::new(json!({"url": authorize_url}), StatusCode::OK), )) } @@ -171,7 +169,7 @@ pub struct AuthenticationResponse { state: CsrfToken, } -pub async fn auth_callback( +pub(crate) async fn auth_callback( _license: LicenseInfo, cookies: CookieJar, private_cookies: PrivateCookieJar, @@ -390,10 +388,7 @@ pub async fn auth_callback( Ok(( cookies, private_cookies, - ApiResponse { - json: json!(mfa_info), - status: StatusCode::CREATED, - }, + ApiResponse::new(json!(mfa_info), StatusCode::CREATED), )) } else { error!("Couldn't fetch MFA info for user {username} with MFA enabled"); @@ -420,26 +415,26 @@ pub async fn auth_callback( Ok(( cookies, private_cookies.remove(openid_cookie), - ApiResponse { - json: json!(AuthResponse { + ApiResponse::new( + json!(AuthResponse { user: user_info, url: Some(redirect_url) }), - status: StatusCode::OK, - }, + StatusCode::OK, + ), )) } else { debug!("No OpenID session found, proceeding with login to defguard."); Ok(( cookies, private_cookies, - ApiResponse { - json: json!(AuthResponse { + ApiResponse::new( + json!(AuthResponse { user: user_info, url: None, }), - status: StatusCode::OK, - }, + StatusCode::OK, + ), )) } } diff --git a/src/enterprise/handlers/openid_providers.rs b/src/enterprise/handlers/openid_providers.rs index d7d170fbb..93a447e6b 100644 --- a/src/enterprise/handlers/openid_providers.rs +++ b/src/enterprise/handlers/openid_providers.rs @@ -10,7 +10,8 @@ use crate::{ appstate::AppState, auth::{AdminRole, SessionInfo}, enterprise::db::models::openid_provider::OpenIdProvider, - handlers::{ApiResponse, ApiResult}, + error::WebError, + handlers::ApiResponse, }; #[derive(Debug, Deserialize, Serialize)] @@ -38,13 +39,13 @@ impl AddProviderData { } } -pub async fn add_openid_provider( +pub(crate) async fn add_openid_provider( _license: LicenseInfo, _admin: AdminRole, session: SessionInfo, State(appstate): State, Json(provider_data): Json, -) -> ApiResult { +) -> Result { // Currently, we only support one OpenID provider at a time let new_provider = OpenIdProvider::new( provider_data.name, @@ -63,36 +64,27 @@ pub async fn add_openid_provider( session.user.username, new_provider.name ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::CREATED, - }) + Ok(ApiResponse::new(json!({}), StatusCode::CREATED)) } -pub async fn get_current_openid_provider( +pub(crate) async fn get_current_openid_provider( _license: LicenseInfo, _admin: AdminRole, State(appstate): State, -) -> ApiResult { +) -> Result { match OpenIdProvider::get_current(&appstate.pool).await? { - Some(provider) => Ok(ApiResponse { - json: json!(provider), - status: StatusCode::OK, - }), - None => Ok(ApiResponse { - json: json!({}), - status: StatusCode::NOT_FOUND, - }), + Some(provider) => Ok(ApiResponse::new(json!(provider), StatusCode::OK)), + None => Ok(ApiResponse::new(json!({}), StatusCode::NOT_FOUND)), } } -pub async fn delete_openid_provider( +pub(crate) async fn delete_openid_provider( _license: LicenseInfo, _admin: AdminRole, session: SessionInfo, State(appstate): State, Path(provider_data): Path, -) -> ApiResult { +) -> Result { debug!( "User {} deleting OpenID provider {}", session.user.username, provider_data.name @@ -104,67 +96,52 @@ pub async fn delete_openid_provider( "User {} deleted OpenID provider {}", session.user.username, provider_data.name ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!({}), StatusCode::OK)) } else { warn!( "User {} failed to delete OpenID provider {}. Such provider does not exist.", session.user.username, provider_data.name ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::NOT_FOUND, - }) + Ok(ApiResponse::new(json!({}), StatusCode::NOT_FOUND)) } } -pub async fn modify_openid_provider( - _license: LicenseInfo, - _admin: AdminRole, - session: SessionInfo, - State(appstate): State, - Json(provider_data): Json, -) -> ApiResult { - debug!( - "User {} modifying OpenID provider {}", - session.user.username, provider_data.name - ); - let provider = OpenIdProvider::find_by_name(&appstate.pool, &provider_data.name).await?; - if let Some(mut provider) = provider { - provider.base_url = provider_data.base_url; - provider.client_id = provider_data.client_id; - provider.client_secret = provider_data.client_secret; - provider.save(&appstate.pool).await?; - info!( - "User {} modified OpenID client {}", - session.user.username, provider.name - ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::OK, - }) - } else { - warn!( - "User {} failed to modify OpenID client {}. Such client does not exist.", - session.user.username, provider_data.name - ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::NOT_FOUND, - }) - } -} +// pub(crate) async fn modify_openid_provider( +// _license: LicenseInfo, +// _admin: AdminRole, +// session: SessionInfo, +// State(appstate): State, +// Json(provider_data): Json, +// ) -> Result { +// debug!( +// "User {} modifying OpenID provider {}", +// session.user.username, provider_data.name +// ); +// let provider = OpenIdProvider::find_by_name(&appstate.pool, &provider_data.name).await?; +// if let Some(mut provider) = provider { +// provider.base_url = provider_data.base_url; +// provider.client_id = provider_data.client_id; +// provider.client_secret = provider_data.client_secret; +// provider.save(&appstate.pool).await?; +// info!( +// "User {} modified OpenID client {}", +// session.user.username, provider.name +// ); +// Ok(ApiResponse::new(json!({}), StatusCode::OK)) +// } else { +// warn!( +// "User {} failed to modify OpenID client {}. Such client does not exist.", +// session.user.username, provider_data.name +// ); +// Ok(ApiResponse::new(json!({}), StatusCode::NOT_FOUND)) +// } +// } -pub async fn list_openid_providers( - _license: LicenseInfo, - _admin: AdminRole, - State(appstate): State, -) -> ApiResult { - let providers = OpenIdProvider::all(&appstate.pool).await?; - Ok(ApiResponse { - json: json!(providers), - status: StatusCode::OK, - }) -} +// pub(crate) async fn list_openid_providers( +// _license: LicenseInfo, +// _admin: AdminRole, +// State(appstate): State, +// ) -> Result { +// let providers = OpenIdProvider::all(&appstate.pool).await?; +// Ok(ApiResponse::new(json!(providers), StatusCode::OK)) +// } diff --git a/src/enterprise/license.rs b/src/enterprise/license.rs index 74b23f28a..c8136f80e 100644 --- a/src/enterprise/license.rs +++ b/src/enterprise/license.rs @@ -9,11 +9,12 @@ use chrono::{DateTime, TimeDelta, Utc}; use humantime::format_duration; use pgp::{types::KeyTrait, Deserializable, SignedPublicKey, StandaloneSignature}; use prost::Message; -use sqlx::{error::Error as SqlxError, PgPool}; +use sqlx::PgPool; use thiserror::Error; use tokio::time::sleep; +use utoipa::ToSchema; -use crate::{db::Settings, VERSION}; +use crate::{db::models::settings::Settings, VERSION}; const LICENSE_SERVER_URL: &str = "https://pkgs.defguard.net/api/license/renew"; @@ -172,7 +173,7 @@ O/CQRZLP6BvYZvex7v3BoKUYkVAeWTGU6WCOPaGp1OxdkQYdryUg/A== -----END PGP PUBLIC KEY BLOCK----- "; -#[derive(Debug, Error)] +#[derive(Debug, Error, ToSchema)] pub enum LicenseError { #[error("Provided license is invalid: {0}")] InvalidLicense(String), @@ -181,7 +182,8 @@ pub enum LicenseError { #[error("Provided signature is invalid")] InvalidSignature, #[error("Database error")] - DbError(#[from] SqlxError), + #[schema(value_type = String)] + DbError(#[from] sqlx::Error), #[error("License decoding error: {0}")] DecodeError(String), #[error("License is expired and has reached its maximum overdue time, please contact salesdefguard.net")] @@ -197,7 +199,7 @@ struct RefreshRequestResponse { key: String, } -#[derive(Debug, Serialize, Deserialize, Clone)] +#[derive(Clone, Deserialize, Debug, Serialize)] pub struct License { pub customer_id: String, pub subscription: bool, @@ -421,11 +423,11 @@ impl License { /// Checks if the license has reached its maximum overdue time. #[must_use] pub fn is_max_overdue(&self) -> bool { - if !self.subscription { + if self.subscription { + self.time_overdue() > MAX_OVERDUE_TIME + } else { // Non-subscription licenses are considered expired immediately, no grace period is required self.is_expired() - } else { - self.time_overdue() > MAX_OVERDUE_TIME } } } @@ -572,36 +574,31 @@ pub async fn run_periodic_license_check(pool: PgPool) -> Result<(), LicenseError let license = get_cached_license(); debug!("Checking if the license {license:?} requires a renewal..."); - match &*license { - Some(license) => { - if license.requires_renewal() { - // check if we are pass the maximum expiration date, after which we don't - // want to try to renew the license anymore - if license.is_max_overdue() { - check_period = CHECK_PERIOD; - warn!("Your license has expired and reached its maximum overdue date, please contact sales at salesdefguard.net"); - debug!("Changing check period to {}", format_duration(check_period)); - false - } else { - debug!("License requires renewal, as it is about to expire and is not past the maximum overdue time"); - true - } - } else { - // This if is only for logging purposes, to provide more detailed information - if license.subscription { - debug!( - "License doesn't need to be renewed yet, skipping renewal check" - ); - } else { - debug!("License is not a subscription, skipping renewal check"); - } + if let Some(license) = &*license { + if license.requires_renewal() { + // check if we are pass the maximum expiration date, after which we don't + // want to try to renew the license anymore + if license.is_max_overdue() { + check_period = CHECK_PERIOD; + warn!("Your license has expired and reached its maximum overdue date, please contact sales at salesdefguard.net"); + debug!("Changing check period to {}", format_duration(check_period)); false + } else { + debug!("License requires renewal, as it is about to expire and is not past the maximum overdue time"); + true + } + } else { + // This if is only for logging purposes, to provide more detailed information + if license.subscription { + debug!("License doesn't need to be renewed yet, skipping renewal check"); + } else { + debug!("License is not a subscription, skipping renewal check"); } - } - None => { - debug!("No license found, skipping license check"); false } + } else { + debug!("No license found, skipping license check"); + false } }; diff --git a/src/error.rs b/src/error.rs index bc13ad5da..e6b80fc20 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,7 +10,6 @@ use crate::{ wireguard::WireguardNetworkError, }, enterprise::license::LicenseError, - grpc::GatewayMapError, ldap::error::LdapError, templates::TemplateError, }; @@ -45,6 +44,7 @@ pub enum WebError { #[error("Public key already exists {0}")] PubkeyExists(String), #[error("HTTP error: {0}")] + #[schema(value_type = u16)] Http(StatusCode), #[error(transparent)] TooManyLoginAttempts(#[from] FailedLoginError), @@ -104,18 +104,6 @@ impl From for WebError { } } -impl From for WebError { - fn from(error: GatewayMapError) -> Self { - match error { - GatewayMapError::NotFound(_, _) - | GatewayMapError::NetworkNotFound(_) - | GatewayMapError::UidNotFound(_) => Self::ObjectNotFound(error.to_string()), - GatewayMapError::RemoveActive(_) => Self::BadRequest(error.to_string()), - GatewayMapError::ConfigError => Self::ServerConfigMissing, - } - } -} - impl From for WebError { fn from(error: WireguardNetworkError) -> Self { match error { diff --git a/src/grpc/auth.rs b/src/grpc/auth.rs index fced88ff4..f80639462 100644 --- a/src/grpc/auth.rs +++ b/src/grpc/auth.rs @@ -9,13 +9,13 @@ use crate::{ failed_login::{check_username, log_failed_login_attempt, FailedLoginMap}, Claims, ClaimsType, }, - db::User, + db::models::user::User, server_config, }; tonic::include_proto!("auth"); -pub struct AuthServer { +pub(crate) struct AuthServer { pool: PgPool, failed_logins: Arc>, } diff --git a/src/grpc/desktop_client_mfa.rs b/src/grpc/desktop_client_mfa.rs index 0dfcb2a56..d56209224 100644 --- a/src/grpc/desktop_client_mfa.rs +++ b/src/grpc/desktop_client_mfa.rs @@ -12,8 +12,13 @@ use super::proto::{ use crate::{ auth::{Claims, ClaimsType}, db::{ - models::device::{DeviceInfo, DeviceNetworkInfo, WireguardNetworkDevice}, - Device, GatewayEvent, Id, User, UserInfo, WireguardNetwork, + models::{ + device::{Device, DeviceInfo, DeviceNetworkInfo, WireguardNetworkDevice}, + user::User, + wireguard::{ChangeEvent, WireguardNetwork}, + UserInfo, + }, + Id, }, handlers::mail::send_email_mfa_code_email, mail::Mail, @@ -31,7 +36,7 @@ struct ClientLoginSession { pub(super) struct ClientMfaServer { pool: PgPool, mail_tx: UnboundedSender, - wireguard_tx: Sender, + events_tx: Sender, sessions: HashMap, } @@ -40,12 +45,12 @@ impl ClientMfaServer { pub fn new( pool: PgPool, mail_tx: UnboundedSender, - wireguard_tx: Sender, + events_tx: Sender, ) -> Self { Self { pool, mail_tx, - wireguard_tx, + events_tx, sessions: HashMap::new(), } } @@ -260,8 +265,8 @@ impl ClientMfaServer { is_authorized: network_device.is_authorized, }], }; - let event = GatewayEvent::DeviceCreated(device_info); - self.wireguard_tx.send(event).map_err(|err| { + let event = ChangeEvent::DeviceCreated(device_info); + self.events_tx.send(event).map_err(|err| { error!("Error sending WireGuard event: {err}"); Status::internal("unexpected error") })?; diff --git a/src/grpc/gateway.rs b/src/grpc/gateway.rs index 64125f34a..66ab8bdd1 100644 --- a/src/grpc/gateway.rs +++ b/src/grpc/gateway.rs @@ -1,138 +1,42 @@ use std::{ - pin::Pin, - sync::{Arc, Mutex}, - task::{Context, Poll}, + str::FromStr, + sync::atomic::{AtomicU64, Ordering}, }; use chrono::{DateTime, Utc}; -use sqlx::{query, Error as SqlxError, PgExecutor, PgPool}; +use sqlx::PgPool; use tokio::{ sync::{ - broadcast::{Receiver as BroadcastReceiver, Sender}, - mpsc::{self, Receiver, UnboundedSender}, + broadcast::{Receiver, Sender}, + mpsc::{self, UnboundedSender}, }, - task::JoinHandle, + time::sleep, +}; +use tokio_stream::wrappers::UnboundedReceiverStream; +use tonic::{ + transport::{ClientTlsConfig, Endpoint}, + Code, Status, }; -use tokio_stream::Stream; -use tonic::{metadata::MetadataMap, Code, Request, Response, Status}; -use super::GatewayMap; +use super::TEN_SECS; use crate::{ + auth::{Claims, ClaimsType}, db::{ - models::wireguard::{WireguardNetwork, WireguardPeerStats}, - Device, GatewayEvent, Id, NoId, + models::{ + device::Device, + gateway::Gateway, + wireguard::{ChangeEvent, WireguardNetwork, WireguardPeerStats}, + }, + Id, NoId, }, + handlers::mail::send_gateway_disconnected_email, mail::Mail, }; -tonic::include_proto!("gateway"); - -pub struct GatewayServer { - pool: PgPool, - state: Arc>, - wireguard_tx: Sender, - mail_tx: UnboundedSender, -} - -impl WireguardNetwork { - /// Get a list of all allowed peers - /// - /// Each device is marked as allowed or not allowed in a given network, - /// which enables enforcing peer disconnect in MFA-protected networks. - pub async fn get_peers<'e, E>(&self, executor: E) -> Result, SqlxError> - where - E: PgExecutor<'e>, - { - debug!("Fetching all peers for network {}", self.id); - let rows = query!( - "SELECT d.wireguard_pubkey pubkey, preshared_key, \ - array[host(wnd.wireguard_ip)] \"allowed_ips!: Vec\" \ - FROM wireguard_network_device wnd \ - JOIN device d ON wnd.device_id = d.id \ - JOIN \"user\" u ON d.user_id = u.id \ - WHERE wireguard_network_id = $1 AND (is_authorized = true OR NOT $2) \ - AND u.is_active = true \ - ORDER BY d.id ASC", - self.id, - self.mfa_enabled - ) - .fetch_all(executor) - .await?; +#[cfg(test)] +mod tests; - // keepalive has to be added manually because Postgres - // doesn't support unsigned integers - let result = rows - .into_iter() - .map(|row| Peer { - pubkey: row.pubkey, - allowed_ips: row.allowed_ips, - preshared_key: row.preshared_key, - keepalive_interval: Some(self.keepalive_interval as u32), - }) - .collect(); - - Ok(result) - } -} - -impl GatewayServer { - /// Create new gateway server instance - #[must_use] - pub fn new( - pool: PgPool, - state: Arc>, - wireguard_tx: Sender, - mail_tx: UnboundedSender, - ) -> Self { - Self { - pool, - state, - wireguard_tx, - mail_tx, - } - } - - fn get_network_id(metadata: &MetadataMap) -> Result { - match Self::get_network_id_from_metadata(metadata) { - Some(m) => Ok(m), - None => Err(Status::new( - Code::Internal, - "Network ID was not found in metadata", - )), - } - } - - // parse network id from gateway request metadata from intercepted information from JWT token - fn get_network_id_from_metadata(metadata: &MetadataMap) -> Option { - if let Some(ascii_value) = metadata.get("gateway_network_id") { - if let Ok(slice) = ascii_value.clone().to_str() { - if let Ok(id) = slice.parse::() { - return Some(id); - } - } - } - None - } - - // extract gateway hostname from request headers - fn get_gateway_hostname(metadata: &MetadataMap) -> Result { - match metadata.get("hostname") { - Some(ascii_value) => { - let hostname = ascii_value.to_str().map_err(|_| { - Status::new( - Code::Internal, - "Failed to parse gateway hostname from request metadata", - ) - })?; - Ok(hostname.into()) - } - None => Err(Status::new( - Code::Internal, - "Gateway hostname not found in request metadata", - )), - } - } -} +tonic::include_proto!("gateway"); fn gen_config(network: &WireguardNetwork, peers: Vec) -> Configuration { Configuration { @@ -166,394 +70,55 @@ impl WireguardPeerStats { } } -/// Helper struct for handling gateway events -struct GatewayUpdatesHandler { - network_id: Id, - network: WireguardNetwork, - gateway_hostname: String, - events_rx: BroadcastReceiver, - tx: mpsc::Sender>, -} - -impl GatewayUpdatesHandler { - pub fn new( - network_id: Id, - network: WireguardNetwork, - gateway_hostname: String, - events_rx: BroadcastReceiver, - tx: mpsc::Sender>, - ) -> Self { - Self { - network_id, - network, - gateway_hostname, - events_rx, - tx, - } - } - - /// Process incoming gateway events - /// - /// Main gRPC server uses a shared channel for broadcasting all gateway events - /// so the handler must determine if an event is relevant for the network being services - pub async fn run(&mut self) { - info!( - "Starting update stream to gateway: {}, network {}", - self.gateway_hostname, self.network - ); - while let Ok(update) = self.events_rx.recv().await { - debug!("Received WireGuard update: {update:?}"); - let result = match update { - GatewayEvent::NetworkCreated(network_id, network) => { - if network_id == self.network_id { - self.send_network_update(&network, Vec::new(), 0).await - } else { - Ok(()) - } - } - GatewayEvent::NetworkModified(network_id, network, peers) => { - if network_id == self.network_id { - let result = self.send_network_update(&network, peers, 1).await; - // update stored network data - self.network = network; - result - } else { - Ok(()) - } - } - GatewayEvent::NetworkDeleted(network_id, network_name) => { - if network_id == self.network_id { - self.send_network_delete(&network_name).await - } else { - Ok(()) - } - } - GatewayEvent::DeviceCreated(device) => { - // check if a peer has to be added in the current network - match device - .network_info - .iter() - .find(|info| info.network_id == self.network_id) - { - Some(network_info) => { - if self.network.mfa_enabled && !network_info.is_authorized { - debug!("Created WireGuard device {} is not authorized to connect to MFA enabled location {}", - device.device.name, self.network.name - ); - continue; - }; - self.send_peer_update( - Peer { - pubkey: device.device.wireguard_pubkey, - allowed_ips: vec![network_info.device_wireguard_ip.to_string()], - preshared_key: network_info.preshared_key.clone(), - keepalive_interval: Some( - self.network.keepalive_interval as u32, - ), - }, - 0, - ) - .await - } - None => Ok(()), - } - } - GatewayEvent::DeviceModified(device) => { - // check if a peer has to be updated in the current network - match device - .network_info - .iter() - .find(|info| info.network_id == self.network_id) - { - Some(network_info) => { - if self.network.mfa_enabled && !network_info.is_authorized { - debug!("Modified WireGuard device {} is not authorized to connect to MFA enabled location {}", - device.device.name, self.network.name - ); - continue; - }; - self.send_peer_update( - Peer { - pubkey: device.device.wireguard_pubkey, - allowed_ips: vec![network_info.device_wireguard_ip.to_string()], - preshared_key: network_info.preshared_key.clone(), - keepalive_interval: Some( - self.network.keepalive_interval as u32, - ), - }, - 1, - ) - .await - } - None => Ok(()), - } - } - GatewayEvent::DeviceDeleted(device) => { - // check if a peer has to be updated in the current network - match device - .network_info - .iter() - .find(|info| info.network_id == self.network_id) - { - Some(_) => self.send_peer_delete(&device.device.wireguard_pubkey).await, - None => Ok(()), - } - } - }; - if result.is_err() { - error!( - "Closing update steam to gateway: {}, network {}", - self.gateway_hostname, self.network - ); - break; - } - } - } - - /// Sends updated network configuration - async fn send_network_update( - &self, - network: &WireguardNetwork, - peers: Vec, - update_type: i32, - ) -> Result<(), Status> { - debug!("Sending network update for network {network}"); - if let Err(err) = self - .tx - .send(Ok(Update { - update_type, - update: Some(update::Update::Network(Configuration { - name: network.name.clone(), - prvkey: network.prvkey.clone(), - address: network.address.to_string(), - port: network.port as u32, - peers, - })), - })) - .await - { - let msg = format!( - "Failed to send network update, network {network}, update type: {update_type} ({}), error: {err}", - if update_type == 0 { - "CREATE" - } else { - "MODIFY" - }, - ); - error!(msg); - return Err(Status::new(Code::Internal, msg)); - } - debug!("Network update sent for network {network}"); - Ok(()) - } - - /// Sends delete network command to gateway - async fn send_network_delete(&self, network_name: &str) -> Result<(), Status> { - debug!( - "Sending network delete command for network {}", - self.network - ); - if let Err(err) = self - .tx - .send(Ok(Update { - update_type: 2, - update: Some(update::Update::Network(Configuration { - name: network_name.to_string(), - prvkey: String::new(), - address: String::new(), - port: 0, - peers: Vec::new(), - })), - })) - .await - { - let msg = format!( - "Failed to send network update, network {}, update type: 2 (DELETE), error: {err}", - self.network, - ); - error!(msg); - return Err(Status::new(Code::Internal, msg)); - } - debug!("Network delete command sent for network {}", self.network); - Ok(()) - } - - /// Send update peer command to gateway - async fn send_peer_update(&self, peer: Peer, update_type: i32) -> Result<(), Status> { - debug!("Sending peer update for network {}", self.network); - if let Err(err) = self - .tx - .send(Ok(Update { - update_type, - update: Some(update::Update::Peer(peer)), - })) - .await - { - let msg = format!( - "Failed to send peer update for network {}, update type: {update_type} ({}), error: {err}", - self.network, - if update_type == 0 { - "CREATE" - } else { - "MODIFY" - }, - ); - error!(msg); - return Err(Status::new(Code::Internal, msg)); - } - debug!("Peer update sent for network {}", self.network); - Ok(()) - } - - /// Send delete peer command to gateway - async fn send_peer_delete(&self, peer_pubkey: &str) -> Result<(), Status> { - debug!("Sending peer delete for network {}", self.network); - if let Err(err) = self - .tx - .send(Ok(Update { - update_type: 2, - update: Some(update::Update::Peer(Peer { - pubkey: peer_pubkey.into(), - allowed_ips: Vec::new(), - preshared_key: None, - keepalive_interval: None, - })), - })) - .await - { - let msg = format!( - "Failed to send peer update for network {}, peer {peer_pubkey}, update type: 2 (DELETE), error: {err}", - self.network, - ); - error!(msg); - return Err(Status::new(Code::Internal, msg)); - } - debug!("Peer delete command sent for network {}", self.network); - Ok(()) - } -} - -pub struct GatewayUpdatesStream { - task_handle: JoinHandle<()>, - rx: Receiver>, - network_id: Id, - gateway_hostname: String, - gateway_state: Arc>, +/// One instance per connected gateway. +pub(super) struct GatewayHandler { + endpoint: Endpoint, + gateway: Gateway, + message_id: AtomicU64, pool: PgPool, + events_tx: Sender, + mail_tx: UnboundedSender, } -impl GatewayUpdatesStream { - #[must_use] - pub fn new( - task_handle: JoinHandle<()>, - rx: Receiver>, - network_id: Id, - gateway_hostname: String, - gateway_state: Arc>, +impl GatewayHandler { + pub(super) fn new( + gateway: Gateway, + tls_config: Option, pool: PgPool, - ) -> Self { - Self { - task_handle, - rx, - network_id, - gateway_hostname, - gateway_state, - pool, - } - } -} - -impl Stream for GatewayUpdatesStream { - type Item = Result; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.rx).poll_recv(cx) - } -} - -impl Drop for GatewayUpdatesStream { - fn drop(&mut self) { - info!("Client disconnected"); - // terminate update task - self.task_handle.abort(); - // update gateway state - self.gateway_state - .lock() - .unwrap() - .disconnect_gateway(self.network_id, self.gateway_hostname.clone(), &self.pool) - .expect("Unable to disconnect gateway."); - } -} - -#[tonic::async_trait] -impl gateway_service_server::GatewayService for GatewayServer { - type UpdatesStream = GatewayUpdatesStream; - - /// Retrieve stats from gateway and save it to database - async fn stats( - &self, - request: Request>, - ) -> Result, Status> { - let network_id = Self::get_network_id(request.metadata())?; - let mut stream = request.into_inner(); - while let Some(stats_update) = stream.message().await? { - debug!("Received stats message: {stats_update:?}"); - let Some(stats_update::Payload::PeerStats(peer_stats)) = stats_update.payload else { - debug!("Received stats message is empty, skipping."); - continue; - }; - let public_key = peer_stats.public_key.clone(); - let mut stats = WireguardPeerStats::from_peer_stats(peer_stats, network_id); - // Get device by public key and fill in stats.device_id - // FIXME: keep an in-memory device map to avoid repeated DB requests - stats.device_id = match Device::find_by_pubkey(&self.pool, &public_key).await { - Ok(Some(device)) => device.id, - Ok(None) => { - error!("Device with public key {public_key} not found"); - return Err(Status::new( - Code::Internal, - format!("Device with public key {public_key} not found"), - )); - } - Err(err) => { - error!("Failed to retrieve device with public key {public_key}: {err}",); - return Err(Status::new( - Code::Internal, - format!("Failed to retrieve device with public key {public_key}: {err}",), - )); - } - }; - // Save stats to db - let stats = match stats.save(&self.pool).await { - Ok(stats) => stats, - Err(err) => { - error!("Saving WireGuard peer stats to db failed: {err}"); - return Err(Status::new( - Code::Internal, - format!("Saving WireGuard peer stats to db failed: {err}"), - )); - } - }; - info!("Saved WireGuard peer stats to db."); - debug!("WireGuard peer stats: {stats:?}"); - } + events_tx: Sender, + mail_tx: UnboundedSender, + ) -> Result { + let endpoint = Endpoint::from_shared(gateway.url.to_string())? + .http2_keep_alive_interval(TEN_SECS) + .tcp_keepalive(Some(TEN_SECS)) + .keep_alive_while_idle(true); + let endpoint = if let Some(tls) = tls_config { + endpoint.tls_config(tls)? + } else { + endpoint + }; - Ok(Response::new(())) + Ok(Self { + endpoint, + gateway, + message_id: AtomicU64::new(0), + pool, + events_tx, + mail_tx, + }) } - async fn config( - &self, - request: Request, - ) -> Result, Status> { - debug!("Sending configuration to gateway client."); - let network_id = Self::get_network_id(request.metadata())?; - let hostname = Self::get_gateway_hostname(request.metadata())?; + /// Send network and VPN configuration to gateway. + async fn send_configuration(&self, tx: &UnboundedSender) -> Result<(), Status> { + debug!("Sending configuration to gateway"); + let network_id = self.gateway.network_id; + // let hostname = Self::get_gateway_hostname(request.metadata())?; let mut network = WireguardNetwork::find_by_id(&self.pool, network_id) .await - .map_err(|e| { + .map_err(|err| { error!("Network {network_id} not found"); - Status::new(Code::Internal, format!("Failed to retrieve network: {e}")) + Status::new(Code::Internal, format!("Failed to retrieve network: {err}")) })? .ok_or_else(|| { Status::new( @@ -562,23 +127,12 @@ impl gateway_service_server::GatewayService for GatewayServer { ) })?; - debug!("Sending configuration to gateway client, network {network}."); - - // store connected gateway in memory - { - let mut state = self.state.lock().unwrap(); - state.add_gateway( - network_id, - &network.name, - hostname, - request.into_inner().name, - self.mail_tx.clone(), - ); - } - - network.connected_at = Some(Utc::now().naive_utc()); - if let Err(err) = network.save(&self.pool).await { - error!("Failed to save updated network {network_id} in the database, status: {err}"); + debug!( + "Sending configuration to {}, network {network}", + self.gateway + ); + if let Err(err) = network.touch_connected(&self.pool).await { + error!("Failed to update connected at for network {network_id} in the database, status: {err}"); } let peers = network.get_peers(&self.pool).await.map_err(|error| { @@ -589,66 +143,378 @@ impl gateway_service_server::GatewayService for GatewayServer { ) })?; - info!("Configuration sent to gateway client, network {network}."); - - Ok(Response::new(gen_config(&network, peers))) + let payload = Some(core_response::Payload::Config(gen_config(&network, peers))); + let id = self.message_id.fetch_add(1, Ordering::Relaxed); + let req = CoreResponse { id, payload }; + match tx.send(req) { + Ok(()) => { + info!("Configuration sent to {}, network {network}", self.gateway); + Ok(()) + } + Err(err) => { + error!("Failed to send configuration sent to {}", self.gateway); + Err(Status::new( + Code::Internal, + format!("Configuration not sent to {}, error {err}", self.gateway), + )) + } + } } - async fn updates(&self, request: Request<()>) -> Result, Status> { - let gateway_network_id = Self::get_network_id(request.metadata())?; - let hostname = Self::get_gateway_hostname(request.metadata())?; - - let Some(network) = WireguardNetwork::find_by_id(&self.pool, gateway_network_id) - .await - .map_err(|_| { - error!("Failed to fetch network {gateway_network_id} from the database"); - Status::new( - Code::Internal, - format!("Failed to retrieve network {gateway_network_id} from the database"), - ) - })? + /// Send gateway disconnected notification. + /// Sends notification only if last notification time is bigger than specified in config. + async fn send_disconnect_notification(&self) { + debug!("Sending gateway disconnect email notification"); + let hostname = self.gateway.hostname.clone(); + let mail_tx = self.mail_tx.clone(); + let pool = self.pool.clone(); + let url = self.gateway.url.clone(); + + let Ok(Some(network)) = + WireguardNetwork::find_by_id(&self.pool, self.gateway.network_id).await else { - return Err(Status::new( - Code::Internal, - format!("Network with id {gateway_network_id} not found"), - )); + error!( + "Failed to fetch network ID {} from database", + self.gateway.network_id + ); + return; }; - info!("New client connected to updates stream: {hostname}, network {network}",); + // Send email only if disconnection time is before the connection time. + let send_email = if let (Some(connected_at), Some(disconnected_at)) = + (self.gateway.connected_at, self.gateway.disconnected_at) + { + disconnected_at <= connected_at + } else { + true + }; + if send_email { + // FIXME: Try to get rid of spawn and use something like block_on + // To return result instead of logging + tokio::spawn(async move { + if let Err(err) = + send_gateway_disconnected_email(hostname, &network.name, &url, &mail_tx, &pool) + .await + { + error!("Failed to send gateway disconnect notification: {err}"); + } else { + info!("Email notification sent about gateway being disconnected"); + } + }); + } else { + info!( + "{} disconnected. Email notification not sent.", + self.gateway + ); + }; + } - let (tx, rx) = mpsc::channel(4); - let events_rx = self.wireguard_tx.subscribe(); - let mut state = self.state.lock().unwrap(); - state - .connect_gateway(gateway_network_id, &hostname) - .map_err(|err| { - error!("Failed to connect gateway on network {gateway_network_id}: {err}"); - Status::new( - Code::Internal, - "Failed to connect gateway on network {gateway_network_id}", + /// Connect to Gateway and handle its messages through gRPC. + pub(super) async fn handle_connection(&mut self) -> ! { + let uri = self.endpoint.uri(); + loop { + #[cfg(not(test))] + let channel = self.endpoint.connect_lazy(); + #[cfg(test)] + let channel = self.endpoint.connect_with_connector_lazy(tower::service_fn( + |_: tonic::transport::Uri| async { + Ok::<_, std::io::Error>(hyper_util::rt::TokioIo::new( + tokio::net::UnixStream::connect(tests::TONIC_SOCKET).await?, + )) + }, + )); + + debug!("Connecting to gateway {uri}"); + let mut client = gateway_client::GatewayClient::new(channel); + let (tx, rx) = mpsc::unbounded_channel(); + let response = match client.bidi(UnboundedReceiverStream::new(rx)).await { + Ok(response) => response, + Err(err) => { + error!("Failed to connect to gateway {uri}, retrying: {err}"); + sleep(TEN_SECS).await; + continue; + } + }; + + info!("Connected to gateway {uri}"); + let mut resp_stream = response.into_inner(); + let mut config_sent = false; + + 'message: loop { + match resp_stream.message().await { + Ok(None) => { + info!("stream was closed by the sender"); + break 'message; + } + Ok(Some(received)) => { + info!("Received message from gateway."); + debug!("Message from gateway {uri}: {received:?}"); + match received.payload { + Some(core_request::Payload::ConfigRequest(config_request)) => { + if config_sent { + warn!( + "Ignoring repeated configuration request from {}", + self.gateway + ); + continue; + } + // Validate authorization token. + if let Ok(claims) = Claims::from_jwt( + ClaimsType::Gateway, + &config_request.auth_token, + ) { + if let Ok(client_id) = Id::from_str(&claims.client_id) { + if client_id == self.gateway.network_id { + debug!( + "Authorization token is correct for {}", + self.gateway + ); + } else { + warn!("Authorization token received from {uri} has `client_id` for a different network"); + continue; + } + } else { + warn!("Authorization token received from {uri} has incorrect `client_id`"); + continue; + } + } else { + warn!("Invalid authorization token received from {uri}"); + continue; + } + + // Send network configuration to gateway. + match self.send_configuration(&tx).await { + Ok(()) => { + info!("Sent configuration to {}", self.gateway); + config_sent = true; + let _ = self + .gateway + .touch_connected(&self.pool, config_request.hostname) + .await; + } + Err(err) => { + error!( + "Failed to send configuration to {}: {err}", + self.gateway + ); + } + } + + // Start observing configuration changes. + let Ok(Some(network)) = WireguardNetwork::find_by_id( + &self.pool, + self.gateway.network_id, + ) + .await + else { + error!( + "Failed to fetch network ID {} from the database", + self.gateway.network_id + ); + continue; + }; + tokio::spawn(handle_events( + network, + tx.clone(), + self.events_tx.subscribe(), + )); + } + Some(core_request::Payload::PeerStats(peer_stats)) => { + if !config_sent { + warn!("Ignoring peer statistics from {} because it didn't authorize itself", self.gateway); + continue; + } + + let public_key = peer_stats.public_key.clone(); + let mut stats = WireguardPeerStats::from_peer_stats( + peer_stats, + self.gateway.network_id, + ); + // Get device by public key and fill in stats.device_id + match Device::find_by_pubkey(&self.pool, &public_key).await { + Ok(Some(device)) => { + stats.device_id = device.id; + match stats.save(&self.pool).await { + Ok(_) => info!("Saved WireGuard peer stats to database."), + Err(err) => error!("Failed to save WireGuard peer stats to database: {err}"), + } + } + Ok(None) => { + error!("Device with public key {public_key} not found"); + } + Err(err) => { + error!("Failed to retrieve device with public key {public_key}: {err}",); + } + }; + } + None => (), + }; + } + Err(err) => { + error!("Disconnected from gateway at {uri}, error: {err}"); + // Important: call this funtion before setting disconnection time. + self.send_disconnect_notification().await; + let _ = self.gateway.touch_disconnected(&self.pool).await; + debug!("Waiting 10s to re-establish the connection"); + sleep(TEN_SECS).await; + break 'message; + } + } + } + } + } +} + +/// Process incoming gateway events +/// +/// Main gRPC server uses a shared channel for broadcasting all gateway events +/// so the handler must determine if an event is relevant for the network being serviced. +async fn handle_events( + mut current_network: WireguardNetwork, + tx: UnboundedSender, + mut events_rx: Receiver, +) { + info!("Starting update stream network {}", current_network); + while let Ok(event) = events_rx.recv().await { + debug!("Received networking state update event: {event:?}"); + let (update_type, update) = match event { + ChangeEvent::NetworkCreated(network) => { + if network.id != current_network.id { + continue; + } + ( + UpdateType::Create, + update::Update::Network(Configuration { + name: network.name.clone(), + prvkey: network.prvkey.clone(), + address: network.address.to_string(), + port: network.port as u32, + peers: Vec::new(), + }), ) - })?; + } + ChangeEvent::NetworkModified(network, peers) => { + if network.id != current_network.id { + continue; + } + // update stored network data + current_network = network.clone(); + ( + UpdateType::Modify, + update::Update::Network(Configuration { + name: network.name, + prvkey: network.prvkey, + address: network.address.to_string(), + port: network.port as u32, + peers, + }), + ) + } + ChangeEvent::NetworkDeleted(network_id, network_name) => { + if network_id != current_network.id { + continue; + } + ( + UpdateType::Delete, + update::Update::Network(Configuration { + name: network_name.to_string(), + prvkey: String::new(), + address: String::new(), + port: 0, + peers: Vec::new(), + }), + ) + } + ChangeEvent::DeviceCreated(device) => { + // check if a peer has to be added in the current network + match device + .network_info + .iter() + .find(|info| info.network_id == current_network.id) + { + Some(network_info) => { + if current_network.mfa_enabled && !network_info.is_authorized { + debug!("Created WireGuard device {} is not authorized to connect to MFA enabled location {}", + device.device.name, current_network.name + ); + continue; + }; + let peer = Peer { + pubkey: device.device.wireguard_pubkey, + allowed_ips: vec![network_info.device_wireguard_ip.to_string()], + preshared_key: network_info.preshared_key.clone(), + keepalive_interval: Some(current_network.keepalive_interval as u32), + }; + (UpdateType::Create, update::Update::Peer(peer)) + } + None => continue, + } + } + ChangeEvent::DeviceModified(device) => { + // check if a peer has to be updated in the current network + match device + .network_info + .iter() + .find(|info| info.network_id == current_network.id) + { + Some(network_info) => { + if current_network.mfa_enabled && !network_info.is_authorized { + debug!("Modified WireGuard device {} is not authorized to connect to MFA enabled location {}", + device.device.name, current_network.name + ); + continue; + }; + let peer = Peer { + pubkey: device.device.wireguard_pubkey, + allowed_ips: vec![network_info.device_wireguard_ip.to_string()], + preshared_key: network_info.preshared_key.clone(), + keepalive_interval: Some(current_network.keepalive_interval as u32), + }; + (UpdateType::Modify, update::Update::Peer(peer)) + } + None => continue, + } + } + ChangeEvent::DeviceDeleted(device) => { + // check if a peer has to be updated in the current network + match device + .network_info + .iter() + .find(|info| info.network_id == current_network.id) + { + Some(_) => ( + UpdateType::Delete, + update::Update::Peer(Peer { + pubkey: device.device.wireguard_pubkey, + allowed_ips: Vec::new(), + preshared_key: None, + keepalive_interval: None, + }), + ), + None => continue, + } + } + }; - // clone here before moving into a closure - let gateway_hostname = hostname.clone(); - let handle = tokio::spawn(async move { - let mut update_handler = GatewayUpdatesHandler::new( - gateway_network_id, - network, - gateway_hostname, - events_rx, - tx, + let req = CoreResponse { + id: 0, + payload: Some(core_response::Payload::Update(Update { + update_type: update_type as i32, + update: Some(update), + })), + }; + if let Err(err) = tx.send(req) { + error!( + "Failed to send network update, network {}, update type: {}, error: {err}", + current_network, + update_type.as_str_name() ); - update_handler.run().await; - }); - - Ok(Response::new(GatewayUpdatesStream::new( - handle, - rx, - gateway_network_id, - hostname, - Arc::clone(&self.state), - self.pool.clone(), - ))) + break; + } + debug!( + "Network update sent for network {}, update type: {}", + current_network, + update_type.as_str_name() + ); } } diff --git a/src/grpc/gateway/tests.rs b/src/grpc/gateway/tests.rs new file mode 100644 index 000000000..18174116e --- /dev/null +++ b/src/grpc/gateway/tests.rs @@ -0,0 +1,87 @@ +use std::{ + io, + net::{IpAddr, Ipv4Addr}, +}; + +use ipnetwork::IpNetwork; +use tokio::{ + net::UnixListener, + sync::{broadcast, mpsc::unbounded_channel}, +}; +use tokio_stream::wrappers::UnixListenerStream; +use tonic::{transport::Server, Request, Response, Status, Streaming}; + +use super::*; + +pub(super) static TONIC_SOCKET: &str = "tonic.sock"; + +struct FakeGateway; + +#[tonic::async_trait] +impl gateway_server::Gateway for FakeGateway { + type BidiStream = UnboundedReceiverStream>; + + async fn bidi( + &self, + request: Request>, + ) -> Result, Status> { + let (_tx, rx) = mpsc::unbounded_channel(); + let mut stream = request.into_inner(); + tokio::spawn(async move { + loop { + match stream.message().await { + Ok(Some(_response)) => (), + Ok(None) => (), + Err(_err) => (), + } + } + }); + + Ok(Response::new(UnboundedReceiverStream::new(rx))) + } +} + +async fn fake_gateway() -> Result<(), io::Error> { + let gateway = FakeGateway {}; + + let uds = UnixListener::bind(TONIC_SOCKET)?; + let uds_stream = UnixListenerStream::new(uds); + + Server::builder() + .add_service(gateway_server::GatewayServer::new(gateway)) + .serve_with_incoming(uds_stream) + .await + .unwrap(); + + Ok(()) +} + +#[sqlx::test] +async fn test_gateway(pool: PgPool) { + let network = WireguardNetwork::new( + "TestNet".to_string(), + IpNetwork::new(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 1)), 24).unwrap(), + 50051, + "0.0.0.0".to_string(), + None, + vec![IpNetwork::new(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 24).unwrap()], + false, + 0, + 0, + ) + .save(&pool) + .await + .unwrap(); + let gateway = Gateway::new(network.id, "http://[::]:50051") + .save(&pool) + .await + .unwrap(); + let (events_tx, _events_rx) = broadcast::channel::(16); + let (mail_tx, _mail_rx) = unbounded_channel::(); + + let mut gateway_handler = GatewayHandler::new(gateway, None, pool, events_tx, mail_tx).unwrap(); + let handle = tokio::spawn(async move { + gateway_handler.handle_connection().await; + }); + handle.abort(); +} diff --git a/src/grpc/interceptor.rs b/src/grpc/interceptor.rs index 190d0f09e..17e86c365 100644 --- a/src/grpc/interceptor.rs +++ b/src/grpc/interceptor.rs @@ -1,4 +1,4 @@ -use tonic::{service::Interceptor, Status}; +use tonic::{service::Interceptor, Request, Status}; use crate::auth::{Claims, ClaimsType}; @@ -11,13 +11,13 @@ pub struct JwtInterceptor { impl JwtInterceptor { #[must_use] - pub fn new(claims_type: ClaimsType) -> Self { + pub(crate) fn new(claims_type: ClaimsType) -> Self { Self { claims_type } } } impl Interceptor for JwtInterceptor { - fn call(&mut self, mut req: tonic::Request<()>) -> Result, Status> { + fn call(&mut self, mut req: Request<()>) -> Result, Status> { let token = match req.metadata().get("authorization") { Some(token) => token .to_str() @@ -28,23 +28,18 @@ impl Interceptor for JwtInterceptor { let request_metadata = req.metadata_mut(); if let ClaimsType::Gateway = self.claims_type { + // This type of claim should not end up here. + } else { + // FIXME: can we push whole Claims object into metadata? request_metadata.insert( - "gateway_network_id", + "username", claims - .client_id + .sub .parse() - .map_err(|_| Status::unknown("Network ID parsing error"))?, + .map_err(|_| Status::unknown("Username parsing error"))?, ); } - // FIXME: can we push whole Claims object into metadata? - request_metadata.insert( - "username", - claims - .sub - .parse() - .map_err(|_| Status::unknown("Username parsing error"))?, - ); debug!("Authorization successful for user {}", claims.sub); Ok(req) } else { diff --git a/src/grpc/mod.rs b/src/grpc/mod.rs index ea2a26cbd..8630fc23f 100644 --- a/src/grpc/mod.rs +++ b/src/grpc/mod.rs @@ -1,6 +1,5 @@ use std::{ collections::hash_map::HashMap, - fs::read_to_string, time::{Duration, Instant}, }; #[cfg(any(feature = "wireguard", feature = "worker"))] @@ -9,35 +8,32 @@ use std::{ sync::{Arc, Mutex}, }; -use chrono::{Duration as ChronoDuration, NaiveDateTime, Utc}; +use chrono::NaiveDateTime; use reqwest::Url; use serde::Serialize; -#[cfg(feature = "worker")] -use sqlx::PgPool; -use thiserror::Error; +use sqlx::{postgres::PgListener, PgPool}; use tokio::{ sync::{ broadcast::Sender, mpsc::{self, UnboundedSender}, }, + task::{AbortHandle, JoinSet}, time::sleep, }; use tokio_stream::wrappers::UnboundedReceiverStream; use tonic::{ - transport::{Certificate, ClientTlsConfig, Endpoint, Identity, Server, ServerTlsConfig}, + transport::{Endpoint, Identity, Server, ServerTlsConfig}, Code, Status, }; use uaparser::UserAgentParser; -use uuid::Uuid; #[cfg(feature = "wireguard")] -use self::gateway::{gateway_service_server::GatewayServiceServer, GatewayServer}; +use self::gateway::GatewayHandler; use self::{ auth::{auth_service_server::AuthServiceServer, AuthServer}, desktop_client_mfa::ClientMfaServer, - enrollment::EnrollmentServer, - password_reset::PasswordResetServer, proto::core_response, + proxy::ProxyHandler, }; #[cfg(feature = "worker")] use self::{ @@ -46,27 +42,28 @@ use self::{ }; use crate::{ auth::failed_login::FailedLoginMap, - db::{AppEvent, Id, Settings}, + db::{ + models::{gateway::Gateway, settings::Settings, webhook::AppEvent}, + ChangeNotification, Id, TriggerOperation, + }, enterprise::{ db::models::enterprise_settings::EnterpriseSettings, grpc::polling::PollingServer, license::{get_cached_license, validate_license}, }, - handlers::mail::send_gateway_disconnected_email, mail::Mail, server_config, }; #[cfg(feature = "worker")] -use crate::{auth::ClaimsType, db::GatewayEvent}; +use crate::{auth::ClaimsType, db::models::wireguard::ChangeEvent}; mod auth; mod desktop_client_mfa; -pub mod enrollment; #[cfg(feature = "wireguard")] pub(crate) mod gateway; #[cfg(any(feature = "wireguard", feature = "worker"))] mod interceptor; -pub mod password_reset; +mod proxy; pub(crate) mod utils; #[cfg(feature = "worker")] pub mod worker; @@ -77,262 +74,31 @@ pub(crate) mod proto { use proto::{core_request, proxy_client::ProxyClient, CoreError, CoreResponse}; -// Helper struct used to handle gateway state -// gateways are grouped by network -type GatewayHostname = String; -#[derive(Debug)] -pub struct GatewayMap(HashMap>); - -#[derive(Error, Debug)] -pub enum GatewayMapError { - #[error("Gateway {1} for network {0} not found")] - NotFound(i64, GatewayHostname), - #[error("Network {0} not found")] - NetworkNotFound(i64), - #[error("Gateway with UID {0} not found")] - UidNotFound(Uuid), - #[error("Cannot remove. Gateway with UID {0} is still active")] - RemoveActive(Uuid), - #[error("Config missing")] - ConfigError, -} - -impl GatewayMap { - #[must_use] - pub fn new() -> Self { - Self(HashMap::new()) - } - - // add a new gateway to map - // this method is meant to be called when a gateway requests a config - // as a sort of "registration" - pub fn add_gateway( - &mut self, - network_id: Id, - network_name: &str, - hostname: String, - name: Option, - mail_tx: UnboundedSender, - ) { - info!("Adding gateway {hostname} with to gateway map for network {network_id}",); - let gateway_state = GatewayState::new(network_id, network_name, &hostname, name, mail_tx); - - if let Some(network_gateway_map) = self.0.get_mut(&network_id) { - network_gateway_map.entry(hostname).or_insert(gateway_state); - } else { - // no map for a given network exists yet - let mut network_gateway_map = HashMap::new(); - network_gateway_map.insert(hostname, gateway_state); - self.0.insert(network_id, network_gateway_map); - } - } - - // remove gateway from map - pub fn remove_gateway(&mut self, network_id: Id, uid: Uuid) -> Result<(), GatewayMapError> { - debug!("Removing gateway from network {network_id}"); - if let Some(network_gateway_map) = self.0.get_mut(&network_id) { - // find gateway by uuid - let hostname = match network_gateway_map - .iter() - .find(|(_address, state)| state.uid == uid) - { - None => { - error!("Failed to find gateway with UID {uid}"); - return Err(GatewayMapError::UidNotFound(uid)); - } - Some((hostname, state)) => { - if state.connected { - error!("Cannot remove. Gateway with UID {uid} is still active"); - return Err(GatewayMapError::RemoveActive(uid)); - } - hostname.clone() - } - }; - // remove matching gateway - network_gateway_map.remove(&hostname) - } else { - // no map for a given network exists yet - error!("Network {network_id} not found in gateway map"); - return Err(GatewayMapError::NetworkNotFound(network_id)); - }; - info!("Gateway with UID {uid} removed from network {network_id}"); - Ok(()) - } - - // change gateway status to connected - // we assume that the gateway is already present in hashmap - pub fn connect_gateway( - &mut self, - network_id: Id, - hostname: &str, - ) -> Result<(), GatewayMapError> { - debug!("Connecting gateway {hostname} in network {network_id}"); - if let Some(network_gateway_map) = self.0.get_mut(&network_id) { - if let Some(state) = network_gateway_map.get_mut(hostname) { - state.connected = true; - state.disconnected_at = None; - state.connected_at = Some(Utc::now().naive_utc()); - debug!( - "Gateway {hostname} found in gateway map, current state: {:#?}", - state - ); - } else { - error!("Gateway {hostname} not found in gateway map for network {network_id}"); - return Err(GatewayMapError::NotFound(network_id, hostname.into())); - } - } else { - // no map for a given network exists yet - error!("Network {network_id} not found in gateway map"); - return Err(GatewayMapError::NetworkNotFound(network_id)); - }; - info!("Gateway {hostname} connected in network {network_id}"); - Ok(()) - } - - // change gateway status to disconnected - pub fn disconnect_gateway( - &mut self, - network_id: Id, - hostname: String, - pool: &PgPool, - ) -> Result<(), GatewayMapError> { - debug!("Disconnecting gateway {hostname} in network {network_id}"); - if let Some(network_gateway_map) = self.0.get_mut(&network_id) { - if let Some(state) = network_gateway_map.get_mut(&hostname) { - state.connected = false; - state.disconnected_at = Some(Utc::now().naive_utc()); - state.send_disconnect_notification(pool); - debug!("Gateway {hostname} found in gateway map, current state: {state:#?}"); - info!("Gateway {hostname} disconnected in network {network_id}"); - return Ok(()); - }; - }; - let err = GatewayMapError::NotFound(network_id, hostname); - error!("Gateway disconnect failed: {err}"); - Err(err) - } - - // return `true` if at least one gateway in a given network is connected - #[must_use] - pub fn connected(&self, network_id: Id) -> bool { - match self.0.get(&network_id) { - Some(network_gateway_map) => network_gateway_map - .values() - .any(|gateway| gateway.connected), - None => false, - } - } - - // return a list af aff statuses af all gateways in a given network - #[must_use] - pub fn get_network_gateway_status(&self, network_id: Id) -> Vec { - match self.0.get(&network_id) { - Some(network_gateway_map) => network_gateway_map.clone().into_values().collect(), - None => Vec::new(), - } - } - - // return gateway name - #[must_use] - pub fn get_network_gateway_name(&self, network_id: Id, hostname: &str) -> Option { - match self.0.get(&network_id) { - Some(network_gateway_map) => { - if let Some(state) = network_gateway_map.get(hostname) { - state.name.clone() - } else { - None - } - } - None => None, - } - } -} - -impl Default for GatewayMap { - fn default() -> Self { - Self::new() - } -} - -#[derive(Serialize, Clone, Debug)] -pub struct GatewayState { - pub uid: Uuid, +#[derive(Clone, Serialize)] +pub(crate) struct GatewayState { + pub id: Id, pub connected: bool, pub network_id: Id, pub network_name: String, - pub name: Option, + pub name: Option, // TODO: remove pub hostname: String, pub connected_at: Option, pub disconnected_at: Option, - #[serde(skip)] - pub mail_tx: UnboundedSender, - #[serde(skip)] - pub last_email_notification: Option, } impl GatewayState { - #[must_use] - pub fn new>( - network_id: Id, - network_name: S, - hostname: S, - name: Option, - mail_tx: UnboundedSender, - ) -> Self { + pub(crate) fn from_gateway(gateway: &Gateway, network_name: &str) -> Self { Self { - uid: Uuid::new_v4(), - connected: false, - network_id, - network_name: network_name.into(), - name, - hostname: hostname.into(), - connected_at: None, - disconnected_at: None, - mail_tx, - last_email_notification: None, + id: gateway.id, + connected: gateway.is_connected(), + network_id: gateway.network_id, + network_name: network_name.to_owned(), + name: None, // TODO: remove + hostname: gateway.hostname.clone().unwrap_or_default(), + connected_at: gateway.connected_at, + disconnected_at: gateway.disconnected_at, } } - - /// Send gateway disconnected notification - /// Sends notification only if last notification time is bigger than specified in config - fn send_disconnect_notification(&mut self, pool: &PgPool) { - debug!("Sending gateway disconnect email notification"); - // Clone here because self doesn't live long enough - let name = self.name.clone(); - let mail_tx = self.mail_tx.clone(); - let pool = pool.clone(); - let hostname = self.hostname.clone(); - let network_name = self.network_name.clone(); - let send_email = if let Some(last_notification_time) = self.last_email_notification { - Utc::now().naive_utc() - last_notification_time - > ChronoDuration::from_std( - *server_config().gateway_disconnection_notification_timeout, - ) - .expect("Failed to parse duration") - } else { - true - }; - if send_email { - self.last_email_notification = Some(Utc::now().naive_utc()); - // FIXME: Try to get rid of spawn and use something like block_on - // To return result instead of logging - tokio::spawn(async move { - if let Err(e) = - send_gateway_disconnected_email(name, network_name, &hostname, &mail_tx, &pool) - .await - { - error!("Failed to send gateway disconnect notification: {e}"); - } else { - info!("Gateway {hostname} disconnected. Email notification sent",); - } - }); - } else { - info!( - "Gateway {hostname} disconnected. Email notification not sent. Last notification was at {:?}", - self.last_email_notification - ); - }; - } } const TEN_SECS: Duration = Duration::from_secs(10); @@ -346,52 +112,138 @@ impl From for CoreError { } } +/// Bi-directional gRPC stream for comminication with Defguard gateway. +pub async fn run_grpc_gateway_stream( + pool: PgPool, + events_tx: Sender, + mail_tx: UnboundedSender, +) -> Result<(), anyhow::Error> { + let config = server_config(); + let tls_config = config.grpc_client_tls_config()?; + + let mut abort_handles = HashMap::new(); + + let mut tasks = JoinSet::new(); + // Helper closure to launch `GatewayHandler`. + let mut launch_gateway_handler = + |gateway: Gateway| -> Result { + let mut gateway_handler = GatewayHandler::new( + gateway, + tls_config.clone(), + pool.clone(), + events_tx.clone(), + mail_tx.clone(), + )?; + let abort_handle = tasks.spawn(async move { + gateway_handler.handle_connection().await; + }); + Ok(abort_handle) + }; + + let gateways = Gateway::all(&pool).await?; + for gateway in gateways { + let id = gateway.id; + let abort_handle = launch_gateway_handler(gateway)?; + abort_handles.insert(id, abort_handle); + } + + // Observe gateway URL changes. + let mut listener = PgListener::connect_with(&pool).await?; + listener.listen("gateway_change").await?; + while let Ok(notification) = listener.recv().await { + let payload = notification.payload(); + match serde_json::from_str::>>(payload) { + Ok(gateway_notification) => { + match gateway_notification.operation { + TriggerOperation::Insert => { + if let Some(new) = gateway_notification.new { + let id = new.id; + let abort_handle = launch_gateway_handler(new)?; + abort_handles.insert(id, abort_handle); + } + } + TriggerOperation::Update => { + if let (Some(old), Some(new)) = + (gateway_notification.old, gateway_notification.new) + { + if old.url == new.url { + debug!("Gateway URL didn't change. Keeping the running gateway handler"); + } else if let Some(abort_handle) = abort_handles.remove(&old.id) { + info!( + "Aborting connection to {old}, it has changed in the database" + ); + abort_handle.abort(); + let id = new.id; + let abort_handle = launch_gateway_handler(new)?; + abort_handles.insert(id, abort_handle); + } else { + warn!("Cannot find {old} on the list of connected gateways"); + } + } + } + TriggerOperation::Delete => { + if let Some(old) = gateway_notification.old { + if let Some(abort_handle) = abort_handles.remove(&old.id) { + info!("Aborting connection to {old}, it has disappeard from the database"); + abort_handle.abort(); + } else { + warn!("Cannot find {old} on the list of connected gateways"); + } + } + } + } + } + Err(err) => error!("Failed to de-serialize database notification object: {err}"), + } + } + + while let Some(Ok(_result)) = tasks.join_next().await { + debug!("Gateway gRPC task has ended"); + } + + Ok(()) +} + /// Bi-directional gRPC stream for comminication with Defguard proxy. pub async fn run_grpc_bidi_stream( pool: PgPool, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, user_agent_parser: Arc, ) -> Result<(), anyhow::Error> { let config = server_config(); + let tls_config = config.grpc_client_tls_config()?; - // TODO: merge the two - let enrollment_server = EnrollmentServer::new( + let proxy_handler = ProxyHandler::new( pool.clone(), - wireguard_tx.clone(), + events_tx.clone(), mail_tx.clone(), user_agent_parser, ); - let password_reset_server = PasswordResetServer::new(pool.clone(), mail_tx.clone()); - let mut client_mfa_server = ClientMfaServer::new(pool.clone(), mail_tx, wireguard_tx); + let mut client_mfa_server = ClientMfaServer::new(pool.clone(), mail_tx, events_tx); let polling_server = PollingServer::new(pool); - let endpoint = Endpoint::from_shared(config.proxy_url.as_deref().unwrap())?; - let endpoint = endpoint + let endpoint = Endpoint::from_shared(config.proxy_url.as_deref().unwrap())? .http2_keep_alive_interval(TEN_SECS) .tcp_keepalive(Some(TEN_SECS)) .keep_alive_while_idle(true); - let endpoint = if let Some(ca) = &config.proxy_grpc_ca { - let ca = read_to_string(ca)?; - let tls = ClientTlsConfig::new().ca_certificate(Certificate::from_pem(ca)); + let endpoint = if let Some(tls) = tls_config { endpoint.tls_config(tls)? } else { endpoint }; + let uri = endpoint.uri(); loop { - debug!("Connecting to proxy at {}", endpoint.uri()); + debug!("Connecting to proxy at {uri}"); let mut client = ProxyClient::new(endpoint.connect_lazy()); let (tx, rx) = mpsc::unbounded_channel(); let Ok(response) = client.bidi(UnboundedReceiverStream::new(rx)).await else { - error!( - "Failed to connect to proxy @ {}, retrying in 10s", - endpoint.uri() - ); + error!("Failed to connect to proxy @ {uri}, retrying in 10s"); sleep(TEN_SECS).await; continue; }; - info!("Connected to proxy at {}", endpoint.uri()); + info!("Connected to proxy at {uri}"); let mut resp_stream = response.into_inner(); 'message: loop { match resp_stream.message().await { @@ -401,11 +253,11 @@ pub async fn run_grpc_bidi_stream( } Ok(Some(received)) => { info!("Received message from proxy."); - debug!("Received the following message from proxy: {received:?}"); + debug!("Message from proxy: {received:?}"); let payload = match received.payload { // rpc StartEnrollment (EnrollmentStartRequest) returns (EnrollmentStartResponse) Some(core_request::Payload::EnrollmentStart(request)) => { - match enrollment_server.start_enrollment(request).await { + match proxy_handler.start_enrollment(request).await { Ok(response_payload) => { Some(core_response::Payload::EnrollmentStart(response_payload)) } @@ -417,7 +269,7 @@ pub async fn run_grpc_bidi_stream( } // rpc ActivateUser (ActivateUserRequest) returns (google.protobuf.Empty) Some(core_request::Payload::ActivateUser(request)) => { - match enrollment_server + match proxy_handler .activate_user(request, received.device_info) .await { @@ -430,7 +282,7 @@ pub async fn run_grpc_bidi_stream( } // rpc CreateDevice (NewDevice) returns (DeviceConfigResponse) Some(core_request::Payload::NewDevice(request)) => { - match enrollment_server + match proxy_handler .create_device(request, received.device_info) .await { @@ -445,7 +297,7 @@ pub async fn run_grpc_bidi_stream( } // rpc GetNetworkInfo (ExistingDevice) returns (DeviceConfigResponse) Some(core_request::Payload::ExistingDevice(request)) => { - match enrollment_server.get_network_info(request).await { + match proxy_handler.get_network_info(request).await { Ok(response_payload) => { Some(core_response::Payload::DeviceConfig(response_payload)) } @@ -457,7 +309,7 @@ pub async fn run_grpc_bidi_stream( } // rpc RequestPasswordReset (PasswordResetInitializeRequest) returns (google.protobuf.Empty) Some(core_request::Payload::PasswordResetInit(request)) => { - match password_reset_server + match proxy_handler .request_password_reset(request, received.device_info) .await { @@ -470,7 +322,7 @@ pub async fn run_grpc_bidi_stream( } // rpc StartPasswordReset (PasswordResetStartRequest) returns (PasswordResetStartResponse) Some(core_request::Payload::PasswordResetStart(request)) => { - match password_reset_server.start_password_reset(request).await { + match proxy_handler.start_password_reset(request).await { Ok(response_payload) => Some( core_response::Payload::PasswordResetStart(response_payload), ), @@ -482,7 +334,7 @@ pub async fn run_grpc_bidi_stream( } // rpc ResetPassword (PasswordResetRequest) returns (google.protobuf.Empty) Some(core_request::Payload::PasswordReset(request)) => { - match password_reset_server + match proxy_handler .reset_password(request, received.device_info) .await { @@ -524,18 +376,14 @@ pub async fn run_grpc_bidi_stream( Some(core_response::Payload::InstanceInfo(response_payload)) } Err(err) => { - match err.code() { - // Ignore the case when we are not enterprise but the client is trying to fetch the instance config, - // to avoid spamming the logs with misleading errors. - Code::FailedPrecondition => { - debug!("A client tried to fetch the instance config, but we are not enterprise."); - Some(core_response::Payload::CoreError(err.into())) - } - _ => { - error!("Instance info error {err}"); - Some(core_response::Payload::CoreError(err.into())) - } + // Ignore the case when we are not enterprise but the client is trying to fetch the instance config, + // to avoid spamming the logs with misleading errors. + if err.code() == Code::FailedPrecondition { + debug!("A client tried to fetch the instance config, but we are not enterprise."); + } else { + error!("Instance info error {err}"); } + Some(core_response::Payload::CoreError(err.into())) } } } @@ -549,7 +397,7 @@ pub async fn run_grpc_bidi_stream( tx.send(req).unwrap(); } Err(err) => { - error!("Disconnected from proxy at {}", endpoint.uri()); + error!("Disconnected from proxy at {uri}"); error!("stream error: {err}"); debug!("waiting 10s to re-establish the connection"); sleep(TEN_SECS).await; @@ -564,9 +412,6 @@ pub async fn run_grpc_bidi_stream( pub async fn run_grpc_server( worker_state: Arc>, pool: PgPool, - gateway_state: Arc>, - wireguard_tx: Sender, - mail_tx: UnboundedSender, grpc_cert: Option, grpc_key: Option, failed_logins: Arc>, @@ -578,11 +423,6 @@ pub async fn run_grpc_server( WorkerServer::new(pool.clone(), worker_state), JwtInterceptor::new(ClaimsType::YubiBridge), ); - #[cfg(feature = "wireguard")] - let gateway_service = GatewayServiceServer::with_interceptor( - GatewayServer::new(pool, gateway_state, wireguard_tx, mail_tx), - JwtInterceptor::new(ClaimsType::Gateway), - ); let (mut health_reporter, health_service) = tonic_health::server::health_reporter(); health_reporter @@ -603,17 +443,18 @@ pub async fn run_grpc_server( .tcp_keepalive(Some(TEN_SECS)) .add_service(health_service) .add_service(auth_service); - #[cfg(feature = "wireguard")] - let router = router.add_service(gateway_service); + // #[cfg(feature = "wireguard")] + // let router = router.add_service(gateway_service); #[cfg(feature = "worker")] let router = router.add_service(worker_service); router.serve(addr).await?; + info!("gRPC server started on {addr}"); Ok(()) } #[cfg(feature = "worker")] -pub struct Job { +pub(crate) struct Job { id: u32, first_name: String, last_name: String, diff --git a/src/grpc/password_reset.rs b/src/grpc/password_reset.rs deleted file mode 100644 index 6a5516c16..000000000 --- a/src/grpc/password_reset.rs +++ /dev/null @@ -1,271 +0,0 @@ -use sqlx::PgPool; -use tokio::sync::mpsc::UnboundedSender; -use tonic::Status; - -use super::proto::{ - DeviceInfo, PasswordResetInitializeRequest, PasswordResetRequest, PasswordResetStartRequest, - PasswordResetStartResponse, -}; -use crate::{ - db::{ - models::enrollment::{Token, PASSWORD_RESET_TOKEN_TYPE}, - User, - }, - handlers::{ - mail::{send_password_reset_email, send_password_reset_success_email}, - user::check_password_strength, - }, - ldap::utils::ldap_change_password, - mail::Mail, - server_config, -}; - -pub(super) struct PasswordResetServer { - pool: PgPool, - mail_tx: UnboundedSender, - // ldap_feature_active: bool, -} - -impl PasswordResetServer { - #[must_use] - pub fn new(pool: PgPool, mail_tx: UnboundedSender) -> Self { - // FIXME: check if LDAP feature is enabled - // let ldap_feature_active = true; - Self { - pool, - mail_tx, - // ldap_feature_active, - } - } - - /// Checks if token provided with request corresponds to a valid password reset session - async fn validate_session(&self, token: &Option) -> Result { - info!("Validating password reset session. Token: {token:?}"); - let Some(token) = token else { - error!("Missing authorization header in request"); - return Err(Status::unauthenticated("Missing authorization header")); - }; - let enrollment = Token::find_by_id(&self.pool, token).await?; - debug!("Found matching token, verifying validity: {enrollment:?}."); - if !enrollment - .token_type - .as_ref() - .is_some_and(|token_type| token_type == PASSWORD_RESET_TOKEN_TYPE) - { - error!( - "Invalid token type used in password reset process: {:?}", - enrollment.token_type - ); - return Err(Status::permission_denied("invalid token")); - } - - if enrollment.is_session_valid(server_config().enrollment_session_timeout.as_secs()) { - info!("Password reset session validated: {enrollment:?}.",); - Ok(enrollment) - } else { - error!("Password reset session expired: {enrollment:?}"); - Err(Status::unauthenticated("Session expired")) - } - } - - pub async fn request_password_reset( - &self, - request: PasswordResetInitializeRequest, - req_device_info: Option, - ) -> Result<(), Status> { - let config = server_config(); - debug!("Starting password reset request"); - - let ip_address; - let user_agent; - if let Some(info) = req_device_info { - ip_address = info.ip_address.unwrap_or_default(); - user_agent = info.user_agent.unwrap_or_default(); - } else { - ip_address = String::new(); - user_agent = String::new(); - } - - let email = request.email; - - let user = User::find_by_email(&self.pool, email.to_string().as_str()) - .await - .map_err(|_| { - error!("Failed to fetch user by email: {email}"); - Status::internal("unexpected error") - })?; - - let Some(user) = user else { - // Do not return information whether user exists - debug!("Password reset skipped for non-existing user {email}"); - return Ok(()); - }; - - // Do not allow password change if user is disabled or not enrolled - if !user.has_password() || !user.is_active { - debug!( - "Password reset skipped for disabled or not enrolled user {} ({email})", - user.username - ); - return Ok(()); - } - - let mut transaction = self.pool.begin().await.map_err(|_| { - error!("Failed to begin transaction"); - Status::internal("unexpected error") - })?; - - Token::delete_unused_user_password_reset_tokens(&mut transaction, user.id).await?; - - let enrollment = Token::new( - user.id, - None, - Some(email.clone()), - config.password_reset_token_timeout.as_secs(), - Some(PASSWORD_RESET_TOKEN_TYPE.to_string()), - ); - enrollment.save(&mut transaction).await?; - - transaction.commit().await.map_err(|_| { - error!("Failed to commit transaction"); - Status::internal("unexpected error") - })?; - - send_password_reset_email( - &user, - &self.mail_tx, - config.enrollment_url.clone(), - &enrollment.id, - Some(&ip_address), - Some(&user_agent), - )?; - - info!( - "Finished processing password reset request for user {}.", - user.username - ); - - Ok(()) - } - - pub async fn start_password_reset( - &self, - request: PasswordResetStartRequest, - ) -> Result { - debug!("Starting password reset session: {request:?}"); - - let mut enrollment = Token::find_by_id(&self.pool, &request.token).await?; - - if enrollment.token_type != Some("PASSWORD_RESET".to_string()) { - error!( - "Invalid token type ({:?}) for password reset session", - enrollment.token_type - ); - return Err(Status::permission_denied("invalid token")); - } - - let user = enrollment.fetch_user(&self.pool).await?; - - if !user.has_password() || !user.is_active { - error!( - "Can't start password reset for a disabled or not enrolled user {}.", - user.username - ); - return Err(Status::permission_denied( - "user disabled or not yet enrolled", - )); - } - - let mut transaction = self.pool.begin().await.map_err(|_| { - error!("Failed to begin transaction"); - Status::internal("unexpected error") - })?; - - let session_deadline = enrollment - .start_session( - &mut transaction, - server_config().password_reset_session_timeout.as_secs(), - ) - .await?; - - let response = PasswordResetStartResponse { - deadline_timestamp: session_deadline.and_utc().timestamp(), - }; - - transaction.commit().await.map_err(|_| { - error!("Failed to commit transaction"); - Status::internal("unexpected error") - })?; - - info!( - "Finished processing password reset session for user {}.", - user.username - ); - - Ok(response) - } - - pub async fn reset_password( - &self, - request: PasswordResetRequest, - req_device_info: Option, - ) -> Result<(), Status> { - debug!("Starting password reset: {request:?}"); - let enrollment = self.validate_session(&request.token).await?; - - let ip_address; - let user_agent; - if let Some(info) = req_device_info { - ip_address = info.ip_address.unwrap_or_default(); - user_agent = info.user_agent.unwrap_or_default(); - } else { - ip_address = String::new(); - user_agent = String::new(); - } - - if let Err(err) = check_password_strength(&request.password) { - error!("Password not strong enough: {err}"); - return Err(Status::invalid_argument("password not strong enough")); - } - - let mut user = enrollment.fetch_user(&self.pool).await?; - - if !user.is_active { - error!( - "Can't reset password for a disabled user {}.", - user.username - ); - return Err(Status::permission_denied("user disabled")); - } - - let mut transaction = self.pool.begin().await.map_err(|_| { - error!("Failed to begin transaction"); - Status::internal("unexpected error") - })?; - - // update user - user.set_password(&request.password); - user.save(&mut *transaction).await.map_err(|err| { - error!("Failed to update user {}: {err}", user.username); - Status::internal("unexpected error") - })?; - - // if self.ldap_feature_active { - let _ = ldap_change_password(&self.pool, &user.username, &request.password).await; - // }; - - transaction.commit().await.map_err(|_| { - error!("Failed to commit transaction"); - Status::internal("unexpected error") - })?; - - send_password_reset_success_email( - &user, - &self.mail_tx, - Some(&ip_address), - Some(&user_agent), - )?; - - Ok(()) - } -} diff --git a/src/grpc/enrollment.rs b/src/grpc/proxy.rs similarity index 56% rename from src/grpc/enrollment.rs rename to src/grpc/proxy.rs index c308d7523..ae3f05244 100644 --- a/src/grpc/enrollment.rs +++ b/src/grpc/proxy.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use ipnetwork::IpNetwork; use sqlx::{PgPool, Transaction}; @@ -10,42 +10,52 @@ use super::{ proto::{ ActivateUserRequest, AdminInfo, Device as ProtoDevice, DeviceConfig as ProtoDeviceConfig, DeviceConfigResponse, EnrollmentStartRequest, EnrollmentStartResponse, ExistingDevice, - InitialUserInfo, NewDevice, + InitialUserInfo, NewDevice, PasswordResetInitializeRequest, PasswordResetRequest, + PasswordResetStartRequest, PasswordResetStartResponse, }, + utils::build_device_config_response, InstanceInfo, }; use crate::{ db::{ models::{ - device::{DeviceConfig, DeviceInfo}, - enrollment::{Token, TokenError, ENROLLMENT_TOKEN_TYPE}, + device::{Device, DeviceConfig, DeviceInfo}, + enrollment::{Token, TokenError, ENROLLMENT_TOKEN_TYPE, PASSWORD_RESET_TOKEN_TYPE}, polling_token::PollingToken, + settings::Settings, + user::User, + wireguard::ChangeEvent, }, - Device, GatewayEvent, Id, Settings, User, + Id, }, enterprise::db::models::enterprise_settings::EnterpriseSettings, - grpc::utils::build_device_config_response, - handlers::{mail::send_new_device_added_email, user::check_password_strength}, + handlers::{ + mail::{ + send_new_device_added_email, send_password_reset_email, + send_password_reset_success_email, + }, + user::check_password_strength, + }, headers::get_device_info, - ldap::utils::ldap_add_user, + ldap::utils::{ldap_add_user, ldap_change_password}, mail::Mail, server_config, templates::{self, TemplateLocation}, }; -pub(super) struct EnrollmentServer { +pub(super) struct ProxyHandler { pool: PgPool, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, user_agent_parser: Arc, ldap_feature_active: bool, } -impl EnrollmentServer { +impl ProxyHandler { #[must_use] pub fn new( pool: PgPool, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, user_agent_parser: Arc, ) -> Self { @@ -53,204 +63,207 @@ impl EnrollmentServer { let ldap_feature_active = true; Self { pool, - wireguard_tx, + events_tx, mail_tx, user_agent_parser, ldap_feature_active, } } - /// Checks if token provided with request corresponds to a valid enrollment session - async fn validate_session(&self, token: &Option) -> Result { - info!("Validating enrollment session. Token: {token:?}"); + /// Checks if token provided with request corresponds to a valid session. + async fn validate_session( + &self, + token: &Option, + desired_token_type: &str, + session_timeout: Duration, + ) -> Result { + debug!("Validating gRPC proxy session; token: {token:?}"); let Some(token) = token else { - error!("Missing authorization header in request"); - return Err(Status::unauthenticated("Missing authorization header")); + error!("Missing authorization token in request"); + return Err(Status::unauthenticated("Missing authorization token")); }; - let enrollment = Token::find_by_id(&self.pool, token).await?; - debug!("Found matching token, verifying validity: {enrollment:?}."); - if !enrollment + let token = Token::find_by_id(&self.pool, token).await?; + debug!("Found matching token, verifying validity: {token:?}."); + if !token .token_type .as_ref() - .is_some_and(|token_type| token_type == ENROLLMENT_TOKEN_TYPE) + .is_some_and(|token_type| token_type == desired_token_type) { - error!( - "Invalid token type used in enrollment process: {:?}", - enrollment.token_type - ); + error!("Invalid token type: {:?}", token.token_type); return Err(Status::permission_denied("invalid token")); } - if enrollment.is_session_valid(server_config().enrollment_session_timeout.as_secs()) { - info!("Enrollment session validated: {enrollment:?}"); - Ok(enrollment) + if token.is_session_valid(session_timeout) { + info!("Proxy session validated: {token:?}"); + Ok(token) } else { - error!("Enrollment session expired: {enrollment:?}"); + error!("Proxy session expired: {token:?}"); Err(Status::unauthenticated("Session expired")) } } - /// Sends given `GatewayEvent` to be handled by gateway GRPC server - pub fn send_wireguard_event(&self, event: GatewayEvent) { - if let Err(err) = self.wireguard_tx.send(event) { + /// Sends given `ChangeEvent` to be handled by gateway over gRPC. + pub(crate) fn send_wireguard_event(&self, event: ChangeEvent) { + if let Err(err) = self.events_tx.send(event) { error!("Error sending WireGuard event {err}"); } } - pub async fn start_enrollment( + pub(crate) async fn start_enrollment( &self, request: EnrollmentStartRequest, ) -> Result { debug!("Starting enrollment session, request: {request:?}"); // fetch enrollment token debug!("Try to find an enrollment token {}.", request.token); - let mut enrollment = Token::find_by_id(&self.pool, &request.token).await?; + let mut token = Token::find_by_id(&self.pool, &request.token).await?; - if let Some(token_type) = &enrollment.token_type { - if token_type != ENROLLMENT_TOKEN_TYPE { - error!("Invalid token type used while trying to start enrollment: {token_type}"); - return Err(Status::permission_denied("invalid token")); - } + let Some(token_type) = &token.token_type else { + debug!("Invalid enrollment token, the token does not have specified type."); + return Err(Status::permission_denied("invalid token")); + }; - // fetch related users - let user = enrollment.fetch_user(&self.pool).await?; - let admin = enrollment.fetch_admin(&self.pool).await?; + if token_type != ENROLLMENT_TOKEN_TYPE { + error!("Invalid token type used while trying to start enrollment: {token_type}"); + return Err(Status::permission_denied("invalid token")); + } - debug!( - "Checking if user {}({:?}) is active", - user.username, user.id - ); - if !user.is_active { - warn!( - "Can't start enrollment for disabled user {}.", - user.username - ); - return Err(Status::permission_denied("user is disabled")); - }; - info!( - "User {}({:?}) is active, proceeding with enrollment", - user.username, user.id + // fetch related users + let user = token.fetch_user(&self.pool).await?; + let admin = token.fetch_admin(&self.pool).await?; + + debug!("Checking if user {}({}) is active", user.username, user.id); + if !user.is_active { + warn!( + "Can't start enrollment for disabled user {}.", + user.username ); + return Err(Status::permission_denied("user is disabled")); + }; + info!( + "User {}({}) is active, proceeding with enrollment", + user.username, user.id + ); - let mut transaction = self.pool.begin().await.map_err(|err| { - error!("Failed to begin a transaction for enrollment: {err}"); + let mut transaction = self.pool.begin().await.map_err(|err| { + error!("Failed to begin a transaction for enrollment: {err}"); + Status::internal("unexpected error") + })?; + + // validate token & start session + debug!( + "Validating enrollment token and starting session for user {}({})", + user.username, user.id, + ); + let session_deadline = token + .start_session( + &mut transaction, + server_config().enrollment_session_timeout.into(), + ) + .await?; + info!( + "Enrollment session started for user {}({})", + user.username, user.id + ); + + debug!( + "Retrieving settings for enrollment of user {}({}).", + user.username, user.id + ); + let settings = Settings::get_settings(&mut *transaction) + .await + .map_err(|err| { + error!("Failed to get settings: {err}"); Status::internal("unexpected error") })?; + debug!("Settings: {settings:?}"); - // validate token & start session - debug!( - "Validating enrollment token and starting session for user {}({:?})", - user.username, user.id, - ); - let session_deadline = enrollment - .start_session( - &mut transaction, - server_config().enrollment_session_timeout.as_secs(), - ) - .await?; - info!( - "Enrollment session started for user {}({:?})", - user.username, user.id - ); - - debug!( - "Retrieving settings for enrollment of user {}({:?}).", - user.username, user.id - ); - let settings = Settings::get_settings(&mut *transaction) + debug!( + "Retrieving enterprise settings for enrollment of user {}({}).", + user.username, user.id + ); + let enterprise_settings = + EnterpriseSettings::get(&mut *transaction) .await .map_err(|err| { - error!("Failed to get settings: {err}"); + error!("Failed to get enterprise settings: {err}"); Status::internal("unexpected error") })?; - debug!("Settings: {settings:?}"); + debug!("Enterprise settings: {enterprise_settings:?}"); - debug!( - "Retrieving enterprise settings for enrollment of user {}({:?}).", - user.username, user.id - ); - let enterprise_settings = - EnterpriseSettings::get(&mut *transaction) - .await - .map_err(|err| { - error!("Failed to get enterprise settings: {err}"); - Status::internal("unexpected error") - })?; - debug!("Enterprise settings: {enterprise_settings:?}"); - - let vpn_setup_optional = settings.enrollment_vpn_step_optional; - debug!( - "Retrieving instance info for user {}({:?}).", - user.username, user.id - ); - let instance_info = InstanceInfo::new(settings, &user.username, &enterprise_settings); - debug!("Instance info {instance_info:?}"); + let vpn_setup_optional = settings.enrollment_vpn_step_optional; + debug!( + "Retrieving instance info for user {}({}).", + user.username, user.id + ); + let instance_info = InstanceInfo::new(settings, &user.username, &enterprise_settings); + debug!("Instance info {instance_info:?}"); - debug!( - "Preparing initial user info to send for user enrollment, user {}({:?}).", - user.username, user.id - ); - let (username, user_id) = (user.username.clone(), user.id); - let user_info = InitialUserInfo::from_user(&self.pool, user) + debug!( + "Preparing initial user info to send for user enrollment, user {}({}).", + user.username, user.id + ); + let (username, user_id) = (user.username.clone(), user.id); + let user_info = InitialUserInfo::from_user(&self.pool, user) + .await + .map_err(|err| { + error!( + "Failed to get user info for user {}({}): {err}", + username, user_id, + ); + Status::internal("unexpected error") + })?; + debug!("User info {user_info:?}"); + + debug!("Trying to get basic admin info..."); + let admin_info = admin.map(AdminInfo::from); + debug!("Admin info {admin_info:?}"); + + debug!( + "Creating enrollment start response for user {}({}).", + username, user_id, + ); + let enterprise_settings = + EnterpriseSettings::get(&mut *transaction) .await .map_err(|err| { - error!( - "Failed to get user info for user {}({:?}): {err}", - username, user_id, - ); + error!("Failed to get enterprise settings: {err}"); Status::internal("unexpected error") })?; - debug!("User info {user_info:?}"); - - debug!("Trying to get basic admin info..."); - let admin_info = admin.map(AdminInfo::from); - debug!("Admin info {admin_info:?}"); + let enrollment_settings = super::proto::Settings { + vpn_setup_optional, + only_client_activation: enterprise_settings.only_client_activation, + }; + let response = super::proto::EnrollmentStartResponse { + admin: admin_info, + user: Some(user_info), + deadline_timestamp: session_deadline.and_utc().timestamp(), + final_page_content: token.get_welcome_page_content(&mut transaction).await?, + instance: Some(instance_info.into()), + settings: Some(enrollment_settings), + }; + debug!("Response {response:?}"); - debug!( - "Creating enrollment start response for user {}({:?}).", - username, user_id, - ); - let enterprise_settings = - EnterpriseSettings::get(&mut *transaction) - .await - .map_err(|err| { - error!("Failed to get enterprise settings: {err}"); - Status::internal("unexpected error") - })?; - let enrollment_settings = super::proto::Settings { - vpn_setup_optional, - only_client_activation: enterprise_settings.only_client_activation, - }; - let response = super::proto::EnrollmentStartResponse { - admin: admin_info, - user: Some(user_info), - deadline_timestamp: session_deadline.and_utc().timestamp(), - final_page_content: enrollment - .get_welcome_page_content(&mut transaction) - .await?, - instance: Some(instance_info.into()), - settings: Some(enrollment_settings), - }; - debug!("Response {response:?}"); - - transaction.commit().await.map_err(|err| { - error!("Failed to commit transaction: {err}"); - Status::internal("unexpected error") - })?; + transaction.commit().await.map_err(|err| { + error!("Failed to commit transaction: {err}"); + Status::internal("unexpected error") + })?; - Ok(response) - } else { - debug!("Invalid enrollment token, the token does not have specified type."); - Err(Status::permission_denied("invalid token")) - } + Ok(response) } - pub async fn activate_user( + pub(crate) async fn activate_user( &self, request: ActivateUserRequest, req_device_info: Option, ) -> Result<(), Status> { debug!("Activating user account: {request:?}"); - let enrollment = self.validate_session(&request.token).await?; + let enrollment = self + .validate_session( + &request.token, + ENROLLMENT_TOKEN_TYPE, + server_config().enrollment_session_timeout.into(), + ) + .await?; let ip_address; let device_info; @@ -262,7 +275,7 @@ impl EnrollmentServer { ip_address = String::new(); device_info = None; } - debug!("Ip address {}, device info {device_info:?}", ip_address); + debug!("IP address {}, device info {device_info:?}", ip_address); // check if password is strong enough debug!("Verifying password strength for user activation process."); @@ -364,25 +377,28 @@ impl EnrollmentServer { Ok(()) } - pub async fn create_device( + pub(crate) async fn create_device( &self, request: NewDevice, req_device_info: Option, ) -> Result { debug!("Adding new user device: {request:?}"); - let enrollment = self.validate_session(&request.token).await?; + let enrollment = self + .validate_session( + &request.token, + ENROLLMENT_TOKEN_TYPE, + server_config().enrollment_session_timeout.into(), + ) + .await?; // fetch related users let user = enrollment.fetch_user(&self.pool).await?; // add device - debug!( - "Verifying if user {}({:?}) is active", - user.username, user.id - ); + debug!("Verifying if user {}({}) is active", user.username, user.id); if !user.is_active { error!( - "Can't create device for disabled user {}({:?})", + "Can't create device for disabled user {}({})", user.username, user.id ); return Err(Status::invalid_argument( @@ -390,7 +406,7 @@ impl EnrollmentServer { )); } info!( - "User {}({:?}) is active, proceeding with device creation, pubkey: {}", + "User {}({}) is active, proceeding with device creation, pubkey: {}", user.username, user.id, request.pubkey ); @@ -404,27 +420,27 @@ impl EnrollmentServer { ip_address = String::new(); device_info = None; } - debug!("Ip address {}, device info {device_info:?}", ip_address); + debug!("IP address {}, device info {device_info:?}", ip_address); debug!( - "Validating pubkey {} for device creation process for user {}({:?})", + "Validating pubkey {} for device creation process for user {}({})", request.pubkey, user.username, user.id, ); Device::validate_pubkey(&request.pubkey).map_err(|err| { error!( - "Invalid pubkey {}, device won't be created for user {}({:?}): {err}", + "Invalid pubkey {}, device won't be created for user {}({}): {err}", request.pubkey, user.username, user.id ); Status::invalid_argument("invalid pubkey") })?; info!( - "Pubkey {} is valid for device creation process for user {}({:?})", + "Pubkey {} is valid for device creation process for user {}({})", request.pubkey, user.username, user.id ); // Make sure there is no device with the same pubkey, such state may lead to unexpected issues debug!( - "Checking pubkey {} uniqueness for device creation process for user {}({:?}).", + "Checking pubkey {} uniqueness for device creation process for user {}({}).", request.pubkey, user.username, user.id, ); if let Some(device) = Device::find_by_pubkey(&self.pool, &request.pubkey) @@ -438,7 +454,7 @@ impl EnrollmentServer { })? { warn!( - "User {}({:?}) failed to add device {}, identical pubkey ({}) already exists for device {}", + "User {}({}) failed to add device {}, identical pubkey ({}) already exists for device {}", user.username, user.id, request.name, @@ -448,7 +464,7 @@ impl EnrollmentServer { return Err(Status::invalid_argument("invalid key")); }; info!( - "Pubkey {} is unique for device creation process for user {}({:?}).", + "Pubkey {} is unique for device creation process for user {}({}).", request.pubkey, user.username, user.id ); @@ -458,7 +474,7 @@ impl EnrollmentServer { enrollment.user_id, ); debug!( - "Creating new device for user {}({:?}) {device:?}.", + "Creating new device for user {}({}) {device:?}.", user.username, user.id, ); @@ -468,7 +484,7 @@ impl EnrollmentServer { })?; let device = device.save(&mut *transaction).await.map_err(|err| { error!( - "Failed to save device {}, pubkey {} for user {}({:?}): {err}", + "Failed to save device {}, pubkey {} for user {}({}): {err}", request.name, request.pubkey, user.username, user.id, ); Status::internal("unexpected error") @@ -476,7 +492,7 @@ impl EnrollmentServer { info!("New device created: {device:?}."); debug!( - "Adding device {} to all existing user networks for user {}({:?}).", + "Adding device {} to all existing user networks for user {}({}).", device.wireguard_pubkey, user.username, user.id, ); let (network_info, configs) = @@ -492,31 +508,31 @@ impl EnrollmentServer { })?; info!( - "Added device {} to all existing user networks for user {}({:?})", + "Added device {} to all existing user networks for user {}({})", device.wireguard_pubkey, user.username, user.id ); debug!( - "Sending DeviceCreated event to gateway for device {}, user {}({:?})", + "Sending DeviceCreated event to gateway for device {}, user {}({})", device.wireguard_pubkey, user.username, user.id, ); - self.send_wireguard_event(GatewayEvent::DeviceCreated(DeviceInfo { + self.send_wireguard_event(ChangeEvent::DeviceCreated(DeviceInfo { device: device.clone(), network_info, })); info!( - "Sent DeviceCreated event to gateway for device {}, user {}({:?})", + "Sent DeviceCreated event to gateway for device {}, user {}({})", device.wireguard_pubkey, user.username, user.id, ); debug!( - "Fetching settings for device {} creation process for user {}({:?})", + "Fetching settings for device {} creation process for user {}({})", device.wireguard_pubkey, user.username, user.id, ); let settings = Settings::get_settings(&mut *transaction) .await .map_err(|err| { error!( - "Failed to fetch settings for device {} creation process for user {}({:?}): {err}", + "Failed to fetch settings for device {} creation process for user {}({}): {err}", device.wireguard_pubkey, user.username, user.id, ); Status::internal("unexpected error") @@ -524,14 +540,14 @@ impl EnrollmentServer { debug!("Settings: {settings:?}"); debug!( - "Fetching enterprise settings for device {} creation process for user {}({:?})", + "Fetching enterprise settings for device {} creation process for user {}({})", device.wireguard_pubkey, user.username, user.id, ); let enterprise_settings = EnterpriseSettings::get(&mut *transaction) .await .map_err(|err| { error!( - "Failed to fetch enterprise settings for device {} creation process for user {}({:?}): {err}", + "Failed to fetch enterprise settings for device {} creation process for user {}({}): {err}", device.wireguard_pubkey, user.username, user.id, ); Status::internal("unexpected error") @@ -540,7 +556,7 @@ impl EnrollmentServer { // create polling token for further client communication debug!( - "Creating polling token for further client communication for device {}, user {}({:?})", + "Creating polling token for further client communication for device {}, user {}({})", device.wireguard_pubkey, user.username, user.id, ); let token = PollingToken::new(device.id) @@ -548,19 +564,19 @@ impl EnrollmentServer { .await .map_err(|err| { error!( - "Failed to save PollingToken for device {}, user {}({:?}): {err}", + "Failed to save PollingToken for device {}, user {}({}): {err}", device.wireguard_pubkey, user.username, user.id ); Status::internal("failed to save polling token") })?; info!( - "Created polling token for further client communication for device: {}, user {}({:?})", + "Created polling token for further client communication for device: {}, user {}({})", device.wireguard_pubkey, user.username, user.id, ); transaction.commit().await.map_err(|err| { error!( - "Failed to commit transaction, device {} won't be created for user {}({:?}): {err}", + "Failed to commit transaction, device {} won't be created for user {}({}): {err}", device.wireguard_pubkey, user.username, user.id, ); Status::internal("unexpected error") @@ -575,7 +591,7 @@ impl EnrollmentServer { .collect(); debug!( - "Sending device created mail for device {}, user {}({:?})", + "Sending device created mail for device {}, user {}({})", device.wireguard_pubkey, user.username, user.id ); send_new_device_added_email( @@ -590,7 +606,7 @@ impl EnrollmentServer { .map_err(|_| Status::internal("error rendering email template"))?; info!( - "Device {} assigned to user {}({:?}) and added to all networks.", + "Device {} assigned to user {}({}) and added to all networks.", device.name, user.username, user.id, ); @@ -608,15 +624,232 @@ impl EnrollmentServer { } /// Get all information needed to update instance information for desktop client - pub async fn get_network_info( + pub(crate) async fn get_network_info( &self, request: ExistingDevice, ) -> Result { debug!("Getting network info for device: {:?}", request.pubkey); - let _token = self.validate_session(&request.token).await?; + let _token = self + .validate_session( + &request.token, + PASSWORD_RESET_TOKEN_TYPE, + server_config().password_reset_session_timeout.into(), + ) + .await?; build_device_config_response(&self.pool, &request.pubkey, true).await } + + pub(crate) async fn request_password_reset( + &self, + request: PasswordResetInitializeRequest, + req_device_info: Option, + ) -> Result<(), Status> { + let config = server_config(); + debug!("Starting password reset request"); + + let ip_address; + let user_agent; + if let Some(info) = req_device_info { + ip_address = info.ip_address.unwrap_or_default(); + user_agent = info.user_agent.unwrap_or_default(); + } else { + ip_address = String::new(); + user_agent = String::new(); + } + + let email = request.email; + + let user = User::find_by_email(&self.pool, email.to_string().as_str()) + .await + .map_err(|_| { + error!("Failed to fetch user by email: {email}"); + Status::internal("unexpected error") + })?; + + let Some(user) = user else { + // Do not return information whether user exists + debug!("Password reset skipped for non-existing user {email}"); + return Ok(()); + }; + + // Do not allow password change if user is disabled or not enrolled + if !user.has_password() || !user.is_active { + debug!( + "Password reset skipped for disabled or not enrolled user {} ({email})", + user.username + ); + return Ok(()); + } + + let mut transaction = self.pool.begin().await.map_err(|_| { + error!("Failed to begin transaction"); + Status::internal("unexpected error") + })?; + + Token::delete_unused_user_password_reset_tokens(&mut transaction, user.id).await?; + + let enrollment = Token::new( + user.id, + None, + Some(email.clone()), + config.password_reset_token_timeout.as_secs(), + Some(PASSWORD_RESET_TOKEN_TYPE.to_string()), + ); + enrollment.save(&mut transaction).await?; + + transaction.commit().await.map_err(|_| { + error!("Failed to commit transaction"); + Status::internal("unexpected error") + })?; + + send_password_reset_email( + &user, + &self.mail_tx, + config.enrollment_url.clone(), + &enrollment.id, + Some(&ip_address), + Some(&user_agent), + )?; + + info!( + "Finished processing password reset request for user {}.", + user.username + ); + + Ok(()) + } + + pub(crate) async fn start_password_reset( + &self, + request: PasswordResetStartRequest, + ) -> Result { + debug!("Starting password reset session: {request:?}"); + + let mut token = Token::find_by_id(&self.pool, &request.token).await?; + + if !token + .token_type + .as_ref() + .is_some_and(|token_type| token_type == PASSWORD_RESET_TOKEN_TYPE) + { + error!( + "Invalid token type ({:?}) for password reset session", + token.token_type + ); + return Err(Status::permission_denied("invalid token")); + } + + let user = token.fetch_user(&self.pool).await?; + + if !user.has_password() || !user.is_active { + error!( + "Can't start password reset for a disabled or not enrolled user {}.", + user.username + ); + return Err(Status::permission_denied( + "user disabled or not yet enrolled", + )); + } + + let mut transaction = self.pool.begin().await.map_err(|_| { + error!("Failed to begin transaction"); + Status::internal("unexpected error") + })?; + + let session_deadline = token + .start_session( + &mut transaction, + server_config().password_reset_session_timeout.into(), + ) + .await?; + + let response = PasswordResetStartResponse { + deadline_timestamp: session_deadline.and_utc().timestamp(), + }; + + transaction.commit().await.map_err(|_| { + error!("Failed to commit transaction"); + Status::internal("unexpected error") + })?; + + info!( + "Finished processing password reset session for user {}.", + user.username + ); + + Ok(response) + } + + pub(crate) async fn reset_password( + &self, + request: PasswordResetRequest, + req_device_info: Option, + ) -> Result<(), Status> { + debug!("Starting password reset: {request:?}"); + let enrollment = self + .validate_session( + &request.token, + PASSWORD_RESET_TOKEN_TYPE, + server_config().password_reset_session_timeout.into(), + ) + .await?; + + let ip_address; + let user_agent; + if let Some(info) = req_device_info { + ip_address = info.ip_address.unwrap_or_default(); + user_agent = info.user_agent.unwrap_or_default(); + } else { + ip_address = String::new(); + user_agent = String::new(); + } + + if let Err(err) = check_password_strength(&request.password) { + error!("Password not strong enough: {err}"); + return Err(Status::invalid_argument("password not strong enough")); + } + + let mut user = enrollment.fetch_user(&self.pool).await?; + + if !user.is_active { + error!( + "Can't reset password for a disabled user {}.", + user.username + ); + return Err(Status::permission_denied("user disabled")); + } + + let mut transaction = self.pool.begin().await.map_err(|_| { + error!("Failed to begin transaction"); + Status::internal("unexpected error") + })?; + + // update user + user.set_password(&request.password); + user.save(&mut *transaction).await.map_err(|err| { + error!("Failed to update user {}: {err}", user.username); + Status::internal("unexpected error") + })?; + + // if self.ldap_feature_active { + let _ = ldap_change_password(&self.pool, &user.username, &request.password).await; + // }; + + transaction.commit().await.map_err(|_| { + error!("Failed to commit transaction"); + Status::internal("unexpected error") + })?; + + send_password_reset_success_email( + &user, + &self.mail_tx, + Some(&ip_address), + Some(&user_agent), + )?; + + Ok(()) + } } impl From> for AdminInfo { diff --git a/src/grpc/utils.rs b/src/grpc/utils.rs index 8078075cf..daf686138 100644 --- a/src/grpc/utils.rs +++ b/src/grpc/utils.rs @@ -7,12 +7,12 @@ use super::{ InstanceInfo, }; use crate::{ - db::{ - models::{ - device::WireguardNetworkDevice, polling_token::PollingToken, - wireguard::WireguardNetwork, - }, - Device, Settings, User, + db::models::{ + device::{Device, WireguardNetworkDevice}, + polling_token::PollingToken, + settings::Settings, + user::User, + wireguard::WireguardNetwork, }, enterprise::db::models::enterprise_settings::EnterpriseSettings, }; diff --git a/src/grpc/worker.rs b/src/grpc/worker.rs index a81636278..d8c48c036 100644 --- a/src/grpc/worker.rs +++ b/src/grpc/worker.rs @@ -11,9 +11,11 @@ use tokio::sync::mpsc::UnboundedSender; use tonic::{Request, Response, Status}; use super::{Job, JobResponse, WorkerDetail, WorkerInfo, WorkerState}; -use crate::db::{ - models::authentication_key::{AuthenticationKey, AuthenticationKeyType}, - AppEvent, HWKeyUserData, User, YubiKey, +use crate::db::models::{ + authentication_key::{AuthenticationKey, AuthenticationKeyType}, + user::User, + webhook::{AppEvent, HWKeyUserData}, + yubikey::YubiKey, }; tonic::include_proto!("worker"); @@ -42,7 +44,7 @@ impl WorkerInfo { /// Return first availale Job. #[must_use] - pub fn get_job(&self) -> Option<&Job> { + pub(crate) fn get_job(&self) -> Option<&Job> { self.jobs.first() } @@ -52,12 +54,12 @@ impl WorkerInfo { } /// Add Job. - pub fn add_job(&mut self, job: Job) { + pub(crate) fn add_job(&mut self, job: Job) { self.jobs.push(job); } /// Remove Job with given id. - pub fn remove_job_with_id(&mut self, job_id: u32) -> Option { + pub(crate) fn remove_job_with_id(&mut self, job_id: u32) -> Option { if let Some(index) = self.jobs.iter().position(|job| job.id == job_id) { Some(self.jobs.remove(index)) } else { @@ -121,7 +123,7 @@ impl WorkerState { } /// Remove a job for a given worker. - pub fn remove_job(&mut self, id: &str, job_id: u32) -> Option { + pub(crate) fn remove_job(&mut self, id: &str, job_id: u32) -> Option { if let Some(worker) = self.workers.get_mut(id) { worker.refresh_status(); worker.remove_job_with_id(job_id) @@ -131,7 +133,7 @@ impl WorkerState { } /// Return the first available job. - pub fn get_job(&mut self, id: &str, ip: IpAddr) -> Option<&Job> { + pub(crate) fn get_job(&mut self, id: &str, ip: IpAddr) -> Option<&Job> { if let Some(worker) = self.workers.get_mut(id) { worker.refresh_status(); worker.set_ip(ip); diff --git a/src/handlers/app_info.rs b/src/handlers/app_info.rs index a8bc4294c..1b2c32f92 100644 --- a/src/handlers/app_info.rs +++ b/src/handlers/app_info.rs @@ -1,12 +1,13 @@ use axum::{extract::State, http::StatusCode}; use serde_json::json; -use super::{ApiResponse, ApiResult, VERSION}; +use super::{ApiResponse, VERSION}; use crate::{ appstate::AppState, auth::SessionInfo, - db::{Settings, WireguardNetwork}, + db::models::{settings::Settings, wireguard::WireguardNetwork}, enterprise::license::{get_cached_license, validate_license}, + error::WebError, }; /// Additional information about core state. @@ -22,7 +23,7 @@ pub struct AppInfo { pub(crate) async fn get_app_info( State(appstate): State, _session: SessionInfo, -) -> ApiResult { +) -> Result { let networks = WireguardNetwork::all(&appstate.pool).await?; let settings = Settings::get_settings(&appstate.pool).await?; let license = get_cached_license(); diff --git a/src/handlers/auth.rs b/src/handlers/auth.rs index 953ed2f34..e70d584fa 100644 --- a/src/handlers/auth.rs +++ b/src/handlers/auth.rs @@ -18,7 +18,7 @@ use webauthn_rs::prelude::PublicKeyCredential; use webauthn_rs_proto::options::CollectedClientData; use super::{ - ApiResponse, ApiResult, Auth, AuthCode, AuthResponse, AuthTotp, RecoveryCode, RecoveryCodes, + ApiResponse, Auth, AuthCode, AuthResponse, AuthTotp, RecoveryCode, RecoveryCodes, WalletAddress, WalletSignature, WebAuthnRegistration, SESSION_COOKIE_NAME, }; use crate::{ @@ -27,7 +27,14 @@ use crate::{ failed_login::{check_username, log_failed_login_attempt}, SessionInfo, }, - db::{MFAInfo, MFAMethod, Session, SessionState, Settings, User, UserInfo, Wallet, WebAuthn}, + db::models::{ + session::{Session, SessionState}, + settings::Settings, + user::{MFAMethod, User}, + wallet::Wallet, + webauthn::WebAuthn, + MFAInfo, UserInfo, + }, error::WebError, handlers::{ mail::{ @@ -43,7 +50,7 @@ use crate::{ /// For successful login, return: /// * 200 with MFA disabled /// * 201 with MFA enabled when additional authentication factor is required -pub async fn authenticate( +pub(crate) async fn authenticate( cookies: CookieJar, private_cookies: PrivateCookieJar, user_agent: Option>, @@ -93,14 +100,13 @@ pub async fn authenticate( Ok(None) => { // create user from LDAP debug!("User not found in DB, authenticating user {username} with LDAP"); - if let Ok(user) = - user_from_ldap(&appstate.pool, &username, &data.password).await - { - user - } else { - info!("Failed to authenticate user {username} with LDAP"); - log_failed_login_attempt(&appstate.failed_logins, &username); - return Err(WebError::Authorization("user not found".into())); + match user_from_ldap(&appstate.pool, &username, &data.password).await { + Ok(user) => user, + Err(err) => { + warn!("Failed to authenticate user {username} with LDAP: {err}"); + log_failed_login_attempt(&appstate.failed_logins, &username); + return Err(WebError::Authorization("user not found".into())); + } } } Err(err) => { @@ -264,7 +270,10 @@ pub async fn mfa_enable( } /// Disable MFA -pub async fn mfa_disable(session_info: SessionInfo, State(appstate): State) -> ApiResult { +pub async fn mfa_disable( + session_info: SessionInfo, + State(appstate): State, +) -> Result { let mut user = session_info.user; debug!("Disabling MFA for user {}", user.username); user.disable_mfa(&appstate.pool).await?; @@ -276,7 +285,7 @@ pub async fn mfa_disable(session_info: SessionInfo, State(appstate): State, -) -> ApiResult { +) -> Result { let user = session_info.user; info!( "Initializing WebAuthn registration for user {}", @@ -313,7 +322,7 @@ pub async fn webauthn_finish( session: SessionInfo, State(appstate): State, Json(webauth_reg): Json, -) -> ApiResult { +) -> Result { info!( "Finishing WebAuthn registration for user {}", session.user.username @@ -376,7 +385,10 @@ pub async fn webauthn_finish( } /// Start WebAuthn authentication -pub async fn webauthn_start(mut session: Session, State(appstate): State) -> ApiResult { +pub async fn webauthn_start( + mut session: Session, + State(appstate): State, +) -> Result { let passkeys = WebAuthn::passkeys_for_user(&appstate.pool, session.user_id).await?; match appstate.webauthn.start_passkey_authentication(&passkeys) { @@ -453,7 +465,10 @@ pub async fn webauthn_end( } /// Generate new TOTP secret -pub async fn totp_secret(session: SessionInfo, State(appstate): State) -> ApiResult { +pub async fn totp_secret( + session: SessionInfo, + State(appstate): State, +) -> Result { let mut user = session.user; debug!("Generating new TOTP secret for user {}", user.username); @@ -470,7 +485,7 @@ pub async fn totp_enable( session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { let mut user = session.user; debug!("Enabling TOTP for user {}", user.username); if user.verify_totp_code(&data.code) { @@ -498,7 +513,10 @@ pub async fn totp_enable( } /// Disable TOTP -pub async fn totp_disable(session: SessionInfo, State(appstate): State) -> ApiResult { +pub async fn totp_disable( + session: SessionInfo, + State(appstate): State, +) -> Result { let mut user = session.user; debug!("Disabling TOTP for user {}", user.username); user.disable_totp(&appstate.pool).await?; @@ -558,7 +576,10 @@ pub async fn totp_code( } /// Initialize email MFA setup -pub async fn email_mfa_init(session: SessionInfo, State(appstate): State) -> ApiResult { +pub async fn email_mfa_init( + session: SessionInfo, + State(appstate): State, +) -> Result { // check if SMTP is configured let settings = Settings::get_settings(&appstate.pool).await?; if !settings.smtp_configured() { @@ -583,7 +604,7 @@ pub async fn email_mfa_enable( session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { let mut user = session.user; debug!("Enabling email MFA for user {}", user.username); if user.verify_email_mfa_code(&data.code) { @@ -614,7 +635,7 @@ pub async fn email_mfa_enable( pub async fn email_mfa_disable( session: SessionInfo, State(appstate): State, -) -> ApiResult { +) -> Result { let mut user = session.user; debug!("Disabling email MFA for user {}", user.username); user.disable_email_mfa(&appstate.pool).await?; @@ -627,7 +648,7 @@ pub async fn email_mfa_disable( pub async fn request_email_mfa_code( session: Session, State(appstate): State, -) -> ApiResult { +) -> Result { if let Some(user) = User::find_by_id(&appstate.pool, session.user_id).await? { debug!("Sending email MFA code for user {}", user.username); if user.email_mfa_enabled { @@ -697,7 +718,7 @@ pub async fn web3auth_start( mut session: Session, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("Starting web3 authentication for wallet {}", data.address); match Settings::get(&appstate.pool).await? { Some(settings) => { diff --git a/src/handlers/forward_auth.rs b/src/handlers/forward_auth.rs index 90352885b..d7208dbce 100644 --- a/src/handlers/forward_auth.rs +++ b/src/handlers/forward_auth.rs @@ -8,7 +8,7 @@ use axum_extra::extract::cookie::CookieJar; use reqwest::Url; use super::SESSION_COOKIE_NAME; -use crate::{appstate::AppState, db::Session, error::WebError, server_config}; +use crate::{appstate::AppState, db::models::session::Session, error::WebError, server_config}; // Header names static FORWARDED_HOST: &str = "x-forwarded-host"; diff --git a/src/handlers/gateway.rs b/src/handlers/gateway.rs new file mode 100644 index 000000000..b2a6a5987 --- /dev/null +++ b/src/handlers/gateway.rs @@ -0,0 +1,165 @@ +use axum::{ + extract::{Json, Path, State}, + http::StatusCode, +}; +use serde_json::json; + +use super::{ApiResponse, WebError}; +use crate::{ + appstate::AppState, + auth::{SessionInfo, VpnRole}, + db::{ + models::{gateway::Gateway, wireguard::WireguardNetwork}, + Id, + }, +}; + +#[derive(Deserialize, Serialize)] +pub(crate) struct GatewayData { + url: String, +} + +pub(crate) async fn add_gateway( + _role: VpnRole, + State(appstate): State, + session: SessionInfo, + Path(network_id): Path, + Json(data): Json, +) -> Result { + let network = WireguardNetwork::find_by_id(&appstate.pool, network_id) + .await? + .ok_or_else(|| { + WebError::ObjectNotFound(format!( + "Network ID {network_id} not found while adding a gateway, aborting" + )) + })?; + + debug!( + "User {} is adding a gateway with URL {} to network {}", + session.user.username, data.url, network.name + ); + + let gateway = Gateway::new(network_id, &data.url) + .save(&appstate.pool) + .await?; + info!( + "User {} has added {gateway} to network {}", + session.user.username, network.name + ); + + Ok(ApiResponse::new(json!({}), StatusCode::CREATED)) +} + +pub(crate) async fn delete_gateway( + _role: VpnRole, + State(appstate): State, + session: SessionInfo, + Path(gateway_id): Path, +) -> Result { + debug!( + "User {} is removing gateway ID {gateway_id}", + session.user.username + ); + let gateway = Gateway::find_by_id(&appstate.pool, gateway_id) + .await? + .ok_or_else(|| { + WebError::ObjectNotFound(format!( + "Gateway ID {gateway_id} not found while removing gateway, aborting" + )) + })?; + debug!("User {} is removing {gateway}", session.user.username); + + let msg = format!("User {} has deleted {gateway}", session.user.username); + gateway.delete(&appstate.pool).await?; + info!("{msg}"); + + Ok(ApiResponse { + json: json!({}), + status: StatusCode::OK, + }) +} + +#[derive(Deserialize, Serialize)] +struct GetGatewaysData { + network_id: Id, +} + +pub(crate) async fn get_gateways( + _role: VpnRole, + State(appstate): State, + session: SessionInfo, + Path(network_id): Path, +) -> Result { + let network = WireguardNetwork::find_by_id(&appstate.pool, network_id) + .await? + .ok_or_else(|| { + WebError::ObjectNotFound(format!( + "Network ID {network_id} not found while getting gateways, aborting" + )) + })?; + + debug!( + "User {} is getting gateways for network {}", + session.user.username, network.name + ); + + let gateways = Gateway::find_by_network_id(&appstate.pool, network_id).await?; + Ok(ApiResponse::new( + json!({ "gateways": gateways }), + StatusCode::OK, + )) +} + +#[derive(Deserialize, Serialize)] +struct GetGatewayData { + gateway_id: Id, +} + +pub(crate) async fn get_gateway( + _role: VpnRole, + State(appstate): State, + session: SessionInfo, + Path(gateway_id): Path, +) -> Result { + debug!( + "User {} is getting gateway ID {gateway_id}", + session.user.username + ); + let gateway = Gateway::find_by_id(&appstate.pool, gateway_id) + .await? + .ok_or_else(|| { + WebError::ObjectNotFound(format!("Gateway ID {gateway_id} not found, aborting")) + })?; + + Ok(ApiResponse::new( + json!({ "gateway": gateway }), + StatusCode::OK, + )) +} + +pub(crate) async fn update_gateway( + _role: VpnRole, + State(appstate): State, + session: SessionInfo, + Path(gateway_id): Path, + Json(data): Json, +) -> Result { + debug!( + "User {} is updating gateway ID {gateway_id}", + session.user.username + ); + let mut gateway = Gateway::find_by_id(&appstate.pool, gateway_id) + .await? + .ok_or_else(|| { + WebError::ObjectNotFound(format!( + "Gateway ID {gateway_id} not found while updating gateway, aborting" + )) + })?; + + debug!("User {} is updating {gateway}", session.user.username); + gateway.url = data.url; + gateway.save(&appstate.pool).await?; + + info!("User {} has updated {gateway}", session.user.username); + Ok(ApiResponse::new(json!({}), StatusCode::OK)) +} diff --git a/src/handlers/group.rs b/src/handlers/group.rs index 97f45dd46..6d5174e2e 100644 --- a/src/handlers/group.rs +++ b/src/handlers/group.rs @@ -10,7 +10,7 @@ use super::{ApiResponse, EditGroupInfo, GroupInfo, Username}; use crate::{ appstate::AppState, auth::{SessionInfo, UserAdminRole}, - db::{Group, User, WireguardNetwork}, + db::models::{group::Group, user::User, wireguard::WireguardNetwork}, error::WebError, server_config, // ldap::utils::{ldap_add_user_to_group, ldap_modify_group, ldap_remove_user_from_group}, diff --git a/src/handlers/mail.rs b/src/handlers/mail.rs index f2cc35f90..0e4d2724e 100644 --- a/src/handlers/mail.rs +++ b/src/handlers/mail.rs @@ -13,11 +13,18 @@ use tokio::{ sync::mpsc::{unbounded_channel, UnboundedSender}, }; -use super::{ApiResponse, ApiResult}; +use super::ApiResponse; use crate::{ appstate::AppState, auth::{AdminRole, SessionInfo}, - db::{models::enrollment::TokenError, Id, MFAMethod, Session, User}, + db::{ + models::{ + enrollment::TokenError, + session::Session, + user::{MFAMethod, User}, + }, + Id, + }, error::WebError, mail::{Attachment, Mail}, server_config, @@ -57,12 +64,12 @@ fn internal_error(to: &str, subject: &str, error: &impl Display) -> ApiResponse } } -pub async fn test_mail( +pub(crate) async fn test_mail( _admin: AdminRole, session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} sending test mail to {}", session.user.username, data.to @@ -114,11 +121,11 @@ async fn read_logs() -> String { } } -pub async fn send_support_data( +pub(crate) async fn send_support_data( _admin: AdminRole, session: SessionInfo, State(appstate): State, -) -> ApiResult { +) -> Result { debug!( "User {} sending support mail to {SUPPORT_EMAIL_ADDRESS}", session.user.username @@ -169,7 +176,7 @@ pub async fn send_support_data( } } -pub fn send_new_device_added_email( +pub(crate) fn send_new_device_added_email( device_name: &str, public_key: &str, template_locations: &[TemplateLocation], @@ -208,10 +215,10 @@ pub fn send_new_device_added_email( } } -pub async fn send_gateway_disconnected_email( +pub(crate) async fn send_gateway_disconnected_email( gateway_name: Option, - network_name: String, - gateway_adress: &str, + network_name: &str, + gateway_url: &str, mail_tx: &UnboundedSender, pool: &PgPool, ) -> Result<(), WebError> { @@ -224,8 +231,8 @@ pub async fn send_gateway_disconnected_email( subject: GATEWAY_DISCONNECTED.to_string(), content: templates::gateway_disconnected_mail( &gateway_name, - gateway_adress, - &network_name, + gateway_url, + network_name, )?, attachments: Vec::new(), result_tx: None, @@ -246,7 +253,7 @@ pub async fn send_gateway_disconnected_email( Ok(()) } -pub async fn send_new_device_login_email( +pub(crate) async fn send_new_device_login_email( user_email: &str, mail_tx: &UnboundedSender, session: &Session, @@ -276,7 +283,7 @@ pub async fn send_new_device_login_email( Ok(()) } -pub async fn send_new_device_ocid_login_email( +pub(crate) async fn send_new_device_ocid_login_email( user_email: &str, oauth2client_name: String, mail_tx: &UnboundedSender, @@ -308,7 +315,7 @@ pub async fn send_new_device_ocid_login_email( Ok(()) } -pub fn send_mfa_configured_email( +pub(crate) fn send_mfa_configured_email( session: Option<&Session>, user: &User, mfa_method: &MFAMethod, @@ -340,7 +347,7 @@ pub fn send_mfa_configured_email( } } -pub fn send_email_mfa_activation_email( +pub(crate) fn send_email_mfa_activation_email( user: &User, mail_tx: &UnboundedSender, session: &Session, @@ -375,7 +382,7 @@ pub fn send_email_mfa_activation_email( } } -pub fn send_email_mfa_code_email( +pub(crate) fn send_email_mfa_code_email( user: &User, mail_tx: &UnboundedSender, session: Option<&Session>, @@ -410,7 +417,7 @@ pub fn send_email_mfa_code_email( } } -pub fn send_password_reset_email( +pub(crate) fn send_password_reset_email( user: &User, mail_tx: &UnboundedSender, service_url: Url, @@ -442,7 +449,7 @@ pub fn send_password_reset_email( } } -pub fn send_password_reset_success_email( +pub(crate) fn send_password_reset_success_email( user: &User, mail_tx: &UnboundedSender, ip_address: Option<&str>, diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 55edbf4da..56559edcd 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -9,10 +9,13 @@ use utoipa::ToSchema; use webauthn_rs::prelude::RegisterPublicKeyCredential; #[cfg(feature = "wireguard")] -use crate::db::Device; +use crate::db::models::device::Device; use crate::{ auth::SessionInfo, - db::{Id, NoId, User, UserInfo, WebHook}, + db::{ + models::{user::User, webhook::WebHook, UserInfo}, + Id, NoId, + }, enterprise::license::LicenseError, error::WebError, VERSION, @@ -21,6 +24,8 @@ use crate::{ pub(crate) mod app_info; pub(crate) mod auth; pub(crate) mod forward_auth; +#[cfg(feature = "wireguard")] +pub mod gateway; pub(crate) mod group; pub(crate) mod mail; #[cfg(feature = "openid")] @@ -42,9 +47,10 @@ pub(crate) static SESSION_COOKIE_NAME: &str = "defguard_session"; pub(crate) static SIGN_IN_COOKIE_NAME: &str = "defguard_sign_in"; #[derive(Default, ToSchema)] -pub struct ApiResponse { - pub json: Value, - pub status: StatusCode, +pub(crate) struct ApiResponse { + json: Value, + #[schema(value_type = u16)] + status: StatusCode, } impl ApiResponse { @@ -158,8 +164,6 @@ impl IntoResponse for ApiResponse { } } -pub type ApiResult = Result; - #[derive(Deserialize, Serialize)] pub struct Auth { username: String, @@ -232,7 +236,7 @@ pub struct Username { pub username: String, } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, ToSchema)] pub struct AddUserData { pub username: String, pub last_name: String, @@ -294,7 +298,7 @@ pub struct WalletAddress { } #[derive(Serialize)] -pub struct RecoveryCodes { +pub(crate) struct RecoveryCodes { codes: Option>, } @@ -333,9 +337,9 @@ impl From for WebHook { } } -/// Return type needed to know if user came from openid flow -/// with optional url to redirect him later if yes -#[derive(Serialize, Deserialize)] +/// Return type needed to know if user came from OpenID flow +/// with optional URL to redirect him later if yes +#[derive(Deserialize, Serialize)] pub struct AuthResponse { pub user: UserInfo, pub url: Option, diff --git a/src/handlers/openid_clients.rs b/src/handlers/openid_clients.rs index b9d2132ea..f26bb3350 100644 --- a/src/handlers/openid_clients.rs +++ b/src/handlers/openid_clients.rs @@ -4,7 +4,7 @@ use axum::{ }; use serde_json::json; -use super::{webhooks::ChangeStateData, ApiResponse, ApiResult}; +use super::{webhooks::ChangeStateData, ApiResponse}; use crate::{ appstate::AppState, auth::{AdminRole, SessionInfo}, @@ -12,6 +12,7 @@ use crate::{ oauth2client::{OAuth2Client, OAuth2ClientSafe}, NewOpenIDClient, }, + error::WebError, }; pub async fn add_openid_client( @@ -19,7 +20,7 @@ pub async fn add_openid_client( session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { let client = OAuth2Client::from_new(data).save(&appstate.pool).await?; debug!( "User {} adding OpenID client {}", @@ -35,7 +36,10 @@ pub async fn add_openid_client( }) } -pub async fn list_openid_clients(_admin: AdminRole, State(appstate): State) -> ApiResult { +pub async fn list_openid_clients( + _admin: AdminRole, + State(appstate): State, +) -> Result { let openid_clients = OAuth2Client::all(&appstate.pool).await?; Ok(ApiResponse { json: json!(openid_clients), @@ -47,7 +51,7 @@ pub async fn get_openid_client( State(appstate): State, Path(client_id): Path, session: SessionInfo, -) -> ApiResult { +) -> Result { match OAuth2Client::find_by_client_id(&appstate.pool, &client_id).await? { Some(openid_client) => { if session.is_admin { @@ -75,7 +79,7 @@ pub async fn change_openid_client( State(appstate): State, Path(client_id): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} updating OpenID client {client_id}...", session.user.username @@ -107,7 +111,7 @@ pub async fn change_openid_client_state( State(appstate): State, Path(client_id): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} updating OpenID client {client_id} enabled state", session.user.username @@ -135,7 +139,7 @@ pub async fn delete_openid_client( session: SessionInfo, State(appstate): State, Path(client_id): Path, -) -> ApiResult { +) -> Result { debug!( "User {} deleting OpenID client {client_id}", session.user.username diff --git a/src/handlers/openid_flow.rs b/src/handlers/openid_flow.rs index 0c166ed25..ef365be3b 100644 --- a/src/handlers/openid_flow.rs +++ b/src/handlers/openid_flow.rs @@ -1,6 +1,7 @@ use std::{ fmt, ops::{Deref, DerefMut}, + time::Duration, }; use axum::{ @@ -33,15 +34,21 @@ use serde::{ }; use serde_json::json; use sqlx::PgPool; -use time::Duration; -use super::{ApiResponse, ApiResult, SESSION_COOKIE_NAME}; +use super::{ApiResponse, SESSION_COOKIE_NAME}; use crate::{ appstate::AppState, auth::{AccessUserInfo, SessionInfo}, db::{ - models::{auth_code::AuthCode, oauth2client::OAuth2Client}, - Id, OAuth2AuthorizedApp, OAuth2Token, Session, SessionState, User, + models::{ + auth_code::AuthCode, + oauth2authorizedapp::OAuth2AuthorizedApp, + oauth2client::OAuth2Client, + oauth2token::OAuth2Token, + session::{Session, SessionState}, + user::User, + }, + Id, }, error::WebError, handlers::{mail::send_new_device_ocid_login_email, SIGN_IN_COOKIE_NAME}, @@ -73,7 +80,7 @@ impl From<&User> for StandardClaims { } } -pub async fn discovery_keys() -> ApiResult { +pub(crate) async fn discovery_keys() -> Result { let mut keys = Vec::new(); if let Some(openid_key) = server_config().openid_key() { keys.push(openid_key.as_verification_key()); @@ -360,13 +367,13 @@ fn login_redirect( .secure(!config.cookie_insecure) .same_site(SameSite::Lax) .http_only(true) - .max_age(Duration::minutes(10)); + .max_age(time::Duration::minutes(10)); redirect_to("/login", private_cookies.add(cookie)) } /// Authorization Endpoint /// See https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint -pub async fn authorization( +pub(crate) async fn authorization( State(appstate): State, Query(data): Query, cookies: CookieJar, @@ -519,7 +526,7 @@ pub async fn get_group_claims(pool: &PgPool, user: &User) -> Result, Query(data): Query, @@ -672,8 +679,8 @@ impl TokenRequest { debug!("Scope contains openid, issuing JWT ID token"); let authorization_code = AuthorizationCode::new(code.into()); let issue_time = Utc::now(); - let timeout = server_config().session_timeout; - let expiration = issue_time + chrono::Duration::seconds(timeout.as_secs() as i64); + let timeout: Duration = server_config().session_timeout.into(); + let expiration = issue_time + timeout; let id_token_claims = IdTokenClaims::new( IssuerUrl::from_url(base_url.clone()), vec![Audience::new(auth_code.client_id.clone())], @@ -755,11 +762,11 @@ impl TokenRequest { /// Token Endpoint /// https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint /// https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens -pub async fn token( +pub(crate) async fn token( State(appstate): State, oauth2client: Option>, Form(form): Form, -) -> ApiResult { +) -> Result { // TODO: cleanup branches match form.grant_type.as_str() { "authorization_code" => { @@ -894,7 +901,7 @@ pub async fn token( } /// https://openid.net/specs/openid-connect-core-1_0.html#UserInfo -pub async fn userinfo(user_info: AccessUserInfo) -> ApiResult { +pub(crate) async fn userinfo(user_info: AccessUserInfo) -> Result { let userclaims = StandardClaims::::from(&user_info.0); Ok(ApiResponse { json: json!(userclaims), @@ -903,7 +910,7 @@ pub async fn userinfo(user_info: AccessUserInfo) -> ApiResult { } // Must be served under /.well-known/openid-configuration -pub async fn openid_configuration() -> ApiResult { +pub(crate) async fn openid_configuration() -> Result { let config = server_config(); let provider_metadata = CoreProviderMetadata::new( IssuerUrl::from_url(config.url.clone()), diff --git a/src/handlers/settings.rs b/src/handlers/settings.rs index 90ccc76bb..23be0267a 100644 --- a/src/handlers/settings.rs +++ b/src/handlers/settings.rs @@ -5,13 +5,10 @@ use axum::{ use serde_json::json; use struct_patch::Patch; -use super::{ApiResponse, ApiResult}; +use super::ApiResponse; use crate::{ auth::{AdminRole, SessionInfo}, - db::{ - models::settings::{SettingsEssentials, SettingsPatch}, - Settings, - }, + db::models::settings::{Settings, SettingsEssentials, SettingsPatch}, enterprise::license::update_cached_license, error::WebError, ldap::LDAPConnection, @@ -21,7 +18,7 @@ use crate::{ static DEFAULT_NAV_LOGO_URL: &str = "/svg/defguard-nav-logo.svg"; static DEFAULT_MAIN_LOGO_URL: &str = "/svg/logo-defguard-white.svg"; -pub async fn get_settings(State(appstate): State) -> ApiResult { +pub async fn get_settings(State(appstate): State) -> Result { debug!("Retrieving settings"); if let Some(mut settings) = Settings::get(&appstate.pool).await? { if settings.nav_logo_url.is_empty() { @@ -47,7 +44,7 @@ pub async fn update_settings( session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("User {} updating settings", session.user.username); update_cached_license(data.license.as_deref())?; @@ -58,7 +55,9 @@ pub async fn update_settings( Ok(ApiResponse::default()) } -pub async fn get_settings_essentials(State(appstate): State) -> ApiResult { +pub async fn get_settings_essentials( + State(appstate): State, +) -> Result { debug!("Retrieving essential settings"); let mut settings = SettingsEssentials::get_settings_essentials(&appstate.pool).await?; if settings.nav_logo_url.is_empty() { @@ -81,7 +80,7 @@ pub async fn set_default_branding( State(appstate): State, Path(_id): Path, // TODO: check with front-end and remove. session: SessionInfo, -) -> ApiResult { +) -> Result { debug!( "User {} restoring default branding settings", session.user.username @@ -111,7 +110,7 @@ pub async fn patch_settings( State(appstate): State, session: SessionInfo, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("Admin {} patching settings.", session.user.username); let mut settings = Settings::get_settings(&appstate.pool).await?; @@ -127,7 +126,10 @@ pub async fn patch_settings( Ok(ApiResponse::default()) } -pub async fn test_ldap_settings(_admin: AdminRole, State(appstate): State) -> ApiResult { +pub async fn test_ldap_settings( + _admin: AdminRole, + State(appstate): State, +) -> Result { debug!("Testing LDAP connection"); if LDAPConnection::create(&appstate.pool).await.is_ok() { debug!("LDAP connected successfully"); diff --git a/src/handlers/ssh_authorized_keys.rs b/src/handlers/ssh_authorized_keys.rs index 9db9cfabe..1a5d923fa 100644 --- a/src/handlers/ssh_authorized_keys.rs +++ b/src/handlers/ssh_authorized_keys.rs @@ -7,13 +7,17 @@ use serde_json::json; use sqlx::{query, Error as SqlxError, PgExecutor, PgPool}; use ssh_key::PublicKey; -use super::{user_for_admin_or_self, ApiResponse, ApiResult}; +use super::{user_for_admin_or_self, ApiResponse}; use crate::{ appstate::AppState, auth::SessionInfo, db::{ - models::authentication_key::{AuthenticationKey, AuthenticationKeyType}, - Group, Id, User, + models::{ + authentication_key::{AuthenticationKey, AuthenticationKeyType}, + group::Group, + user::User, + }, + Id, }, error::WebError, }; @@ -97,52 +101,44 @@ pub async fn get_authorized_keys( let mut ssh_keys: Vec = Vec::new(); // check if group filter was specified - match ¶ms.group { - Some(group_name) => { - // fetch group - if let Some(group) = Group::find_by_name(&appstate.pool, group_name).await? { - // check if user filter was specified - match ¶ms.username { - Some(username) => { - debug!("Fetching SSH keys for user {username} in group {group_name}"); - // fetch user - if let Some(user) = User::find_by_username(&appstate.pool, username).await? - { - // check if user belongs to specified group - let members = group.member_usernames(&appstate.pool).await?; - if members.contains(&user.username) { - add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys) - .await; - } else { - debug!("User {username} is not a member of group {group_name}",); - } - } else { - debug!("Specified user does not exist"); - } - } - None => { - debug!("Fetching SSH keys for all users in group {group_name}"); - // fetch all users in group - let users = group.members(&appstate.pool).await?; - for user in users { - add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys).await; - } - } - } - } else { - debug!("Specified group does not exist"); - } - } - None => { + if let Some(group_name) = ¶ms.group { + // fetch group + if let Some(group) = Group::find_by_name(&appstate.pool, group_name).await? { // check if user filter was specified if let Some(username) = ¶ms.username { - debug!("Fetching SSH keys for user {username}"); + debug!("Fetching SSH keys for user {username} in group {group_name}"); // fetch user if let Some(user) = User::find_by_username(&appstate.pool, username).await? { - add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys).await; + // check if user belongs to specified group + let members = group.member_usernames(&appstate.pool).await?; + if members.contains(&user.username) { + add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys).await; + } else { + debug!("User {username} is not a member of group {group_name}",); + } } else { debug!("Specified user does not exist"); } + } else { + debug!("Fetching SSH keys for all users in group {group_name}"); + // fetch all users in group + let users = group.members(&appstate.pool).await?; + for user in users { + add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys).await; + } + } + } else { + debug!("Specified group does not exist"); + } + } else { + // check if user filter was specified + if let Some(username) = ¶ms.username { + debug!("Fetching SSH keys for user {username}"); + // fetch user + if let Some(user) = User::find_by_username(&appstate.pool, username).await? { + add_user_ssh_keys_to_list(&appstate.pool, &user, &mut ssh_keys).await; + } else { + debug!("Specified user does not exist"); } } } @@ -163,7 +159,7 @@ pub async fn add_authentication_key( session: SessionInfo, Path(username): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "Adding authentication key of type {:?} for user {username}", data.key_type, @@ -226,7 +222,7 @@ pub async fn fetch_authentication_keys( State(appstate): State, Path(username): Path, session: SessionInfo, -) -> ApiResult { +) -> Result { let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; let keys_info = AuthenticationKeyInfo::find_by_user_id(&appstate.pool, user.id).await?; @@ -240,7 +236,7 @@ pub async fn delete_authentication_key( State(appstate): State, session: SessionInfo, Path((username, key_id)): Path<(String, i64)>, -) -> ApiResult { +) -> Result { let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; if let Some(key) = AuthenticationKey::find_by_id(&appstate.pool, key_id).await? { if !session.is_admin && user.id != key.user_id { @@ -268,7 +264,7 @@ pub async fn rename_authentication_key( session: SessionInfo, Path((username, key_id)): Path<(String, i64)>, Json(data): Json, -) -> ApiResult { +) -> Result { let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; if let Some(mut key) = AuthenticationKey::find_by_id(&appstate.pool, key_id).await? { if key.yubikey_id.is_some() { diff --git a/src/handlers/support.rs b/src/handlers/support.rs index 549486fca..8631a714a 100644 --- a/src/handlers/support.rs +++ b/src/handlers/support.rs @@ -1,6 +1,6 @@ use axum::{extract::State, http::StatusCode}; -use super::{ApiResponse, ApiResult}; +use super::ApiResponse; use crate::{ auth::{AdminRole, SessionInfo}, error::WebError, @@ -13,7 +13,7 @@ pub async fn configuration( _admin: AdminRole, State(appstate): State, session: SessionInfo, -) -> ApiResult { +) -> Result { debug!("User {} dumping app configuration", session.user.username); let config = dump_config(&appstate.pool).await; info!("User {} dumped app configuration", session.user.username); diff --git a/src/handlers/user.rs b/src/handlers/user.rs index 51e88154f..969b1faf3 100644 --- a/src/handlers/user.rs +++ b/src/handlers/user.rs @@ -7,20 +7,24 @@ use utoipa::ToSchema; use super::{ mail::{send_mfa_configured_email, EMAIL_PASSOWRD_RESET_START_SUBJECT}, - user_for_admin_or_self, AddUserData, ApiResponse, ApiResult, PasswordChange, - PasswordChangeSelf, RecoveryCodes, StartEnrollmentRequest, Username, WalletChallenge, - WalletChange, WalletSignature, + user_for_admin_or_self, AddUserData, ApiResponse, PasswordChange, PasswordChangeSelf, + RecoveryCodes, StartEnrollmentRequest, Username, WalletChallenge, WalletChange, + WalletSignature, }; use crate::{ appstate::AppState, auth::{SessionInfo, UserAdminRole}, - db::{ - models::{ - device::DeviceInfo, - enrollment::{Token, PASSWORD_RESET_TOKEN_TYPE}, - }, - AppEvent, GatewayEvent, MFAMethod, OAuth2AuthorizedApp, Settings, User, UserDetails, - UserInfo, Wallet, WebAuthn, WireguardNetwork, + db::models::{ + device::DeviceInfo, + enrollment::{Token, PASSWORD_RESET_TOKEN_TYPE}, + oauth2authorizedapp::OAuth2AuthorizedApp, + settings::Settings, + user::{MFAMethod, User}, + wallet::Wallet, + webauthn::WebAuthn, + webhook::AppEvent, + wireguard::{ChangeEvent, WireguardNetwork}, + UserDetails, UserInfo, }, error::WebError, ldap::utils::{ldap_add_user, ldap_change_password, ldap_delete_user, ldap_modify_user}, @@ -38,7 +42,7 @@ use crate::{ /// - starts with non-special character /// - special characters: . - _ /// - no whitespaces -pub fn check_username(username: &str) -> Result<(), WebError> { +pub(crate) fn check_username(username: &str) -> Result<(), WebError> { // check length let length = username.len(); if !(3..64).contains(&length) { @@ -78,7 +82,7 @@ pub fn check_username(username: &str) -> Result<(), WebError> { /// - starts with non-special character /// - only special characters allowed: . - _ /// - no whitespaces -pub fn prune_username(username: &str) -> String { +pub(crate) fn prune_username(username: &str) -> String { let mut result = username.to_string(); if result.len() > 64 { @@ -157,7 +161,10 @@ pub(crate) fn check_password_strength(password: &str) -> Result<(), WebError> { (status = 500, description = "Unable return list of users.", body = ApiResponse, example = json!({"msg": "Internal error"})) ) )] -pub async fn list_users(_role: UserAdminRole, State(appstate): State) -> ApiResult { +pub(crate) async fn list_users( + _role: UserAdminRole, + State(appstate): State, +) -> Result { let all_users = User::all(&appstate.pool).await?; let mut users: Vec = Vec::with_capacity(all_users.len()); for user in all_users { @@ -232,11 +239,11 @@ pub async fn list_users(_role: UserAdminRole, State(appstate): State) (status = 500, description = "Unable to return user details.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn get_user( +pub(crate) async fn get_user( session: SessionInfo, State(appstate): State, Path(username): Path, -) -> ApiResult { +) -> Result { let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; let user_details = UserDetails::from_user(&appstate.pool, &user).await?; Ok(ApiResponse { @@ -256,7 +263,7 @@ pub async fn get_user( path = "/api/v1/user", request_body = AddUserData, responses( - (status = 201, description = "Add a new user.", body = UserInfo, example = json!( + (status = CREATED, description = "Add a new user.", body = UserInfo, example = json!( { "authorized_apps": [], "email": "name@email.com", @@ -276,18 +283,18 @@ pub async fn get_user( "username": "username" } )), - (status = 400, description = "Bad request, invalid user data.", body = ApiResponse, example = json!({})), - (status = 401, description = "Unauthorized to create a user.", body = ApiResponse, example = json!({"msg": "Session is required"})), - (status = 403, description = "You don't have permission to create a user.", body = ApiResponse, example = json!({"msg": "access denied"})), - (status = 500, description = "Unable to create a user.", body = ApiResponse, example = json!({"msg": "Internal server error"})) + (status = BAD_REQUEST, description = "Bad request, invalid user data.", body = ApiResponse, example = json!({})), + (status = UNAUTHORIZED, description = "Unauthorized to create a user.", body = ApiResponse, example = json!({"msg": "Session is required"})), + (status = FORBIDDEN, description = "You don't have permission to create a user.", body = ApiResponse, example = json!({"msg": "access denied"})), + (status = INTERNAL_SERVER_ERROR, description = "Unable to create a user.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn add_user( +pub(crate) async fn add_user( _role: UserAdminRole, session: SessionInfo, State(appstate): State, Json(user_data): Json, -) -> ApiResult { +) -> Result { let username = user_data.username.clone(); debug!("User {} adding user {username}", session.user.username); @@ -369,21 +376,21 @@ pub async fn add_user( path = "/api/v1/user/{username}/start_enrollment", request_body = StartEnrollmentRequest, responses( - (status = 201, description = "Trigger enrollment process manually.", body = ApiResponse, example = json!({"enrollment_token": "your_enrollment_token", "enrollment_url": "your_enrollment_token"})), + (status = CREATED, description = "Trigger enrollment process manually.", body = ApiResponse, example = json!({"enrollment_token": "your_enrollment_token", "enrollment_url": "your_enrollment_token"})), (status = 400, description = "Bad request, invalid enrollment request.", body = ApiResponse, example = json!({"msg": "Email notification is enabled, but email was not provided"})), (status = 401, description = "Unauthorized to start enrollment.", body = ApiResponse, example = json!({"msg": "Session is required"})), - (status = 403, description = "You don't have permission to start enrollment.", body = Json, example = json!({"msg": "access denied"})), - (status = 404, description = "Provided user does not exist.", body = Json, example = json!({"msg": "user not found"})), - (status = 500, description = "Unable to start enrollment.", body = Json, example = json!({"msg": "unexpected error"})) + (status = 403, description = "You don't have permission to start enrollment.", body = ApiResponse, example = json!({"msg": "access denied"})), + (status = 404, description = "Provided user does not exist.", body = ApiResponse, example = json!({"msg": "user not found"})), + (status = 500, description = "Unable to start enrollment.", body = ApiResponse, example = json!({"msg": "unexpected error"})) ) )] -pub async fn start_enrollment( +pub(crate) async fn start_enrollment( _role: UserAdminRole, session: SessionInfo, State(appstate): State, Path(username): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} has started a new enrollment request.", session.user.username @@ -463,19 +470,19 @@ pub async fn start_enrollment( path = "/api/v1/user/{username}/start_desktop", request_body = StartEnrollmentRequest, responses( - (status = 201, description = "Trigger enrollment process manually.", body = Json, example = json!({"enrollment_token": "your_enrollment_token", "enrollment_url": "your_enrollment_token"})), - (status = 400, description = "Bad request, invalid enrollment request.", body = Json, example = json!({"msg": "Email notification is enabled, but email was not provided"})), - (status = 401, description = "Unauthorized to start remote desktop configuration.", body = Json, example = json!({"msg": "Can't create desktop configuration enrollment token for disabled user "})), - (status = 404, description = "Provided user does not exist.", body = Json, example = json!({"msg": "user not found"})), - (status = 500, description = "Unable to start remote desktop configuration.", body = Json, example = json!({"msg": "unexpected error"})) + (status = 201, description = "Trigger enrollment process manually.", body = ApiResponse, example = json!({"enrollment_token": "your_enrollment_token", "enrollment_url": "your_enrollment_token"})), + (status = 400, description = "Bad request, invalid enrollment request.", body = ApiResponse, example = json!({"msg": "Email notification is enabled, but email was not provided"})), + (status = 401, description = "Unauthorized to start remote desktop configuration.", body = ApiResponse, example = json!({"msg": "Can't create desktop configuration enrollment token for disabled user "})), + (status = 404, description = "Provided user does not exist.", body = ApiResponse, example = json!({"msg": "user not found"})), + (status = 500, description = "Unable to start remote desktop configuration.", body = ApiResponse, example = json!({"msg": "unexpected error"})) ) )] -pub async fn start_remote_desktop_configuration( +pub(crate) async fn start_remote_desktop_configuration( session: SessionInfo, State(appstate): State, Path(username): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} has started a new desktop activation for {username}.", session.user.username @@ -543,7 +550,6 @@ pub async fn start_remote_desktop_configuration( #[utoipa::path( post, path = "/api/v1/user/available", - request_body = Json, responses( (status = 200, description = "Provided username is available to use.", body = ApiResponse, example = json!({})), (status = 400, description = "Bad request, provided username is not available or username is invalid.", body = ApiResponse, example = json!({})), @@ -552,11 +558,11 @@ pub async fn start_remote_desktop_configuration( (status = 500, description = "Unable to check is username available.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn username_available( +pub(crate) async fn username_available( _role: UserAdminRole, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { if let Err(err) = check_username(&data.username) { debug!("Username {} rejected: {err}", data.username); return Ok(ApiResponse { @@ -590,7 +596,6 @@ pub async fn username_available( params( ("username" = String, description = "name of a user"), ), - request_body = Json, responses( (status = 200, description = "User has been updated."), (status = 400, description = "Bad request, unable to change user data. Verify user data that you want to update.", body = ApiResponse, example = json!({})), @@ -598,12 +603,12 @@ pub async fn username_available( (status = 500, description = "Unable to modify user.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn modify_user( +pub(crate) async fn modify_user( session: SessionInfo, State(appstate): State, Path(username): Path, Json(mut user_info): Json, -) -> ApiResult { +) -> Result { debug!("User {} updating user {username}", session.user.username); let mut user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; if let Err(err) = check_username(&user_info.username) { @@ -657,13 +662,13 @@ pub async fn modify_user( let networks = WireguardNetwork::all(&mut *transaction).await?; for network in networks { let gateway_events = network.sync_allowed_devices(&mut transaction, None).await?; - appstate.send_multiple_wireguard_events(gateway_events); + appstate.send_multiple_change_events(gateway_events); } info!("Allowed network devices of {username} synced"); }; - user_info.into_user_all_fields(&mut user)?; + user_info.into_user_all_fields(&mut user); } else { - user_info.into_user_safe_fields(&mut user)?; + user_info.into_user_safe_fields(&mut user); } user.save(&mut *transaction).await?; @@ -683,7 +688,7 @@ pub async fn modify_user( /// Endpoint helps you delete a user, but `you can't delete yourself as a administrator`. /// /// # Returns -/// If erorr occurs, endpoint will return `WebError` object. +/// If error occurs, endpoint will return `WebError` object. #[utoipa::path( delete, path = "/api/v1/user/{username}", @@ -691,7 +696,7 @@ pub async fn modify_user( ("username" = String, description = "name of a user"), ), responses( - (status = 200, description = "User has been deleted."), + (status = OK, description = "User has been deleted."), (status = 400, description = "Bad request, unable to delete user.", body = ApiResponse, example = json!({})), (status = 401, description = "Unauthorized to delete user.", body = ApiResponse, example = json!({"msg": "Session is required"})), (status = 403, description = "You don't have permission to delete user.", body = ApiResponse, example = json!({"msg": "access denied"})), @@ -699,12 +704,12 @@ pub async fn modify_user( (status = 500, description = "Unable to delete user.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn delete_user( +pub(crate) async fn delete_user( _role: UserAdminRole, State(appstate): State, Path(username): Path, session: SessionInfo, -) -> ApiResult { +) -> Result { debug!("User {} deleting user {username}", session.user.username); if session.user.username == username { debug!("User {username} attempted to delete himself"); @@ -723,11 +728,11 @@ pub async fn delete_user( let devices = user.devices(&mut *transaction).await?; let mut events = Vec::new(); for device in devices { - events.push(GatewayEvent::DeviceDeleted( + events.push(ChangeEvent::DeviceDeleted( DeviceInfo::from_device(&mut *transaction, device).await?, )); } - appstate.send_multiple_wireguard_events(events); + appstate.send_multiple_change_events(events); debug!("Devices of user {username} purged from networks."); user.delete(&mut *transaction).await?; @@ -754,19 +759,18 @@ pub async fn delete_user( #[utoipa::path( put, path = "/api/v1/user/change_password", - request_body = Json, responses( - (status = 200, description = "Pasword has been changed.", body = ApiResponse, example = json!({})), + (status = OK, description = "Pasword has been changed.", body = ApiResponse, example = json!({})), (status = 400, description = "Bad request, provided passwords are not same or new password does not satisfy requirements.", body = ApiResponse, example = json!({})), (status = 401, description = "Unauthorized to change password.", body = ApiResponse, example = json!({"msg": "Session is required"})), (status = 500, description = "Unable to change your password", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn change_self_password( +pub(crate) async fn change_self_password( session: SessionInfo, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("User {} is changing his password.", session.user.username); let mut user = session.user; if user.verify_password(&data.old_password).is_err() { @@ -811,23 +815,22 @@ pub async fn change_self_password( params( ("username" = String, description = "name of a user"), ), - request_body = Json, responses( - (status = 200, description = "Pasword has been changed.", body = ApiResponse, example = json!({})), + (status = OK, description = "Pasword has been changed.", body = ApiResponse, example = json!({})), (status = 400, description = "Bad request, password does not satisfy requirements. This endpoint does not change your own password.", body = ApiResponse, example = json!({})), - (status = 401, description = "Unauthorized to change password.", body = Json, example = json!({"msg": "Session is required"})), + (status = 401, description = "Unauthorized to change password.", body = ApiResponse, example = json!({"msg": "Session is required"})), (status = 403, description = "You don't have permission to change user password.", body = ApiResponse, example = json!({"msg": "access denied"})), (status = 404, description = "Cannot change user password that does not exist.", body = ApiResponse, example = json!({})), (status = 500, description = "Unable to change user password", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn change_password( +pub(crate) async fn change_password( _role: UserAdminRole, session: SessionInfo, State(appstate): State, Path(username): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "Admin {} changing password for user {username}", session.user.username, @@ -899,12 +902,12 @@ pub async fn change_password( (status = 500, description = "Unable to send reset password to email", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn reset_password( +pub(crate) async fn reset_password( _role: UserAdminRole, session: SessionInfo, State(appstate): State, Path(username): Path, -) -> ApiResult { +) -> Result { debug!( "Admin {} resetting password for user {username}", session.user.username, @@ -1013,12 +1016,12 @@ pub struct WalletInfoShort { (status = 500, description = "Cannot retrive settings.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn wallet_challenge( +pub(crate) async fn wallet_challenge( session: SessionInfo, State(appstate): State, Path(username): Path, Query(wallet_info): Query, -) -> ApiResult { +) -> Result { debug!( "User {} generating wallet challenge for user {username}", session.user.username, @@ -1083,18 +1086,18 @@ pub async fn wallet_challenge( ), responses( (status = 200, description = "Successfully set wallet signature."), - (status = 401, description = "Unauthorized to set a new signature.", body = Json, example = json!({"msg": "Session is required"})), - (status = 403, description = "You don't have permission to set new signature to wallet.", body = Json, example = json!({"msg": "requires privileged access"})), + (status = 401, description = "Unauthorized to set a new signature.", body = ApiResponse, example = json!({"msg": "Session is required"})), + (status = 403, description = "You don't have permission to set new signature to wallet.", body = ApiResponse, example = json!({"msg": "requires privileged access"})), (status = 404, description = "Incorrect wallet signature or address, can't set new signature for user.", body = ApiResponse, example = json!({"msg": "wallet not found"})), - (status = 500, description = "Cannot set a new wallet signature", body = Json, example = json!({"msg": "Internal server error"})) + (status = 500, description = "Cannot set a new wallet signature", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn set_wallet( +pub(crate) async fn set_wallet( session: SessionInfo, State(appstate): State, Path(username): Path, Json(wallet_info): Json, -) -> ApiResult { +) -> Result { debug!( "User {} setting wallet signature for user {username}", session.user.username @@ -1142,21 +1145,20 @@ pub async fn set_wallet( ("username" = String, description = "name of a user"), ("address" = String, description = "address of a user portfel") ), - request_body = Json, responses( - (status = 200, description = "Successfully updated user's wallet.", body = RecoveryCodes, example = json!({"codes": "[]"})), + (status = OK, description = "Successfully updated user's wallet.", body = ApiResponse, example = json!({"codes": "[]"})), (status = 401, description = "Unauthorized to udpate user wallet.", body = ApiResponse, example = json!({"msg": "Session is required"})), (status = 403, description = "You don't have permission to update user wallet.", body = ApiResponse, example = json!({"msg": "requires privileged access"})), (status = 404, description = "Incorrect wallet, can't update user wallet.", body = ApiResponse, example = json!({"msg": "wallet not found"})), (status = 500, description = "Cannot udpate user wallet.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn update_wallet( +pub(crate) async fn update_wallet( session: SessionInfo, Path((username, address)): Path<(String, String)>, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} updating wallet {address} for user {username}", session.user.username, @@ -1239,11 +1241,11 @@ pub async fn update_wallet( (status = 500, description = "Cannot delete user wallet.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn delete_wallet( +pub(crate) async fn delete_wallet( session: SessionInfo, State(appstate): State, Path((username, address)): Path<(String, String)>, -) -> ApiResult { +) -> Result { debug!( "User {} deleting wallet {address} for user {username}", session.user.username, @@ -1297,11 +1299,11 @@ pub async fn delete_wallet( (status = 500, description = "Cannot delete authorized app.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn delete_security_key( +pub(crate) async fn delete_security_key( session: SessionInfo, State(appstate): State, Path((username, id)): Path<(String, i64)>, -) -> ApiResult { +) -> Result { debug!( "User {} deleting security key {id} for user {username}", session.user.username, @@ -1366,7 +1368,10 @@ pub async fn delete_security_key( (status = 500, description = "Cannot retrive own user data.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn me(session: SessionInfo, State(appstate): State) -> ApiResult { +pub(crate) async fn me( + session: SessionInfo, + State(appstate): State, +) -> Result { let user_info = UserInfo::from_user(&appstate.pool, &session.user).await?; Ok(ApiResponse { json: json!(user_info), @@ -1395,11 +1400,11 @@ pub async fn me(session: SessionInfo, State(appstate): State) -> ApiRe (status = 500, description = "Cannot delete authorized app.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn delete_authorized_app( +pub(crate) async fn delete_authorized_app( session: SessionInfo, State(appstate): State, Path((username, oauth2client_id)): Path<(String, i64)>, -) -> ApiResult { +) -> Result { debug!( "User {} deleting OAuth2 client {oauth2client_id} for user {username}", session.user.username, diff --git a/src/handlers/webhooks.rs b/src/handlers/webhooks.rs index cc6513e36..151d4e13d 100644 --- a/src/handlers/webhooks.rs +++ b/src/handlers/webhooks.rs @@ -4,11 +4,12 @@ use axum::{ }; use serde_json::json; -use super::{ApiResponse, ApiResult, WebHookData}; +use super::{ApiResponse, WebHookData}; use crate::{ appstate::AppState, auth::{AdminRole, SessionInfo}, - db::WebHook, + db::models::webhook::WebHook, + error::WebError, }; pub async fn add_webhook( @@ -16,7 +17,7 @@ pub async fn add_webhook( session: SessionInfo, State(appstate): State, Json(webhookdata): Json, -) -> ApiResult { +) -> Result { let url = webhookdata.url.clone(); debug!("User {} adding webhook {url}", session.user.username); let webhook: WebHook = webhookdata.into(); @@ -33,7 +34,10 @@ pub async fn add_webhook( } // TODO: paginate -pub async fn list_webhooks(_admin: AdminRole, State(appstate): State) -> ApiResult { +pub async fn list_webhooks( + _admin: AdminRole, + State(appstate): State, +) -> Result { let webhooks = WebHook::all(&appstate.pool).await?; Ok(ApiResponse { @@ -46,7 +50,7 @@ pub async fn get_webhook( _admin: AdminRole, State(appstate): State, Path(id): Path, -) -> ApiResult { +) -> Result { match WebHook::find_by_id(&appstate.pool, id).await? { Some(webhook) => Ok(ApiResponse { json: json!(webhook), @@ -65,7 +69,7 @@ pub async fn change_webhook( State(appstate): State, Path(id): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("User {} updating webhook {id}", session.user.username); let status = match WebHook::find_by_id(&appstate.pool, id).await? { Some(mut webhook) => { @@ -95,7 +99,7 @@ pub async fn delete_webhook( State(appstate): State, Path(id): Path, session: SessionInfo, -) -> ApiResult { +) -> Result { debug!("User {} deleting webhook {id}", session.user.username); let status = match WebHook::find_by_id(&appstate.pool, id).await? { Some(webhook) => { @@ -122,7 +126,7 @@ pub async fn change_enabled( State(appstate): State, Path(id): Path, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} changing webhook {id} enabled state to {}", session.user.username, data.enabled diff --git a/src/handlers/wireguard.rs b/src/handlers/wireguard.rs index 149433e2d..97bb2ca91 100644 --- a/src/handlers/wireguard.rs +++ b/src/handlers/wireguard.rs @@ -1,36 +1,35 @@ -use std::{ - net::IpAddr, - str::FromStr, - sync::{Arc, Mutex}, -}; +use std::{net::IpAddr, str::FromStr}; use axum::{ extract::{Json, Path, Query, State}, http::StatusCode, - Extension, }; -use chrono::{DateTime, Duration, NaiveDateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, TimeDelta, Utc}; use ipnetwork::IpNetwork; use serde_json::{json, Value}; use sqlx::PgPool; use utoipa::ToSchema; -use uuid::Uuid; -use super::{device_for_admin_or_self, user_for_admin_or_self, ApiResponse, ApiResult, WebError}; +use super::{device_for_admin_or_self, user_for_admin_or_self, ApiResponse, WebError}; use crate::{ appstate::AppState, auth::{Claims, ClaimsType, SessionInfo, VpnRole}, db::{ models::{ device::{ - DeviceConfig, DeviceInfo, DeviceNetworkInfo, ModifyDevice, WireguardNetworkDevice, + AddDevice, Device, DeviceConfig, DeviceInfo, DeviceNetworkInfo, ModifyDevice, + WireguardNetworkDevice, + }, + gateway::Gateway, + wireguard::{ + ChangeEvent, DateTimeAggregation, MappedDevice, WireguardNetwork, + WireguardNetworkInfo, }, - wireguard::{DateTimeAggregation, MappedDevice, WireguardNetworkInfo}, }, - AddDevice, Device, GatewayEvent, Id, WireguardNetwork, + Id, }, enterprise::handlers::CanManageDevices, - grpc::GatewayMap, + grpc::GatewayState, handlers::mail::send_new_device_added_email, server_config, templates::TemplateLocation, @@ -40,6 +39,7 @@ use crate::{ #[derive(Deserialize, Serialize, ToSchema)] pub struct WireguardNetworkData { pub name: String, + #[schema(value_type = String)] pub address: IpNetwork, pub endpoint: String, pub port: i32, @@ -62,20 +62,20 @@ impl WireguardNetworkData { } // Used in process of importing network from WireGuard config -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Debug, Deserialize, Serialize)] pub struct MappedDevices { pub devices: Vec, } #[derive(Deserialize)] -pub struct ImportNetworkData { +pub(crate) struct ImportNetworkData { pub name: String, pub endpoint: String, pub config: String, pub allowed_groups: Vec, } -#[derive(Serialize, Deserialize)] +#[derive(Deserialize, Serialize)] pub struct ImportedNetworkData { pub network: WireguardNetwork, pub devices: Vec, @@ -92,12 +92,12 @@ pub struct ImportedNetworkData { // (status = 500, description = "Unable to create network.", body = Json, example = json!({"msg": "Invalid network address"})) // ) // )] -pub async fn create_network( +pub(crate) async fn create_network( _role: VpnRole, State(appstate): State, session: SessionInfo, Json(data): Json, -) -> ApiResult { +) -> Result { let network_name = data.name.clone(); debug!( "User {} creating WireGuard network {network_name}", @@ -114,8 +114,7 @@ pub async fn create_network( data.mfa_enabled, data.keepalive_interval, data.peer_disconnect_threshold, - ) - .map_err(|_| WebError::Serialization("Invalid network address".into()))?; + ); let mut transaction = appstate.pool.begin().await?; let network = network.save(&mut *transaction).await?; @@ -127,7 +126,7 @@ pub async fn create_network( network.add_all_allowed_devices(&mut transaction).await?; info!("Assigning IPs for existing devices in network {network}"); - appstate.send_wireguard_event(GatewayEvent::NetworkCreated(network.id, network.clone())); + appstate.send_change_event(ChangeEvent::NetworkCreated(network.clone())); transaction.commit().await?; @@ -136,10 +135,7 @@ pub async fn create_network( session.user.username ); - Ok(ApiResponse { - json: json!(network), - status: StatusCode::CREATED, - }) + Ok(ApiResponse::new(json!(network), StatusCode::CREATED)) } async fn find_network(id: Id, pool: &PgPool) -> Result, WebError> { @@ -148,13 +144,13 @@ async fn find_network(id: Id, pool: &PgPool) -> Result, Web .ok_or_else(|| WebError::ObjectNotFound(format!("Network {id} not found"))) } -pub async fn modify_network( +pub(crate) async fn modify_network( _role: VpnRole, - Path(network_id): Path, + Path(network_id): Path, State(appstate): State, session: SessionInfo, Json(data): Json, -) -> ApiResult { +) -> Result { debug!( "User {} updating WireGuard network {network_id}", session.user.username @@ -181,11 +177,7 @@ pub async fn modify_network( let _events = network.sync_allowed_devices(&mut transaction, None).await?; let peers = network.get_peers(&mut *transaction).await?; - appstate.send_wireguard_event(GatewayEvent::NetworkModified( - network.id, - network.clone(), - peers, - )); + appstate.send_change_event(ChangeEvent::NetworkModified(network.clone(), peers)); // commit DB transaction transaction.commit().await?; @@ -194,18 +186,15 @@ pub async fn modify_network( "User {} updated WireGuard network {network_id}", session.user.username, ); - Ok(ApiResponse { - json: json!(network), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(network), StatusCode::OK)) } -pub async fn delete_network( +pub(crate) async fn delete_network( _role: VpnRole, - Path(network_id): Path, + Path(network_id): Path, State(appstate): State, session: SessionInfo, -) -> ApiResult { +) -> Result { debug!( "User {} deleting WireGuard network {network_id}", session.user.username, @@ -213,7 +202,7 @@ pub async fn delete_network( let network = find_network(network_id, &appstate.pool).await?; let network_name = network.name.clone(); network.delete(&appstate.pool).await?; - appstate.send_wireguard_event(GatewayEvent::NetworkDeleted(network_id, network_name)); + appstate.send_change_event(ChangeEvent::NetworkDeleted(network_id, network_name)); info!( "User {} deleted WireGuard network {network_id}", session.user.username, @@ -222,119 +211,94 @@ pub async fn delete_network( Ok(ApiResponse::default()) } -pub async fn list_networks( +/// Convert `WireguardNetwork` to `WireguardNetworkInfo`. +async fn network_to_info( + pool: &PgPool, + network: WireguardNetwork, +) -> Result { + let allowed_groups = network.fetch_allowed_groups(pool).await?; + let gateways = Gateway::find_by_network_id(pool, network.id).await?; + let connected = gateways.iter().any(Gateway::is_connected); + let gateways = gateways + .into_iter() + .map(|gateway| GatewayState::from_gateway(&gateway, &network.name)) + .collect(); + + Ok(WireguardNetworkInfo { + network, + connected, + gateways, + allowed_groups, + }) +} + +pub(crate) async fn list_networks( _role: VpnRole, State(appstate): State, - Extension(gateway_state): Extension>>, -) -> ApiResult { +) -> Result { debug!("Listing WireGuard networks"); let mut network_info = Vec::new(); - let networks = WireguardNetwork::all(&appstate.pool).await?; - - for network in networks { - let network_id = network.id; + for network in WireguardNetwork::all(&appstate.pool).await? { let allowed_groups = network.fetch_allowed_groups(&appstate.pool).await?; - { - let gateway_state = gateway_state - .lock() - .expect("Failed to acquire gateway state lock"); - network_info.push(WireguardNetworkInfo { - network, - connected: gateway_state.connected(network_id), - gateways: gateway_state.get_network_gateway_status(network_id), - allowed_groups, - }); - } + let gateways = Gateway::find_by_network_id(&appstate.pool, network.id).await?; + let connected = gateways.iter().any(Gateway::is_connected); + let gateways = gateways + .into_iter() + .map(|gateway| GatewayState::from_gateway(&gateway, &network.name)) + .collect(); + network_info.push(WireguardNetworkInfo { + network, + connected, + gateways, + allowed_groups, + }); } - debug!("Listed WireGuard networks"); + debug!("Listed {} networks", network_info.len()); - Ok(ApiResponse { - json: json!(network_info), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(network_info), StatusCode::OK)) } -pub async fn network_details( - Path(network_id): Path, +pub(crate) async fn network_details( + Path(network_id): Path, _role: VpnRole, State(appstate): State, - Extension(gateway_state): Extension>>, -) -> ApiResult { +) -> Result { debug!("Displaying network details for network {network_id}"); let network = WireguardNetwork::find_by_id(&appstate.pool, network_id).await?; let response = match network { Some(network) => { - let allowed_groups = network.fetch_allowed_groups(&appstate.pool).await?; - let gateway_state = gateway_state - .lock() - .expect("Failed to acquire gateway state lock"); - let network_info = WireguardNetworkInfo { - network, - connected: gateway_state.connected(network_id), - gateways: gateway_state.get_network_gateway_status(network_id), - allowed_groups, - }; - ApiResponse { - json: json!(network_info), - status: StatusCode::OK, - } + let network_info = network_to_info(&appstate.pool, network).await?; + ApiResponse::new(json!(network_info), StatusCode::OK) } - None => ApiResponse { - json: Value::Null, - status: StatusCode::NOT_FOUND, - }, + None => ApiResponse::new(Value::Null, StatusCode::NOT_FOUND), }; debug!("Displayed network details for network {network_id}"); Ok(response) } -pub async fn gateway_status( - Path(network_id): Path, +pub(crate) async fn gateway_status( + Path(network_id): Path, _role: VpnRole, - Extension(gateway_state): Extension>>, -) -> ApiResult { + State(appstate): State, +) -> Result { debug!("Displaying gateway status for network {network_id}"); - let gateway_state = gateway_state - .lock() - .expect("Failed to acquire gateway state lock"); + let network_name = WireguardNetwork::name_for_id(&appstate.pool, network_id).await?; + let gateways = Gateway::find_by_network_id(&appstate.pool, network_id).await?; + let gateways: Vec<_> = gateways + .into_iter() + .map(|gateway| GatewayState::from_gateway(&gateway, &network_name)) + .collect(); debug!("Displayed gateway status for network {network_id}"); - Ok(ApiResponse { - json: json!(gateway_state.get_network_gateway_status(network_id)), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(gateways), StatusCode::OK)) } -pub async fn remove_gateway( - Path((network_id, gateway_id)): Path<(i64, String)>, - _role: VpnRole, - Extension(gateway_state): Extension>>, -) -> ApiResult { - debug!("Removing gateway {gateway_id} in network {network_id}"); - let mut gateway_state = gateway_state - .lock() - .expect("Failed to acquire gateway state lock"); - - gateway_state.remove_gateway( - network_id, - Uuid::from_str(&gateway_id) - .map_err(|_| WebError::Http(StatusCode::INTERNAL_SERVER_ERROR))?, - )?; - - info!("Removed gateway {gateway_id} in network {network_id}"); - - Ok(ApiResponse { - json: Value::Null, - status: StatusCode::OK, - }) -} - -pub async fn import_network( +pub(crate) async fn import_network( _role: VpnRole, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("Importing network from config file"); let (mut network, imported_devices) = parse_wireguard_config(&data.config).map_err(|error| { @@ -351,7 +315,7 @@ pub async fn import_network( .await?; info!("New network {network} created"); - appstate.send_wireguard_event(GatewayEvent::NetworkCreated(network.id, network.clone())); + appstate.send_change_event(ChangeEvent::NetworkCreated(network.clone())); let reserved_ips: Vec = imported_devices .iter() @@ -360,35 +324,35 @@ pub async fn import_network( let (devices, gateway_events) = network .handle_imported_devices(&mut transaction, imported_devices) .await?; - appstate.send_multiple_wireguard_events(gateway_events); + appstate.send_multiple_change_events(gateway_events); // assign IPs for other existing devices debug!("Assigning IPs in imported network for remaining existing devices"); let gateway_events = network .sync_allowed_devices(&mut transaction, Some(&reserved_ips)) .await?; - appstate.send_multiple_wireguard_events(gateway_events); + appstate.send_multiple_change_events(gateway_events); debug!("Assigned IPs in imported network for remaining existing devices"); transaction.commit().await?; info!("Imported network {network} with {} devices", devices.len()); - Ok(ApiResponse { - json: json!(ImportedNetworkData { network, devices }), - status: StatusCode::CREATED, - }) + Ok(ApiResponse::new( + json!(ImportedNetworkData { network, devices }), + StatusCode::CREATED, + )) } // This is used exclusively for the wizard to map imported devices to users. -pub async fn add_user_devices( +pub(crate) async fn add_user_devices( _role: VpnRole, session: SessionInfo, State(appstate): State, - Path(network_id): Path, + Path(network_id): Path, Json(request_data): Json, -) -> ApiResult { - let mapped_devices = request_data.devices.clone(); +) -> Result { + let mapped_devices = request_data.devices; let user = session.user; let device_count = mapped_devices.len(); @@ -400,19 +364,16 @@ pub async fn add_user_devices( // finish early if no devices were provided in request if mapped_devices.is_empty() { debug!("No devices provided in request, skipping mapping"); - return Ok(ApiResponse { - json: json!({}), - status: StatusCode::NO_CONTENT, - }); + return Ok(ApiResponse::new(json!({}), StatusCode::NO_CONTENT)); } if let Some(network) = WireguardNetwork::find_by_id(&appstate.pool, network_id).await? { // wrap loop in transaction to abort if a device is invalid let mut transaction = appstate.pool.begin().await?; let events = network - .handle_mapped_devices(&mut transaction, mapped_devices) + .handle_mapped_devices(&mut transaction, mapped_devices.as_slice()) .await?; - appstate.send_multiple_wireguard_events(events); + appstate.send_multiple_change_events(events); transaction.commit().await?; info!( @@ -420,10 +381,7 @@ pub async fn add_user_devices( user.username, ); - Ok(ApiResponse { - json: json!({}), - status: StatusCode::CREATED, - }) + Ok(ApiResponse::new(json!({}), StatusCode::CREATED)) } else { error!("Failed to map devices, network {network_id} not found"); Err(WebError::ObjectNotFound(format!( @@ -490,14 +448,14 @@ pub struct AddDeviceResult { (status = 500, description = "Cannot add a new device for a user.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn add_device( +pub(crate) async fn add_device( _can_manage_devices: CanManageDevices, session: SessionInfo, State(appstate): State, // Alias, because otherwise `axum` reports conflicting routes. Path(username): Path, Json(add_device): Json, -) -> ApiResult { +) -> Result { let device_name = add_device.name.clone(); debug!( "User {} adding device {device_name} for user {username}", @@ -551,7 +509,7 @@ pub async fn add_device( network_ips.push(network_info_item.device_wireguard_ip.to_string()); } - appstate.send_wireguard_event(GatewayEvent::DeviceCreated(DeviceInfo { + appstate.send_change_event(ChangeEvent::DeviceCreated(DeviceInfo { device: device.clone(), network_info: network_info.clone(), })); @@ -592,10 +550,7 @@ pub async fn add_device( let result = AddDeviceResult { configs, device }; - Ok(ApiResponse { - json: json!(result), - status: StatusCode::CREATED, - }) + Ok(ApiResponse::new(json!(result), StatusCode::CREATED)) } /// Modify device @@ -611,11 +566,11 @@ pub async fn add_device( put, path = "/api/v1/device/{device_id}", params( - ("device_id" = i64, description = "Id of device to update details.") + ("device_id" = Id, description = "Device ID for updating the details") ), request_body = ModifyDevice, responses( - (status = 200, description = "Successfully updated a device.", body = Device, example = json!( + (status = 200, description = "Device successfully updated.", body = ApiResponse, example = json!( { "id": 0, "name": "name", @@ -630,33 +585,30 @@ pub async fn add_device( (status = 500, description = "Cannot update a device.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn modify_device( +pub(crate) async fn modify_device( _can_manage_devices: CanManageDevices, session: SessionInfo, - Path(device_id): Path, + Path(device_id): Path, State(appstate): State, Json(data): Json, -) -> ApiResult { +) -> Result { debug!("User {} updating device {device_id}", session.user.username); let mut device = device_for_admin_or_self(&appstate.pool, &session, device_id).await?; let networks = WireguardNetwork::all(&appstate.pool).await?; if networks.is_empty() { error!("Failed to update device {device_id}, no networks found"); - return Ok(ApiResponse { - json: json!({}), - status: StatusCode::BAD_REQUEST, - }); + return Ok(ApiResponse::new(json!({}), StatusCode::BAD_REQUEST)); } // check pubkeys for network in &networks { if network.pubkey == data.wireguard_pubkey { error!("Failed to update device {device_id}, device's pubkey must be different from server's pubkey"); - return Ok(ApiResponse { - json: json!({"msg": "device's pubkey must be different from server's pubkey"}), - status: StatusCode::BAD_REQUEST, - }); + return Ok(ApiResponse::new( + json!({"msg": "device's pubkey must be different from server's pubkey"}), + StatusCode::BAD_REQUEST, + )); } } @@ -679,16 +631,13 @@ pub async fn modify_device( network_info.push(device_network_info); } } - appstate.send_wireguard_event(GatewayEvent::DeviceModified(DeviceInfo { + appstate.send_change_event(ChangeEvent::DeviceModified(DeviceInfo { device: device.clone(), network_info, })); info!("User {} updated device {device_id}", session.user.username); - Ok(ApiResponse { - json: json!(device), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(device), StatusCode::OK)) } /// Get device @@ -699,10 +648,10 @@ pub async fn modify_device( get, path = "/api/v1/device/{device_id}", params( - ("device_id" = i64, description = "Id of device to update details.") + ("device_id" = Id, description = "Device ID for fetching the details.") ), responses( - (status = 200, description = "Successfully updated a device.", body = Device, example = json!( + (status = 200, description = "Device successfully fetched.", body = Device, example = json!( { "id": 0, "name": "name", @@ -713,21 +662,18 @@ pub async fn modify_device( )), (status = 400, description = "Bad request, no networks found or device with pubkey that you want to send with is a server's pubkey.", body = ApiResponse, example = json!({"msg": "device's pubkey must be different from server's pubkey"})), (status = 401, description = "Unauthorized to update a device.", body = ApiResponse, example = json!({"msg": "Session is required"})), - (status = 404, description = "Device not found.", body = ApiResponse, example = json!({"msg": "device id not found"})) + (status = 404, description = "Device not found.", body = ApiResponse, example = json!({"msg": "device ID not found"})) ) )] -pub async fn get_device( +pub(crate) async fn get_device( session: SessionInfo, - Path(device_id): Path, + Path(device_id): Path, State(appstate): State, -) -> ApiResult { +) -> Result { debug!("Retrieving device with id: {device_id}"); let device = device_for_admin_or_self(&appstate.pool, &session, device_id).await?; debug!("Retrieved device with id: {device_id}"); - Ok(ApiResponse { - json: json!(device), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(device), StatusCode::OK)) } /// Delete device @@ -740,24 +686,24 @@ pub async fn get_device( delete, path = "/api/v1/device/{device_id}", params( - ("device_id" = i64, description = "Id of device to update details.") + ("device_id" = Id, description = "Device ID for deletion.") ), responses( - (status = 200, description = "Successfully deleted device."), + (status = 200, description = "Device successfully deleted."), (status = 401, description = "Unauthorized to update a device.", body = ApiResponse, example = json!({"msg": "Session is required"})), (status = 404, description = "Device not found.", body = ApiResponse, example = json!({"msg": "device id not found"})), (status = 500, description = "Cannot update a device.", body = ApiResponse, example = json!({"msg": "Internal server error"})) ) )] -pub async fn delete_device( +pub(crate) async fn delete_device( _can_manage_devices: CanManageDevices, session: SessionInfo, - Path(device_id): Path, + Path(device_id): Path, State(appstate): State, -) -> ApiResult { +) -> Result { debug!("User {} deleting device {device_id}", session.user.username); let device = device_for_admin_or_self(&appstate.pool, &session, device_id).await?; - appstate.send_wireguard_event(GatewayEvent::DeviceDeleted( + appstate.send_change_event(ChangeEvent::DeviceDeleted( DeviceInfo::from_device(&appstate.pool, device.clone()).await?, )); device.delete(&appstate.pool).await?; @@ -786,15 +732,15 @@ pub async fn delete_device( (status = 403, description = "You don't have permission to list all devices.", body = ApiResponse, example = json!({"msg": "requires privileged access"})), ) )] -pub async fn list_devices(_role: VpnRole, State(appstate): State) -> ApiResult { +pub(crate) async fn list_devices( + _role: VpnRole, + State(appstate): State, +) -> Result { debug!("Listing devices"); let devices = Device::all(&appstate.pool).await?; info!("Listed {} devices", devices.len()); - Ok(ApiResponse { - json: json!(devices), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(devices), StatusCode::OK)) } /// List user devices @@ -823,11 +769,11 @@ pub async fn list_devices(_role: VpnRole, State(appstate): State) -> A (status = 403, description = "You don't have permission to list user devices.", body = ApiResponse, example = json!({"msg": "Admin access required"})), ) )] -pub async fn list_user_devices( +pub(crate) async fn list_user_devices( session: SessionInfo, State(appstate): State, Path(username): Path, -) -> ApiResult { +) -> Result { // only allow for admin or user themselves if !session.is_admin && session.user.username != username { warn!( @@ -840,16 +786,13 @@ pub async fn list_user_devices( let devices = Device::all_for_username(&appstate.pool, &username).await?; info!("Listed {} devices for user: {username}", devices.len()); - Ok(ApiResponse { - json: json!(devices), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(devices), StatusCode::OK)) } -pub async fn download_config( +pub(crate) async fn download_config( session: SessionInfo, State(appstate): State, - Path((network_id, device_id)): Path<(i64, i64)>, + Path((network_id, device_id)): Path<(Id, Id)>, ) -> Result { debug!("Creating config for device {device_id} in network {network_id}"); let network = find_network(network_id, &appstate.pool).await?; @@ -871,11 +814,11 @@ pub async fn download_config( } } -pub async fn create_network_token( +pub(crate) async fn create_network_token( _role: VpnRole, State(appstate): State, - Path(network_id): Path, -) -> ApiResult { + Path(network_id): Path, +) -> Result { debug!("Generating a new token for network ID {network_id}"); let network = find_network(network_id, &appstate.pool).await?; let token = Claims::new( @@ -893,10 +836,12 @@ pub async fn create_network_token( )) })?; info!("Generated a new token for network ID {network_id}"); - Ok(ApiResponse { - json: json!({"token": token, "grpc_url": server_config().grpc_url.to_string()}), - status: StatusCode::OK, - }) + + // TODO: `grpc_url` is meaningless. + Ok(ApiResponse::new( + json!({"token": token, "grpc_url": server_config().grpc_url.to_string()}), + StatusCode::OK, + )) } /// Returns appropriate aggregation level depending on the `from` date param @@ -905,8 +850,8 @@ pub async fn create_network_token( fn get_aggregation(from: NaiveDateTime) -> Result { // Use hourly aggregation for longer periods let aggregation = match Utc::now().naive_utc() - from { - duration if duration >= Duration::hours(6) => Ok(DateTimeAggregation::Hour), - duration if duration < Duration::zero() => Err(StatusCode::BAD_REQUEST), + duration if duration >= TimeDelta::hours(6) => Ok(DateTimeAggregation::Hour), + duration if duration < TimeDelta::zero() => Err(StatusCode::BAD_REQUEST), _ => Ok(DateTimeAggregation::Minute), }?; Ok(aggregation) @@ -922,17 +867,17 @@ impl QueryFrom { fn parse_timestamp(&self) -> Result, StatusCode> { Ok(match &self.from { Some(from) => DateTime::::from_str(from).map_err(|_| StatusCode::BAD_REQUEST)?, - None => Utc::now() - Duration::hours(1), + None => Utc::now() - TimeDelta::hours(1), }) } } -pub async fn user_stats( +pub(crate) async fn user_stats( _role: VpnRole, State(appstate): State, - Path(network_id): Path, + Path(network_id): Path, Query(query_from): Query, -) -> ApiResult { +) -> Result { debug!("Displaying WireGuard user stats for network {network_id}"); let Some(network) = WireguardNetwork::find_by_id(&appstate.pool, network_id).await? else { return Err(WebError::ObjectNotFound(format!( @@ -946,18 +891,15 @@ pub async fn user_stats( .await?; debug!("Displayed WireGuard user stats for network {network_id}"); - Ok(ApiResponse { - json: json!(stats), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(stats), StatusCode::OK)) } -pub async fn network_stats( +pub(crate) async fn network_stats( _role: VpnRole, State(appstate): State, - Path(network_id): Path, + Path(network_id): Path, Query(query_from): Query, -) -> ApiResult { +) -> Result { debug!("Displaying WireGuard network stats for network {network_id}"); let Some(network) = WireguardNetwork::find_by_id(&appstate.pool, network_id).await? else { return Err(WebError::ObjectNotFound(format!( @@ -971,8 +913,5 @@ pub async fn network_stats( .await?; debug!("Displayed WireGuard network stats for network {network_id}"); - Ok(ApiResponse { - json: json!(stats), - status: StatusCode::OK, - }) + Ok(ApiResponse::new(json!(stats), StatusCode::OK)) } diff --git a/src/handlers/worker.rs b/src/handlers/worker.rs index 1ed10fe7b..df42d9aef 100644 --- a/src/handlers/worker.rs +++ b/src/handlers/worker.rs @@ -6,11 +6,11 @@ use axum::{ }; use serde_json::json; -use super::{ApiResponse, ApiResult}; +use super::ApiResponse; use crate::{ appstate::AppState, auth::{AdminRole, Claims, ClaimsType, SessionInfo}, - db::User, + db::models::user::User, error::WebError, grpc::WorkerState, }; @@ -31,12 +31,12 @@ struct JobResponseError { message: String, } -pub async fn create_job( +pub(crate) async fn create_job( session: SessionInfo, State(appstate): State, Extension(worker_state): Extension>>, Json(job_data): Json, -) -> ApiResult { +) -> Result { let (worker, username) = (job_data.worker.clone(), job_data.username.clone()); debug!( "User {} creating a worker job for worker {worker} and user {username}", @@ -80,7 +80,10 @@ pub async fn create_job( } } -pub async fn create_worker_token(session: SessionInfo, _admin: AdminRole) -> ApiResult { +pub(crate) async fn create_worker_token( + session: SessionInfo, + _admin: AdminRole, +) -> Result { let username = session.user.username; let token = Claims::new( ClaimsType::YubiBridge, @@ -96,10 +99,10 @@ pub async fn create_worker_token(session: SessionInfo, _admin: AdminRole) -> Api }) } -pub async fn list_workers( +pub(crate) async fn list_workers( _admin: AdminRole, Extension(worker_state): Extension>>, -) -> ApiResult { +) -> Result { debug!("Listing workers"); let state = worker_state.lock().unwrap(); let workers = state.list_workers(); @@ -110,12 +113,12 @@ pub async fn list_workers( }) } -pub async fn remove_worker( +pub(crate) async fn remove_worker( _admin: AdminRole, session: SessionInfo, Extension(worker_state): Extension>>, Path(id): Path, -) -> ApiResult { +) -> Result { debug!("User {} deleting worker {id}", session.user.username,); let mut state = worker_state.lock().unwrap(); if state.remove_worker(&id) { @@ -129,11 +132,11 @@ pub async fn remove_worker( } } -pub async fn job_status( +pub(crate) async fn job_status( session: SessionInfo, Extension(worker_state): Extension>>, Path(id): Path, -) -> ApiResult { +) -> Result { debug!( "User {} fetching job status for job {id}", session.user.username diff --git a/src/handlers/yubikey.rs b/src/handlers/yubikey.rs index c8660f740..b13a0342b 100644 --- a/src/handlers/yubikey.rs +++ b/src/handlers/yubikey.rs @@ -5,14 +5,14 @@ use axum::{ }; use serde_json::json; -use super::{user_for_admin_or_self, ApiResponse, ApiResult}; -use crate::{appstate::AppState, auth::SessionInfo, db::YubiKey, error::WebError}; +use super::{user_for_admin_or_self, ApiResponse}; +use crate::{appstate::AppState, auth::SessionInfo, db::models::yubikey::YubiKey, error::WebError}; pub async fn delete_yubikey( State(appstate): State, session: SessionInfo, Path((username, key_id)): Path<(String, i64)>, -) -> ApiResult { +) -> Result { debug!("Deleting yubikey {key_id} by {:?}", &session.user.id); let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; let Some(yubikey) = YubiKey::find_by_id(&appstate.pool, key_id).await? else { @@ -44,7 +44,7 @@ pub async fn rename_yubikey( session: SessionInfo, Path((username, key_id)): Path<(String, i64)>, Json(data): Json, -) -> ApiResult { +) -> Result { let user = user_for_admin_or_self(&appstate.pool, &session, &username).await?; debug!("User {} attempts to rename yubikey {}", user.id, key_id); let Some(mut yubikey) = YubiKey::find_by_id(&appstate.pool, key_id).await? else { diff --git a/src/headers.rs b/src/headers.rs index f550edfad..eda515345 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -5,7 +5,10 @@ use tokio::sync::mpsc::UnboundedSender; use uaparser::{Client, Parser, UserAgentParser}; use crate::{ - db::{models::device_login::DeviceLoginEvent, Id, Session, User}, + db::{ + models::{device_login::DeviceLoginEvent, session::Session, user::User}, + Id, + }, handlers::mail::send_new_device_login_email, mail::Mail, templates::TemplateError, diff --git a/src/ldap/mod.rs b/src/ldap/mod.rs index a68111516..1c90e6ebe 100644 --- a/src/ldap/mod.rs +++ b/src/ldap/mod.rs @@ -1,10 +1,13 @@ use std::collections::HashSet; -use ldap3::{drive, Ldap, LdapConnAsync, Mod, Scope, SearchEntry}; +use ldap3::{adapters::EntriesOnly, drive, Ldap, LdapConnAsync, Mod, Scope, SearchEntry}; use sqlx::PgExecutor; use self::error::LdapError; -use crate::db::{self, Id, Settings, User}; +use crate::db::{ + models::{group::Group, settings::Settings, user::User}, + Id, +}; pub mod error; pub mod hash; @@ -123,7 +126,7 @@ impl LDAPConnection { /// Searches LDAP for users. async fn search_users(&mut self, filter: &str) -> Result, LdapError> { - let (rs, _res) = self + let (entries, _result) = self .ldap .search( &self.config.ldap_user_search_base, @@ -135,7 +138,7 @@ impl LDAPConnection { .success()?; info!("Performed LDAP user search with filter = {filter}"); - Ok(rs.into_iter().map(SearchEntry::construct).collect()) + Ok(entries.into_iter().map(SearchEntry::construct).collect()) } /// Searches LDAP for groups. @@ -202,6 +205,7 @@ impl LDAPConnection { self.config.ldap_username_attr, self.config.ldap_user_obj_class )) .await; + // TODO: use streaming, as in `get_user()` match users { Ok(users) => users.is_empty(), _ => true, @@ -209,23 +213,41 @@ impl LDAPConnection { } /// Retrieves user with given username from LDAP. - /// TODO: Password must agree with the password stored in LDAP. pub async fn get_user(&mut self, username: &str, password: &str) -> Result { debug!("Performing LDAP user search: {username}"); - let mut entries = self - .search_users(&format!( - "(&({}={username})(objectClass={}))", - self.config.ldap_username_attr, self.config.ldap_user_obj_class - )) + let filter = format!( + "(&({}={username})(objectClass={}))", + self.config.ldap_username_attr, self.config.ldap_user_obj_class + ); + let mut stream = self + .ldap + .streaming_search_with( + EntriesOnly::new(), + &self.config.ldap_user_search_base, + Scope::Subtree, + &filter, + vec!["*", &self.config.ldap_member_attr], + ) .await?; - if let Some(entry) = entries.pop() { - info!("Performed LDAP user search: {username}"); - Ok(User::from_searchentry(&entry, username, password)) - } else { - Err(LdapError::ObjectNotFound(format!( - "User {username} not found", - ))) + while let Some(result) = stream.next().await? { + let entry = SearchEntry::construct(result); + // Check password by binding to LDAP. + error!("Trying to bind as {}", entry.dn); + match self.ldap.simple_bind(&entry.dn, password).await?.success() { + Ok(_) => { + info!("Performed LDAP user search: {username}"); + return Ok(User::from_searchentry(&entry, username, password)); + } + Err(err) => { + warn!("User {username} didn't authenticate in LDAP"); + return Err(err.into()); + } + } } + + Err(LdapError::ObjectNotFound(format!( + "User {username} not found", + ))) } /// Adds user to LDAP. @@ -303,11 +325,7 @@ impl LDAPConnection { // } /// Modifies LDAP group. - pub async fn modify_group( - &mut self, - groupname: &str, - group: &db::Group, - ) -> Result<(), LdapError> { + pub async fn modify_group(&mut self, groupname: &str, group: &Group) -> Result<(), LdapError> { debug!("Modifying LDAP group {groupname}"); let old_dn = self.config.group_dn(groupname); let new_dn = self.config.group_dn(&group.name); diff --git a/src/ldap/model.rs b/src/ldap/model.rs index a817feaf0..4106cd323 100644 --- a/src/ldap/model.rs +++ b/src/ldap/model.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use ldap3::{Mod, SearchEntry}; use super::LDAPConfig; -use crate::{db::User, hashset}; +use crate::{db::models::user::User, hashset}; impl User { #[must_use] diff --git a/src/ldap/utils.rs b/src/ldap/utils.rs index 1e80af19d..8dbfb092f 100644 --- a/src/ldap/utils.rs +++ b/src/ldap/utils.rs @@ -1,9 +1,9 @@ use sqlx::{PgExecutor, PgPool}; use super::{error::LdapError, LDAPConnection}; -use crate::db::{Group, Id, User}; +use crate::db::{models::user::User, Id}; -pub async fn user_from_ldap( +pub(crate) async fn user_from_ldap( pool: &PgPool, username: &str, password: &str, @@ -18,7 +18,7 @@ pub async fn user_from_ldap( .map_err(|_| LdapError::Database) } -pub async fn ldap_add_user<'e, E>( +pub(crate) async fn ldap_add_user<'e, E>( executor: E, user: &User, password: &str, @@ -34,7 +34,7 @@ where } } -pub async fn ldap_modify_user<'e, E>( +pub(crate) async fn ldap_modify_user<'e, E>( executor: E, username: &str, user: &User, @@ -46,7 +46,7 @@ where ldap_connection.modify_user(username, user).await } -pub async fn ldap_delete_user<'e, E>(executor: E, username: &str) -> Result<(), LdapError> +pub(crate) async fn ldap_delete_user<'e, E>(executor: E, username: &str) -> Result<(), LdapError> where E: PgExecutor<'e>, { @@ -54,33 +54,33 @@ where ldap_connection.delete_user(username).await } -pub async fn ldap_add_user_to_group<'e, E>( - executor: E, - username: &str, - groupname: &str, -) -> Result<(), LdapError> -where - E: PgExecutor<'e>, -{ - let mut ldap_connection = LDAPConnection::create(executor).await?; - ldap_connection.add_user_to_group(username, groupname).await -} +// pub(crate) async fn ldap_add_user_to_group<'e, E>( +// executor: E, +// username: &str, +// groupname: &str, +// ) -> Result<(), LdapError> +// where +// E: PgExecutor<'e>, +// { +// let mut ldap_connection = LDAPConnection::create(executor).await?; +// ldap_connection.add_user_to_group(username, groupname).await +// } -pub async fn ldap_remove_user_from_group<'e, E>( - executor: E, - username: &str, - groupname: &str, -) -> Result<(), LdapError> -where - E: PgExecutor<'e>, -{ - let mut ldap_connection = LDAPConnection::create(executor).await?; - ldap_connection - .remove_user_from_group(username, groupname) - .await -} +// pub(crate) async fn ldap_remove_user_from_group<'e, E>( +// executor: E, +// username: &str, +// groupname: &str, +// ) -> Result<(), LdapError> +// where +// E: PgExecutor<'e>, +// { +// let mut ldap_connection = LDAPConnection::create(executor).await?; +// ldap_connection +// .remove_user_from_group(username, groupname) +// .await +// } -pub async fn ldap_change_password<'e, E>( +pub(crate) async fn ldap_change_password<'e, E>( executor: E, username: &str, password: &str, @@ -92,14 +92,14 @@ where ldap_connection.set_password(username, password).await } -pub async fn ldap_modify_group<'e, E>( - executor: E, - groupname: &str, - group: &Group, -) -> Result<(), LdapError> -where - E: PgExecutor<'e>, -{ - let mut ldap_connection = LDAPConnection::create(executor).await?; - ldap_connection.modify_group(groupname, group).await -} +// pub(crate) async fn ldap_modify_group<'e, E>( +// executor: E, +// groupname: &str, +// group: &Group, +// ) -> Result<(), LdapError> +// where +// E: PgExecutor<'e>, +// { +// let mut ldap_connection = LDAPConnection::create(executor).await?; +// ldap_connection.modify_group(groupname, group).await +// } diff --git a/src/lib.rs b/src/lib.rs index f3f2f3deb..e6d26a11d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,12 +45,16 @@ use utoipa::{ }; use utoipa_swagger_ui::SwaggerUi; +#[cfg(feature = "wireguard")] +use self::handlers::gateway::{ + add_gateway, delete_gateway, get_gateway, get_gateways, update_gateway, +}; #[cfg(feature = "wireguard")] use self::handlers::wireguard::{ add_device, add_user_devices, create_network, create_network_token, delete_device, delete_network, download_config, gateway_status, get_device, import_network, list_devices, list_networks, list_user_devices, modify_device, modify_network, network_details, - network_stats, remove_gateway, user_stats, + network_stats, user_stats, }; #[cfg(feature = "worker")] use self::handlers::worker::{ @@ -72,8 +76,15 @@ use self::{ config::{DefGuardConfig, InitVpnLocationArgs}, db::{ init_db, - models::wireguard::{DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL}, - AppEvent, Device, GatewayEvent, User, WireguardNetwork, + models::{ + device::Device, + user::User, + webhook::AppEvent, + wireguard::{ + ChangeEvent, WireguardNetwork, DEFAULT_DISCONNECT_THRESHOLD, + DEFAULT_KEEPALIVE_INTERVAL, + }, + }, }, handlers::{ auth::{ @@ -108,9 +119,7 @@ use self::{ }; #[cfg(any(feature = "openid", feature = "worker"))] use self::{ - auth::failed_login::FailedLoginMap, - db::models::oauth2client::OAuth2Client, - grpc::{GatewayMap, WorkerState}, + auth::failed_login::FailedLoginMap, db::models::oauth2client::OAuth2Client, grpc::WorkerState, handlers::app_info::get_app_info, }; @@ -154,9 +163,9 @@ pub(crate) fn server_config() -> &'static DefGuardConfig { pub(crate) const KEY_LENGTH: usize = 32; mod openapi { - use db::{ - models::device::{ModifyDevice, UserDevice}, - AddDevice, UserDetails, UserInfo, + use db::models::{ + device::{AddDevice, ModifyDevice, UserDevice}, + UserDetails, UserInfo, }; use error::WebError; use handlers::{ @@ -278,10 +287,9 @@ async fn openapi() -> Json { pub fn build_webapp( webhook_tx: UnboundedSender, webhook_rx: UnboundedReceiver, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, worker_state: Arc>, - gateway_state: Arc>, pool: PgPool, user_agent_parser: Arc, failed_logins: Arc>, @@ -458,10 +466,6 @@ pub fn build_webapp( .route("/network", get(list_networks)) .route("/network/:network_id", get(network_details)) .route("/network/:network_id/gateways", get(gateway_status)) - .route( - "/network/:network_id/gateways/:gateway_id", - delete(remove_gateway), - ) .route("/network/import", post(import_network)) .route("/network/:network_id/devices", post(add_user_devices)) .route( @@ -471,7 +475,11 @@ pub fn build_webapp( .route("/network/:network_id/token", get(create_network_token)) .route("/network/:network_id/stats/users", get(user_stats)) .route("/network/:network_id/stats", get(network_stats)) - .layer(Extension(gateway_state)), + .route("/network/:network_id/gateway", post(add_gateway)) + .route("/gateway/:gateway_id", get(get_gateway)) + .route("/gateway/:gateway_id", put(update_gateway)) + .route("/gateway/:gateway_id", delete(delete_gateway)) + .route("/network/:network_id/all_gateways", get(get_gateways)), ); #[cfg(feature = "worker")] @@ -494,7 +502,7 @@ pub fn build_webapp( pool, webhook_tx, webhook_rx, - wireguard_tx, + events_tx, mail_tx, user_agent_parser, failed_logins, @@ -516,10 +524,9 @@ pub fn build_webapp( /// Runs core web server exposing REST API. pub async fn run_web_server( worker_state: Arc>, - gateway_state: Arc>, webhook_tx: UnboundedSender, webhook_rx: UnboundedReceiver, - wireguard_tx: Sender, + events_tx: Sender, mail_tx: UnboundedSender, pool: PgPool, user_agent_parser: Arc, @@ -528,10 +535,9 @@ pub async fn run_web_server( let webapp = build_webapp( webhook_tx, webhook_rx, - wireguard_tx, + events_tx, mail_tx, worker_state, - gateway_state, pool, user_agent_parser, failed_logins, @@ -594,8 +600,7 @@ pub async fn init_dev_env(config: &DefGuardConfig) { false, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, - ) - .expect("Could not create network"); + ); network.pubkey = "zGMeVGm9HV9I4wSKF9AXmYnnAIhDySyqLMuKpcfIaQo=".to_string(); network.prvkey = "MAk3d5KuB167G88HM7nGYR6ksnPMAOguAg2s5EcPp1M=".to_string(); network @@ -674,7 +679,7 @@ pub async fn init_vpn_location( false, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, - )? + ) .save(pool) .await?; diff --git a/src/mail.rs b/src/mail.rs index 6b93b326f..a4cf959f0 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -10,9 +10,9 @@ use sqlx::PgPool; use thiserror::Error; use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; -use crate::db::{models::settings::SmtpEncryption, Settings}; +use crate::db::models::settings::{Settings, SmtpEncryption}; -const SMTP_TIMEOUT_SECONDS: u64 = 15; +const SMTP_TIMEOUT: Duration = Duration::from_secs(15); #[derive(Debug, Error)] pub enum MailError { @@ -40,12 +40,12 @@ pub enum MailError { /// Subset of Settings object representing SMTP configuration struct SmtpSettings { - pub server: String, - pub port: u16, - pub encryption: SmtpEncryption, - pub user: String, - pub password: String, - pub sender: String, + server: String, + port: u16, + encryption: SmtpEncryption, + user: String, + password: String, + sender: String, } impl SmtpSettings { @@ -181,7 +181,7 @@ impl MailHandler { // Construct lettre Message let result_tx = mail.result_tx.clone(); - let message: Message = match mail.into_message(&settings.sender) { + let message = match mail.into_message(&settings.sender) { Ok(message) => message, Err(err) => { error!("Failed to build message to: {to}, subject: {subject}, error: {err}"); @@ -226,7 +226,7 @@ impl MailHandler { } } .port(settings.port) - .timeout(Some(Duration::from_secs(SMTP_TIMEOUT_SECONDS))); + .timeout(Some(SMTP_TIMEOUT)); Ok(builder .credentials(Credentials::new(settings.user, settings.password)) .build()) diff --git a/src/support.rs b/src/support.rs index d20cdc283..f68fb9ed5 100644 --- a/src/support.rs +++ b/src/support.rs @@ -5,7 +5,13 @@ use serde_json::{json, value::to_value, Value}; use sqlx::PgPool; use crate::{ - db::{models::device::WireguardNetworkDevice, Id, Settings, User, WireguardNetwork}, + db::{ + models::{ + device::WireguardNetworkDevice, settings::Settings, user::User, + wireguard::WireguardNetwork, + }, + Id, + }, server_config, VERSION, }; diff --git a/src/templates.rs b/src/templates.rs index 38890abfa..efa699c2d 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -2,9 +2,16 @@ use chrono::{Datelike, NaiveDateTime, Utc}; use reqwest::Url; use tera::{Context, Tera}; use thiserror::Error; +use utoipa::ToSchema; use crate::{ - db::{Id, MFAMethod, Session, User}, + db::{ + models::{ + session::Session, + user::{MFAMethod, User}, + }, + Id, + }, server_config, VERSION, }; @@ -32,11 +39,12 @@ static MAIL_PASSWORD_RESET_START: &str = static MAIL_PASSWORD_RESET_SUCCESS: &str = include_str!("../templates/mail_password_reset_success.tera"); -#[derive(Error, Debug)] +#[derive(Debug, Error, ToSchema)] pub enum TemplateError { #[error("Failed to generate email MFA code")] MfaError, #[error(transparent)] + #[schema(value_type = String)] TemplateError(#[from] tera::Error), } @@ -173,7 +181,7 @@ pub fn support_data_mail() -> Result { Ok(tera.render("mail_support_data", &context)?) } -#[derive(Serialize, Debug, Clone)] +#[derive(Clone, Debug, Serialize)] pub struct TemplateLocation { pub name: String, pub assigned_ip: String, diff --git a/src/wg_config.rs b/src/wg_config.rs index 0e65ac62f..db6a5801f 100644 --- a/src/wg_config.rs +++ b/src/wg_config.rs @@ -6,11 +6,12 @@ use thiserror::Error; use x25519_dalek::{PublicKey, StaticSecret}; use crate::{ - db::{ - models::wireguard::{ - WireguardNetworkError, DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, + db::models::{ + device::Device, + wireguard::{ + WireguardNetwork, WireguardNetworkError, DEFAULT_DISCONNECT_THRESHOLD, + DEFAULT_KEEPALIVE_INTERVAL, }, - Device, WireguardNetwork, }, KEY_LENGTH, }; @@ -94,7 +95,7 @@ pub fn parse_wireguard_config( false, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, - )?; + ); network.pubkey = pubkey; network.prvkey = prvkey.to_string(); diff --git a/src/wireguard_peer_disconnect.rs b/src/wireguard_peer_disconnect.rs index e8d0fc0d4..fb497e989 100644 --- a/src/wireguard_peer_disconnect.rs +++ b/src/wireguard_peer_disconnect.rs @@ -10,13 +10,10 @@ use sqlx::{query_as, Error as SqlxError, PgPool}; use thiserror::Error; use tokio::{sync::broadcast::Sender, time::sleep}; -use crate::db::{ - models::{ - device::{DeviceInfo, DeviceNetworkInfo, WireguardNetworkDevice}, - error::ModelError, - wireguard::WireguardNetworkError, - }, - Device, GatewayEvent, Id, WireguardNetwork, +use crate::db::models::{ + device::{Device, DeviceInfo, DeviceNetworkInfo, WireguardNetworkDevice}, + error::ModelError, + wireguard::{ChangeEvent, WireguardNetwork, WireguardNetworkError}, }; // How long to sleep between loop iterations @@ -39,22 +36,13 @@ pub enum PeerDisconnectError { /// Run with a specified frequency and disconnect all inactive peers in MFA-protected locations. pub async fn run_periodic_peer_disconnect( pool: PgPool, - wireguard_tx: Sender, + events_tx: Sender, ) -> Result<(), PeerDisconnectError> { info!("Starting periodic disconnect of inactive devices in MFA-protected locations"); loop { debug!("Starting periodic inactive device disconnect"); - // get all MFA-protected locations - let locations = query_as!( - WireguardNetwork::, - "SELECT \ - id, name, address, port, pubkey, prvkey, endpoint, dns, allowed_ips, \ - connected_at, mfa_enabled, keepalive_interval, peer_disconnect_threshold \ - FROM wireguard_network WHERE mfa_enabled = true", - ) - .fetch_all(&pool) - .await?; + let locations = WireguardNetwork::all_mfa_enabled(&pool).await?; // loop over all locations for location in locations { @@ -62,20 +50,20 @@ pub async fn run_periodic_peer_disconnect( let devices = query_as!( Device, "WITH stats AS ( \ - SELECT DISTINCT ON (device_id) device_id, endpoint, latest_handshake \ - FROM wireguard_peer_stats \ - WHERE network = $1 \ - ORDER BY device_id, collected_at DESC \ - ) \ + SELECT DISTINCT ON (device_id) device_id, endpoint, latest_handshake \ + FROM wireguard_peer_stats \ + WHERE network = $1 \ + ORDER BY device_id, collected_at DESC \ + ) \ SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created \ FROM device d \ JOIN wireguard_network_device wnd ON wnd.device_id = d.id \ LEFT JOIN stats on d.id = stats.device_id \ WHERE wnd.wireguard_network_id = $1 AND wnd.is_authorized = true AND \ - (wnd.authorized_at IS NULL OR (NOW() - wnd.authorized_at) > $2 * interval '1 second') AND \ - (stats.latest_handshake IS NULL OR (NOW() - stats.latest_handshake) > $2 * interval '1 second')", + (wnd.authorized_at IS NULL OR (NOW() - wnd.authorized_at) > $2 * interval '1s') AND \ + (stats.latest_handshake IS NULL OR (NOW() - stats.latest_handshake) > $2 * interval '1s')", location.id, - f64::from(location.peer_disconnect_threshold) + f64::from(location.peer_disconnect_threshold) ) .fetch_all(&pool) .await?; @@ -107,8 +95,8 @@ pub async fn run_periodic_peer_disconnect( is_authorized: device_network_config.is_authorized, }], }; - let event = GatewayEvent::DeviceDeleted(device_info); - wireguard_tx.send(event).map_err(|err| { + let event = ChangeEvent::DeviceDeleted(device_info); + events_tx.send(event).map_err(|err| { error!("Error sending WireGuard event: {err}"); PeerDisconnectError::EventError(err.to_string()) })?; diff --git a/src/wireguard_stats_purge.rs b/src/wireguard_stats_purge.rs index 3a9580c2d..568b2bde0 100644 --- a/src/wireguard_stats_purge.rs +++ b/src/wireguard_stats_purge.rs @@ -1,11 +1,11 @@ use std::time::Duration; -use chrono::{DateTime, Duration as ChronoDuration, NaiveDateTime, Utc}; +use chrono::{DateTime, NaiveDateTime, TimeDelta, Utc}; use humantime::format_duration; use sqlx::{query, query_scalar, Error as SqlxError, PgExecutor, PgPool}; use tokio::time::sleep; -use crate::db::WireguardPeerStats; +use crate::db::models::wireguard::WireguardPeerStats; // How long to sleep between loop iterations const PURGE_LOOP_SLEEP_SECONDS: u64 = 300; // 5 minutes @@ -26,7 +26,7 @@ impl WireguardPeerStats { ); let threshold = (Utc::now() - - ChronoDuration::from_std(stats_purge_threshold).expect("Failed to parse duration")) + - TimeDelta::from_std(stats_purge_threshold).expect("Failed to parse duration")) .naive_utc(); let result = query!( "DELETE FROM wireguard_peer_stats \ @@ -87,8 +87,17 @@ impl WireguardPeerStats { E: PgExecutor<'e>, { debug!("Recording successful stats purge in DB"); - query!("INSERT INTO wireguard_stats_purge (started_at, finished_at, removal_threshold, records_removed) VALUES ($1, $2, $3, $4)", - start.naive_utc(), end.naive_utc(), removal_threshold, records_removed).execute(executor).await?; + query!( + "INSERT INTO wireguard_stats_purge \ + (started_at, finished_at, removal_threshold, records_removed) \ + VALUES ($1, $2, $3, $4)", + start.naive_utc(), + end.naive_utc(), + removal_threshold, + records_removed + ) + .execute(executor) + .await?; Ok(()) } } @@ -117,7 +126,7 @@ pub async fn run_periodic_stats_purge( match WireguardPeerStats::purge_old_stats(&pool, stats_purge_threshold).await { Ok(()) => { let next_purge_timestamp = (Utc::now() - + ChronoDuration::from_std(stats_purge_frequency) + + TimeDelta::from_std(stats_purge_frequency) .expect("Failed to parse duration")) .naive_utc(); info!( diff --git a/tests/auth.rs b/tests/auth.rs index ebcb932b1..94f5a8669 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -7,7 +7,12 @@ use claims::assert_err; use common::fetch_user_details; use defguard::{ auth::{TOTP_CODE_DIGITS, TOTP_CODE_VALIDITY_PERIOD}, - db::{models::wallet::keccak256, MFAInfo, MFAMethod, Settings, User, UserDetails, Wallet}, + db::models::{ + settings::Settings, + user::{MFAMethod, User}, + wallet::{keccak256, Wallet}, + MFAInfo, UserDetails, + }, handlers::{Auth, AuthCode, AuthResponse, AuthTotp, WalletChallenge}, hex::to_lower_hex, secret::SecretString, diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 394bedce5..2bc9b9e23 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -6,9 +6,13 @@ use defguard::{ auth::failed_login::FailedLoginMap, build_webapp, config::DefGuardConfig, - db::{init_db, AppEvent, GatewayEvent, Id, User, UserDetails}, + db::{ + init_db, + models::{user::User, webhook::AppEvent, wireguard::ChangeEvent, UserDetails}, + Id, + }, enterprise::license::{set_cached_license, License}, - grpc::{GatewayMap, WorkerState}, + grpc::WorkerState, headers::create_user_agent_parser, mail::Mail, SERVER_CONFIG, @@ -82,7 +86,7 @@ async fn initialize_users(pool: &PgPool, config: &DefGuardConfig) { pub struct ClientState { pub pool: PgPool, pub worker_state: Arc>, - pub wireguard_rx: Receiver, + pub events_rx: Receiver, pub mail_rx: UnboundedReceiver, pub failed_logins: Arc>, pub test_user: User, @@ -93,7 +97,7 @@ impl ClientState { pub fn new( pool: PgPool, worker_state: Arc>, - wireguard_rx: Receiver, + events_rx: Receiver, mail_rx: UnboundedReceiver, failed_logins: Arc>, test_user: User, @@ -102,7 +106,7 @@ impl ClientState { Self { pool, worker_state, - wireguard_rx, + events_rx, mail_rx, failed_logins, test_user, @@ -114,9 +118,8 @@ impl ClientState { pub async fn make_base_client(pool: PgPool, config: DefGuardConfig) -> (TestClient, ClientState) { let (tx, rx) = unbounded_channel::(); let worker_state = Arc::new(Mutex::new(WorkerState::new(tx.clone()))); - let (wg_tx, wg_rx) = broadcast::channel::(16); + let (wg_tx, wg_rx) = broadcast::channel::(16); let (mail_tx, mail_rx) = unbounded_channel::(); - let gateway_state = Arc::new(Mutex::new(GatewayMap::new())); let failed_logins = FailedLoginMap::new(); let failed_logins = Arc::new(Mutex::new(failed_logins)); @@ -163,7 +166,6 @@ pub async fn make_base_client(pool: PgPool, config: DefGuardConfig) -> (TestClie wg_tx, mail_tx, worker_state, - gateway_state, pool, user_agent_parser, failed_logins, diff --git a/tests/forward_auth.rs b/tests/forward_auth.rs index f5edd5e8c..6d43b64b8 100644 --- a/tests/forward_auth.rs +++ b/tests/forward_auth.rs @@ -1,6 +1,6 @@ mod common; -use defguard::{db::Wallet, handlers::Auth, SERVER_CONFIG}; +use defguard::{db::models::wallet::Wallet, handlers::Auth, SERVER_CONFIG}; use reqwest::StatusCode; use self::common::{client::TestClient, make_test_client, X_FORWARDED_HOST, X_FORWARDED_URI}; diff --git a/tests/oauth.rs b/tests/oauth.rs index bbe5ac5b3..2bbcc975a 100644 --- a/tests/oauth.rs +++ b/tests/oauth.rs @@ -5,10 +5,11 @@ use std::borrow::Cow; use defguard::{ db::{ models::{ + oauth2authorizedapp::OAuth2AuthorizedApp, oauth2client::{OAuth2Client, OAuth2ClientSafe}, NewOpenIDClient, }, - Id, OAuth2AuthorizedApp, + Id, }, handlers::Auth, }; diff --git a/tests/openid_login.rs b/tests/openid_login.rs index beb62c7e5..52dbf5bd3 100644 --- a/tests/openid_login.rs +++ b/tests/openid_login.rs @@ -1,4 +1,4 @@ -use chrono::{Duration, Utc}; +use chrono::{TimeDelta, Utc}; use defguard::{ config::DefGuardConfig, enterprise::{ @@ -78,7 +78,7 @@ async fn test_openid_providers() { let new_license = License { customer_id: "test".to_string(), subscription: false, - valid_until: Some(Utc::now() - Duration::days(1)), + valid_until: Some(Utc::now() - TimeDelta::days(1)), }; set_cached_license(Some(new_license)); let response = client.get("/api/v1/openid/auth_info").send().await; diff --git a/tests/user.rs b/tests/user.rs index 66d6730b2..a95c9e7e3 100644 --- a/tests/user.rs +++ b/tests/user.rs @@ -2,8 +2,11 @@ mod common; use defguard::{ db::{ - models::{oauth2client::OAuth2Client, wallet::keccak256, NewOpenIDClient}, - AddDevice, Id, UserInfo, + models::{ + device::AddDevice, oauth2client::OAuth2Client, wallet::keccak256, NewOpenIDClient, + UserInfo, + }, + Id, }, handlers::{AddUserData, Auth, PasswordChange, PasswordChangeSelf, Username, WalletChallenge}, hex::to_lower_hex, diff --git a/tests/webhook.rs b/tests/webhook.rs index 42ec6876a..c4b151b2f 100644 --- a/tests/webhook.rs +++ b/tests/webhook.rs @@ -1,7 +1,7 @@ mod common; use defguard::{ - db::{Id, NoId, WebHook}, + db::{models::webhook::WebHook, Id, NoId}, handlers::Auth, }; use reqwest::StatusCode; diff --git a/tests/wireguard.rs b/tests/wireguard.rs index a3cd2814f..6047604df 100644 --- a/tests/wireguard.rs +++ b/tests/wireguard.rs @@ -3,10 +3,13 @@ mod common; use defguard::{ db::{ models::{ - device::WireguardNetworkDevice, - wireguard::{DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL}, + device::{Device, WireguardNetworkDevice}, + wireguard::{ + ChangeEvent, WireguardNetwork, DEFAULT_DISCONNECT_THRESHOLD, + DEFAULT_KEEPALIVE_INTERVAL, + }, }, - Device, GatewayEvent, Id, WireguardNetwork, + Id, }, handlers::{wireguard::WireguardNetworkData, Auth, GroupInfo}, }; @@ -35,7 +38,7 @@ fn make_network() -> Value { async fn test_network() { let (client, client_state) = make_test_client().await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -51,7 +54,7 @@ async fn test_network() { let network: WireguardNetwork = response.json().await; assert_eq!(network.name, "network"); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // check vpn locations for `admin` group let response = client.get("/api/v1/group/admin").send().await; @@ -78,7 +81,7 @@ async fn test_network() { .await; assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkModified(..)); + assert_matches!(event, ChangeEvent::NetworkModified(..)); // check vpn locations for `admin` group let response = client.get("/api/v1/group/admin").send().await; @@ -110,14 +113,14 @@ async fn test_network() { .await; assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkDeleted(..)); + assert_matches!(event, ChangeEvent::NetworkDeleted(..)); } #[tokio::test] async fn test_device() { let (client, client_state) = make_test_client().await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -131,7 +134,7 @@ async fn test_device() { .await; assert_eq!(response.status(), StatusCode::CREATED); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // network details let response = client.get("/api/v1/network/1").send().await; @@ -150,7 +153,7 @@ async fn test_device() { .await; assert_eq!(response.status(), StatusCode::CREATED); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::DeviceCreated(..)); + assert_matches!(event, ChangeEvent::DeviceCreated(..)); // an IP was assigned for new device let network_devices = WireguardNetworkDevice::find_by_device(&client_state.pool, 1) @@ -169,7 +172,7 @@ async fn test_device() { .send() .await; assert_eq!(response.status(), StatusCode::CREATED); - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::NetworkCreated(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::NetworkCreated(..)); // an IP was assigned for an existing device let network_devices = WireguardNetworkDevice::find_by_device(&client_state.pool, 1) @@ -215,7 +218,7 @@ async fn test_device() { .await; assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::DeviceModified(..)); + assert_matches!(event, ChangeEvent::DeviceModified(..)); // device details let response = client @@ -257,7 +260,7 @@ async fn test_device() { .await; assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkDeleted(..)); + assert_matches!(event, ChangeEvent::NetworkDeleted(..)); // delete device let response = client @@ -266,7 +269,7 @@ async fn test_device() { .await; assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::DeviceDeleted(..)); + assert_matches!(event, ChangeEvent::DeviceDeleted(..)); let response = client.get("/api/v1/device").json(&device).send().await; assert_eq!(response.status(), StatusCode::OK); @@ -421,7 +424,7 @@ async fn test_device_permissions() { async fn test_device_pubkey() { let (client, client_state) = make_test_client().await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -435,7 +438,7 @@ async fn test_device_pubkey() { .await; assert_eq!(response.status(), StatusCode::CREATED); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // network details let response = client.get("/api/v1/network/1").send().await; diff --git a/tests/wireguard_network_allowed_groups.rs b/tests/wireguard_network_allowed_groups.rs index c5e93e471..29edd0ba2 100644 --- a/tests/wireguard_network_allowed_groups.rs +++ b/tests/wireguard_network_allowed_groups.rs @@ -2,7 +2,15 @@ mod common; use claims::assert_err; use defguard::{ - db::{Device, GatewayEvent, Group, Id, User, WireguardNetwork}, + db::{ + models::{ + device::Device, + group::Group, + user::User, + wireguard::{ChangeEvent, WireguardNetwork}, + }, + Id, + }, handlers::{wireguard::ImportedNetworkData, Auth}, }; use matches::assert_matches; @@ -112,7 +120,7 @@ async fn test_create_new_network() { let (client, client_state) = make_test_client().await; let (_users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -139,7 +147,7 @@ async fn test_create_new_network() { let network: WireguardNetwork = response.json().await; assert_eq!(network.name, "network"); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); assert_err!(wg_rx.try_recv()); // network configuration was created only for admin and allowed user @@ -154,7 +162,7 @@ async fn test_modify_network() { let (client, client_state) = make_test_client().await; let (_users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -181,7 +189,7 @@ async fn test_modify_network() { let network: WireguardNetwork = response.json().await; assert_eq!(network.name, "network"); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // network configuration was created for all devices let peers = network.get_peers(&client_state.pool).await.unwrap(); @@ -209,7 +217,7 @@ async fn test_modify_network() { .send() .await; assert_eq!(response.status(), StatusCode::OK); - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::NetworkModified(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::NetworkModified(..)); let new_peers = network.get_peers(&client_state.pool).await.unwrap(); assert_eq!(new_peers.len(), 2); @@ -234,7 +242,7 @@ async fn test_modify_network() { .send() .await; assert_eq!(response.status(), StatusCode::OK); - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::NetworkModified(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::NetworkModified(..)); let new_peers = network.get_peers(&client_state.pool).await.unwrap(); assert_eq!(new_peers.len(), 3); @@ -260,7 +268,7 @@ async fn test_modify_network() { .send() .await; assert_eq!(response.status(), StatusCode::OK); - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::NetworkModified(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::NetworkModified(..)); let new_peers = network.get_peers(&client_state.pool).await.unwrap(); assert_eq!(new_peers.len(), 2); @@ -285,7 +293,7 @@ async fn test_modify_network() { .send() .await; assert_eq!(response.status(), StatusCode::OK); - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::NetworkModified(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::NetworkModified(..)); let new_peers = network.get_peers(&client_state.pool).await.unwrap(); assert_eq!(new_peers.len(), 4); @@ -303,7 +311,7 @@ async fn test_import_network_existing_devices() { let (client, client_state) = make_test_client().await; let (_users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -358,10 +366,10 @@ async fn test_import_network_existing_devices() { assert_eq!(peers[1].pubkey, devices[1].wireguard_pubkey); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // network config was only created for one of the existing devices and the admin device - let GatewayEvent::DeviceModified(device_info) = wg_rx.try_recv().unwrap() else { + let ChangeEvent::DeviceModified(device_info) = wg_rx.try_recv().unwrap() else { panic!() }; assert_eq!(device_info.device.id, devices[1].id); @@ -372,7 +380,7 @@ async fn test_import_network_existing_devices() { peers[1].allowed_ips[0] ); - let GatewayEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { + let ChangeEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { panic!() }; assert_eq!(device_info.device.id, devices[0].id); @@ -391,7 +399,7 @@ async fn test_import_mapping_devices() { let (client, client_state) = make_test_client().await; let (users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -462,7 +470,7 @@ PersistentKeepalive = 300 assert_eq!(peers[3].pubkey, mapped_devices[1].wireguard_pubkey); // assert events - let GatewayEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { + let ChangeEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { panic!() }; assert_eq!( @@ -476,7 +484,7 @@ PersistentKeepalive = 300 mapped_devices[0].wireguard_ip ); - let GatewayEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { + let ChangeEvent::DeviceCreated(device_info) = wg_rx.try_recv().unwrap() else { panic!() }; assert_eq!( @@ -499,7 +507,7 @@ async fn test_modify_user() { let (client, client_state) = make_test_client().await; let (_users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -526,7 +534,7 @@ async fn test_modify_user() { let network: WireguardNetwork = response.json().await; assert_eq!(network.name, "network"); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); assert_err!(wg_rx.try_recv()); // network configuration was created only for admin and allowed user @@ -546,7 +554,7 @@ async fn test_modify_user() { assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::DeviceDeleted(..)); + assert_matches!(event, ChangeEvent::DeviceDeleted(..)); assert_err!(wg_rx.try_recv()); let peers = network.get_peers(&client_state.pool).await.unwrap(); @@ -580,7 +588,7 @@ async fn test_modify_user() { assert_eq!(response.status(), StatusCode::OK); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::DeviceCreated(..)); + assert_matches!(event, ChangeEvent::DeviceCreated(..)); assert_err!(wg_rx.try_recv()); let peers = network.get_peers(&client_state.pool).await.unwrap(); @@ -594,7 +602,7 @@ async fn test_delete_only_allowed_group() { let (client, client_state) = make_test_client().await; let (_users, devices) = setup_test_users(&client_state.pool).await; - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -621,7 +629,7 @@ async fn test_delete_only_allowed_group() { let network: WireguardNetwork = response.json().await; assert_eq!(network.name, "network"); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); let peers = network.get_peers(&client_state.pool).await.unwrap(); assert_eq!(peers.len(), 2); diff --git a/tests/wireguard_network_import.rs b/tests/wireguard_network_import.rs index d5e43656f..c0cfd775d 100644 --- a/tests/wireguard_network_import.rs +++ b/tests/wireguard_network_import.rs @@ -1,12 +1,11 @@ mod common; use defguard::{ - db::{ - models::{ - device::UserDevice, - wireguard::{DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL}, + db::models::{ + device::{Device, UserDevice}, + wireguard::{ + ChangeEvent, WireguardNetwork, DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, }, - Device, GatewayEvent, WireguardNetwork, }, handlers::{wireguard::ImportedNetworkData, Auth}, }; @@ -55,8 +54,7 @@ async fn test_config_import() { false, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, - ) - .unwrap(); + ); initial_network.save(&pool).await.unwrap(); // add existing devices @@ -90,7 +88,7 @@ async fn test_config_import() { transaction.commit().await.unwrap(); - let mut wg_rx = client_state.wireguard_rx; + let mut wg_rx = client_state.events_rx; let auth = Auth::new("admin", "pass123"); let response = &client.post("/api/v1/auth").json(&auth).send().await; @@ -121,11 +119,11 @@ async fn test_config_import() { assert_eq!(network.allowed_ips, vec!["10.0.0.0/24".parse().unwrap()]); assert_eq!(network.connected_at, None); let event = wg_rx.try_recv().unwrap(); - assert_matches!(event, GatewayEvent::NetworkCreated(..)); + assert_matches!(event, ChangeEvent::NetworkCreated(..)); // existing devices assertion // imported config for an existing device - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::DeviceModified(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::DeviceModified(..)); let user_device_1 = UserDevice::from_device(&pool, device_1) .await .unwrap() @@ -133,7 +131,7 @@ async fn test_config_import() { assert_eq!(user_device_1.networks.len(), 2); assert_eq!(user_device_1.networks[1].device_wireguard_ip, "10.0.0.12"); // generated IP for other existing device - assert_matches!(wg_rx.try_recv().unwrap(), GatewayEvent::DeviceCreated(..)); + assert_matches!(wg_rx.try_recv().unwrap(), ChangeEvent::DeviceCreated(..)); let user_device_2 = UserDevice::from_device(&pool, device_2) .await .unwrap() @@ -179,7 +177,7 @@ async fn test_config_import() { // assert events let event = wg_rx.try_recv().unwrap(); match event { - GatewayEvent::DeviceCreated(device_info) => { + ChangeEvent::DeviceCreated(device_info) => { assert_eq!(device_info.device.name, "device_1"); } _ => unreachable!("Invalid event type received"), @@ -187,7 +185,7 @@ async fn test_config_import() { let event = wg_rx.try_recv().unwrap(); match event { - GatewayEvent::DeviceCreated(device_info) => { + ChangeEvent::DeviceCreated(device_info) => { assert_eq!(device_info.device.name, "device_2"); } _ => unreachable!("Invalid event type received"), diff --git a/tests/wireguard_network_stats.rs b/tests/wireguard_network_stats.rs index 11f5f7654..f882d9b13 100644 --- a/tests/wireguard_network_stats.rs +++ b/tests/wireguard_network_stats.rs @@ -1,12 +1,16 @@ mod common; -use chrono::{Datelike, Duration, NaiveDate, SubsecRound, Timelike, Utc}; +use chrono::{Datelike, NaiveDate, SubsecRound, TimeDelta, Timelike, Utc}; use defguard::{ db::{ - models::wireguard::{ - WireguardDeviceTransferRow, WireguardNetworkStats, WireguardUserStatsRow, + models::{ + device::Device, + wireguard::{ + WireguardDeviceTransferRow, WireguardNetworkStats, WireguardPeerStats, + WireguardUserStatsRow, + }, }, - Device, Id, NoId, WireguardPeerStats, + Id, NoId, }, handlers::Auth, }; @@ -84,7 +88,7 @@ async fn test_stats() { // empty stats let now = Utc::now().naive_utc(); - let hour_ago = now - Duration::hours(1); + let hour_ago = now - TimeDelta::hours(1); let response = client .get(format!( "/api/v1/network/1/stats/users?from={}", @@ -103,12 +107,12 @@ async fn test_stats() { WireguardPeerStats { id: NoId, device_id: device.id, - collected_at: now - Duration::minutes(i), + collected_at: now - TimeDelta::minutes(i), network: 1, endpoint: Some("11.22.33.44".into()), upload: (samples - i) * 10 * (d as i64 + 1), download: (samples - i) * 20 * (d as i64 + 1), - latest_handshake: now - Duration::minutes(i * 10), + latest_handshake: now - TimeDelta::minutes(i * 10), allowed_ips: Some("10.1.1.0/24".into()), } .save(&pool) @@ -220,7 +224,7 @@ async fn test_stats() { ); // hourly aggregation - let ten_hours_ago = now - Duration::hours(10); + let ten_hours_ago = now - TimeDelta::hours(10); let ten_hours_samples = 10 * 60 + 1; let response = client .get(format!( diff --git a/web/package.json b/web/package.json index c7ed2738c..e9bc98d25 100644 --- a/web/package.json +++ b/web/package.json @@ -41,105 +41,105 @@ } }, "dependencies": { - "@floating-ui/react": "^0.26.7", + "@floating-ui/react": "^0.26.25", "@github/webauthn-json": "^2.1.1", - "@hookform/resolvers": "^3.3.4", - "@ladle/react": "^4.0.2", + "@hookform/resolvers": "^3.9.1", + "@ladle/react": "^4.1.2", "@metamask/detect-provider": "^2.0.0", "@react-rxjs/core": "^0.10.7", - "@stablelib/base64": "^1.0.1", - "@stablelib/x25519": "^1.0.3", - "@tanstack/query-core": "^4.32.6", - "@tanstack/react-query": "^4.32.6", + "@stablelib/base64": "^2.0.0", + "@stablelib/x25519": "^2.0.0", + "@tanstack/query-core": "^4.36.1", + "@tanstack/react-query": "^4.36.1", "@tanstack/react-virtual": "3.0.0-beta.9", "@tanstack/virtual-core": "3.0.0-beta.9", - "@tauri-apps/api": "^1.5.3", + "@tauri-apps/api": "^1.6.0", "@types/react-virtualized-auto-sizer": "^1.0.4", "@types/react-window": "^1.8.8", - "@vitejs/plugin-legacy": "^5.3.0", - "@vitejs/plugin-react": "^4.2.1", - "axios": "^1.6.7", - "byte-size": "^8.1.1", + "@vitejs/plugin-legacy": "^5.4.3", + "@vitejs/plugin-react": "^4.3.3", + "axios": "^1.7.7", + "byte-size": "^9.0.0", "classnames": "^2.5.1", - "dayjs": "^1.11.10", + "dayjs": "^1.11.13", "detect-browser": "^5.3.0", - "ethers": "^6.10.0", + "ethers": "^6.13.4", "events": "^3.3.0", "fast-deep-equal": "^3.1.3", "file-saver": "^2.0.5", - "framer-motion": "^11.0.3", + "framer-motion": "^11.11.10", "get-text-width": "^1.0.3", "hex-rgb": "^5.0.0", - "html-react-parser": "^5.1.1", - "itertools": "^2.2.3", + "html-react-parser": "^5.1.18", + "itertools": "^2.3.2", "lodash-es": "^4.17.21", - "numbro": "^2.4.0", - "qrcode": "^1.5.3", - "radash": "^11.0.0", - "react": "^18.2.0", + "numbro": "^2.5.0", + "qrcode": "^1.5.4", + "radash": "^12.1.0", + "react": "^18.3.1", "react-click-away-listener": "^2.2.3", - "react-dom": "^18.2.0", - "react-hook-form": "^7.49.3", + "react-dom": "^18.3.1", + "react-hook-form": "^7.53.1", "react-idle-timer": "^5.7.2", - "react-is": "^18.2.0", - "react-loading-skeleton": "^3.3.1", + "react-is": "^18.3.1", + "react-loading-skeleton": "^3.5.0", "react-markdown": "^9.0.1", - "react-qr-code": "^2.0.12", - "react-router": "^6.21.3", - "react-router-dom": "^6.21.3", - "react-virtualized-auto-sizer": "^1.0.21", + "react-qr-code": "^2.0.15", + "react-router": "^6.27.0", + "react-router-dom": "^6.27.0", + "react-virtualized-auto-sizer": "^1.0.24", "react-window": "^1.8.10", - "recharts": "^2.10.4", - "rollup": "^4.9.6", + "recharts": "^2.13.0", + "rollup": "npm:@rollup/wasm-node@^4.24.2", "rxjs": "^7.8.1", - "terser": "^5.27.0", + "terser": "^5.36.0", "typesafe-i18n": "^5.26.2", "use-breakpoint": "^4.0.1", - "zod": "^3.22.4", - "zustand": "^4.5.0" + "zod": "^3.23.8", + "zustand": "^4.5.5" }, "devDependencies": { - "@babel/core": "^7.23.9", - "@csstools/css-parser-algorithms": "^2.5.0", - "@csstools/css-tokenizer": "^2.2.3", + "@babel/core": "^7.26.0", + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1", "@hookform/devtools": "^4.3.1", "@svgr/cli": "^8.1.0", - "@tanstack/react-query-devtools": "^4.32.6", + "@tanstack/react-query-devtools": "^4.36.1", "@types/byte-size": "^8.1.2", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.7", - "@types/react": "^18.2.48", - "@types/react-dom": "^18.2.18", + "@types/node": "^20.17.2", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", "@types/react-router-dom": "^5.3.3", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", - "@vitejs/plugin-react-swc": "^3.5.0", - "autoprefixer": "^10.4.17", - "concurrently": "^8.2.2", - "esbuild": "^0.19.12", - "eslint": "^8.56.0", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "@vitejs/plugin-react-swc": "^3.7.1", + "autoprefixer": "^10.4.20", + "concurrently": "^9.0.1", + "esbuild": "^0.24.0", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.5", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.2", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.14", "eslint-plugin-simple-import-sort": "^10.0.0", - "postcss": "^8.4.33", - "prettier": "^3.2.4", + "postcss": "^8.4.47", + "prettier": "^3.3.3", "prop-types": "^15.8.1", - "rollup-plugin-preserve-directives": "^0.3.1", - "sass": "^1.70.0", + "rollup-plugin-preserve-directives": "^0.4.0", + "sass": "^1.80.4", "standard-version": "^9.5.0", "stylelint-config-prettier-scss": "^1.0.0", - "stylelint-config-standard-scss": "^13.0.0", - "stylelint-scss": "^6.1.0", - "typedoc": "^0.25.7", + "stylelint-config-standard-scss": "^13.1.0", + "stylelint-scss": "^6.8.1", + "typedoc": "^0.25.13", "typescript": "~5.3.3", "typescript-eslint-language-service": "^5.0.5", - "vite": "^5.0.12", + "vite": "^5.4.10", "vite-plugin-eslint": "^1.8.1", "vite-plugin-package-version": "^1.1.0" }, diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index ba7fe4b1a..ffbbbd9c2 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -12,44 +12,44 @@ importers: .: dependencies: '@floating-ui/react': - specifier: ^0.26.7 - version: 0.26.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^0.26.25 + version: 0.26.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@github/webauthn-json': specifier: ^2.1.1 version: 2.1.1 '@hookform/resolvers': - specifier: ^3.3.4 - version: 3.3.4(react-hook-form@7.49.3(react@18.2.0)) + specifier: ^3.9.1 + version: 3.9.1(react-hook-form@7.53.1(react@18.3.1)) '@ladle/react': - specifier: ^4.0.2 - version: 4.0.2(@types/node@20.11.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.70.0)(terser@5.27.0)(typescript@5.3.3) + specifier: ^4.1.2 + version: 4.1.2(@types/node@20.17.2)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)(terser@5.36.0)(typescript@5.3.3) '@metamask/detect-provider': specifier: ^2.0.0 version: 2.0.0 '@react-rxjs/core': specifier: ^0.10.7 - version: 0.10.7(react@18.2.0)(rxjs@7.8.1) + version: 0.10.7(react@18.3.1)(rxjs@7.8.1) '@stablelib/base64': - specifier: ^1.0.1 - version: 1.0.1 + specifier: ^2.0.0 + version: 2.0.0 '@stablelib/x25519': - specifier: ^1.0.3 - version: 1.0.3 + specifier: ^2.0.0 + version: 2.0.0 '@tanstack/query-core': - specifier: ^4.32.6 + specifier: ^4.36.1 version: 4.36.1 '@tanstack/react-query': - specifier: ^4.32.6 - version: 4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^4.36.1 + version: 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-virtual': specifier: 3.0.0-beta.9 - version: 3.0.0-beta.9(react@18.2.0) + version: 3.0.0-beta.9(react@18.3.1) '@tanstack/virtual-core': specifier: 3.0.0-beta.9 version: 3.0.0-beta.9 '@tauri-apps/api': - specifier: ^1.5.3 - version: 1.5.3 + specifier: ^1.6.0 + version: 1.6.0 '@types/react-virtualized-auto-sizer': specifier: ^1.0.4 version: 1.0.4 @@ -57,29 +57,29 @@ importers: specifier: ^1.8.8 version: 1.8.8 '@vitejs/plugin-legacy': - specifier: ^5.3.0 - version: 5.3.0(esbuild@0.19.12)(terser@5.27.0)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + specifier: ^5.4.3 + version: 5.4.3(terser@5.36.0)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) '@vitejs/plugin-react': - specifier: ^4.2.1 - version: 4.2.1(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + specifier: ^4.3.3 + version: 4.3.3(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) axios: - specifier: ^1.6.7 - version: 1.6.7 + specifier: ^1.7.7 + version: 1.7.7 byte-size: - specifier: ^8.1.1 - version: 8.1.1 + specifier: ^9.0.0 + version: 9.0.0 classnames: specifier: ^2.5.1 version: 2.5.1 dayjs: - specifier: ^1.11.10 - version: 1.11.10 + specifier: ^1.11.13 + version: 1.11.13 detect-browser: specifier: ^5.3.0 version: 5.3.0 ethers: - specifier: ^6.10.0 - version: 6.10.0 + specifier: ^6.13.4 + version: 6.13.4 events: specifier: ^3.3.0 version: 3.3.0 @@ -90,8 +90,8 @@ importers: specifier: ^2.0.5 version: 2.0.5 framer-motion: - specifier: ^11.0.3 - version: 11.0.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^11.11.10 + version: 11.11.10(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) get-text-width: specifier: ^1.0.3 version: 1.0.3 @@ -99,105 +99,105 @@ importers: specifier: ^5.0.0 version: 5.0.0 html-react-parser: - specifier: ^5.1.1 - version: 5.1.1(react@18.2.0) + specifier: ^5.1.18 + version: 5.1.18(@types/react@18.3.12)(react@18.3.1) itertools: - specifier: ^2.2.3 - version: 2.2.3 + specifier: ^2.3.2 + version: 2.3.2 lodash-es: specifier: ^4.17.21 version: 4.17.21 numbro: - specifier: ^2.4.0 - version: 2.4.0 + specifier: ^2.5.0 + version: 2.5.0 qrcode: - specifier: ^1.5.3 - version: 1.5.3 + specifier: ^1.5.4 + version: 1.5.4 radash: - specifier: ^11.0.0 - version: 11.0.0 + specifier: ^12.1.0 + version: 12.1.0 react: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-click-away-listener: specifier: ^2.2.3 - version: 2.2.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-dom: - specifier: ^18.2.0 - version: 18.2.0(react@18.2.0) + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) react-hook-form: - specifier: ^7.49.3 - version: 7.49.3(react@18.2.0) + specifier: ^7.53.1 + version: 7.53.1(react@18.3.1) react-idle-timer: specifier: ^5.7.2 - version: 5.7.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 5.7.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-is: - specifier: ^18.2.0 - version: 18.2.0 + specifier: ^18.3.1 + version: 18.3.1 react-loading-skeleton: - specifier: ^3.3.1 - version: 3.3.1(react@18.2.0) + specifier: ^3.5.0 + version: 3.5.0(react@18.3.1) react-markdown: specifier: ^9.0.1 - version: 9.0.1(@types/react@18.2.48)(react@18.2.0) + version: 9.0.1(@types/react@18.3.12)(react@18.3.1) react-qr-code: - specifier: ^2.0.12 - version: 2.0.12(react@18.2.0) + specifier: ^2.0.15 + version: 2.0.15(react@18.3.1) react-router: - specifier: ^6.21.3 - version: 6.21.3(react@18.2.0) + specifier: ^6.27.0 + version: 6.27.0(react@18.3.1) react-router-dom: - specifier: ^6.21.3 - version: 6.21.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^6.27.0 + version: 6.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-virtualized-auto-sizer: - specifier: ^1.0.21 - version: 1.0.21(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^1.0.24 + version: 1.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-window: specifier: ^1.8.10 - version: 1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recharts: - specifier: ^2.10.4 - version: 2.10.4(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^2.13.0 + version: 2.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) rollup: - specifier: npm:@rollup/wasm-node - version: '@rollup/wasm-node@4.24.0' + specifier: npm:@rollup/wasm-node@^4.24.2 + version: '@rollup/wasm-node@4.24.2' rxjs: specifier: ^7.8.1 version: 7.8.1 terser: - specifier: ^5.27.0 - version: 5.27.0 + specifier: ^5.36.0 + version: 5.36.0 typesafe-i18n: specifier: ^5.26.2 version: 5.26.2(typescript@5.3.3) use-breakpoint: specifier: ^4.0.1 - version: 4.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) zod: - specifier: ^3.22.4 - version: 3.22.4 + specifier: ^3.23.8 + version: 3.23.8 zustand: - specifier: ^4.5.0 - version: 4.5.0(@types/react@18.2.48)(react@18.2.0) + specifier: ^4.5.5 + version: 4.5.5(@types/react@18.3.12)(react@18.3.1) devDependencies: '@babel/core': - specifier: ^7.23.9 - version: 7.23.9 + specifier: ^7.26.0 + version: 7.26.0 '@csstools/css-parser-algorithms': - specifier: ^2.5.0 - version: 2.5.0(@csstools/css-tokenizer@2.2.3) + specifier: ^2.7.1 + version: 2.7.1(@csstools/css-tokenizer@2.4.1) '@csstools/css-tokenizer': - specifier: ^2.2.3 - version: 2.2.3 + specifier: ^2.4.1 + version: 2.4.1 '@hookform/devtools': specifier: ^4.3.1 - version: 4.3.1(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 4.3.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@svgr/cli': specifier: ^8.1.0 version: 8.1.0(typescript@5.3.3) '@tanstack/react-query-devtools': - specifier: ^4.32.6 - version: 4.36.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: ^4.36.1 + version: 4.36.1(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/byte-size': specifier: ^8.1.2 version: 8.1.2 @@ -208,77 +208,77 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/node': - specifier: ^20.11.7 - version: 20.11.7 + specifier: ^20.17.2 + version: 20.17.2 '@types/react': - specifier: ^18.2.48 - version: 18.2.48 + specifier: ^18.3.12 + version: 18.3.12 '@types/react-dom': - specifier: ^18.2.18 - version: 18.2.18 + specifier: ^18.3.1 + version: 18.3.1 '@types/react-router-dom': specifier: ^5.3.3 version: 5.3.3 '@typescript-eslint/eslint-plugin': - specifier: ^6.19.1 - version: 6.19.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3) '@typescript-eslint/parser': - specifier: ^6.19.1 - version: 6.19.1(eslint@8.56.0)(typescript@5.3.3) + specifier: ^6.21.0 + version: 6.21.0(eslint@8.57.1)(typescript@5.3.3) '@vitejs/plugin-react-swc': - specifier: ^3.5.0 - version: 3.5.0(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + specifier: ^3.7.1 + version: 3.7.1(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) autoprefixer: - specifier: ^10.4.17 - version: 10.4.17(postcss@8.4.33) + specifier: ^10.4.20 + version: 10.4.20(postcss@8.4.47) concurrently: - specifier: ^8.2.2 - version: 8.2.2 + specifier: ^9.0.1 + version: 9.0.1 esbuild: - specifier: ^0.19.12 - version: 0.19.12 + specifier: ^0.24.0 + version: 0.24.0 eslint: - specifier: ^8.56.0 - version: 8.56.0 + specifier: ^8.57.1 + version: 8.57.1 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.56.0) + version: 9.1.0(eslint@8.57.1) eslint-plugin-import: - specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0) + specifier: ^2.31.0 + version: 2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1) eslint-plugin-jsx-a11y: - specifier: ^6.8.0 - version: 6.8.0(eslint@8.56.0) + specifier: ^6.10.2 + version: 6.10.2(eslint@8.57.1) eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(@types/eslint@8.56.2)(eslint-config-prettier@9.1.0(eslint@8.56.0))(eslint@8.56.0)(prettier@3.2.4) + specifier: ^5.2.1 + version: 5.2.1(@types/eslint@8.56.12)(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3) eslint-plugin-react: - specifier: ^7.33.2 - version: 7.33.2(eslint@8.56.0) + specifier: ^7.37.2 + version: 7.37.2(eslint@8.57.1) eslint-plugin-react-hooks: - specifier: ^4.6.0 - version: 4.6.0(eslint@8.56.0) + specifier: ^4.6.2 + version: 4.6.2(eslint@8.57.1) eslint-plugin-react-refresh: - specifier: ^0.4.5 - version: 0.4.5(eslint@8.56.0) + specifier: ^0.4.14 + version: 0.4.14(eslint@8.57.1) eslint-plugin-simple-import-sort: specifier: ^10.0.0 - version: 10.0.0(eslint@8.56.0) + version: 10.0.0(eslint@8.57.1) postcss: - specifier: ^8.4.33 - version: 8.4.33 + specifier: ^8.4.47 + version: 8.4.47 prettier: - specifier: ^3.2.4 - version: 3.2.4 + specifier: ^3.3.3 + version: 3.3.3 prop-types: specifier: ^15.8.1 version: 15.8.1 rollup-plugin-preserve-directives: - specifier: ^0.3.1 - version: 0.3.1(@rollup/wasm-node@4.24.0) + specifier: ^0.4.0 + version: 0.4.0(@rollup/wasm-node@4.24.2) sass: - specifier: ^1.70.0 - version: 1.70.0 + specifier: ^1.80.4 + version: 1.80.4 standard-version: specifier: ^9.5.0 version: 9.5.0 @@ -286,295 +286,195 @@ importers: specifier: ^1.0.0 version: 1.0.0(stylelint@16.2.0(typescript@5.3.3)) stylelint-config-standard-scss: - specifier: ^13.0.0 - version: 13.0.0(postcss@8.4.33)(stylelint@16.2.0(typescript@5.3.3)) + specifier: ^13.1.0 + version: 13.1.0(postcss@8.4.47)(stylelint@16.2.0(typescript@5.3.3)) stylelint-scss: - specifier: ^6.1.0 - version: 6.1.0(stylelint@16.2.0(typescript@5.3.3)) + specifier: ^6.8.1 + version: 6.8.1(stylelint@16.2.0(typescript@5.3.3)) typedoc: - specifier: ^0.25.7 - version: 0.25.7(typescript@5.3.3) + specifier: ^0.25.13 + version: 0.25.13(typescript@5.3.3) typescript: specifier: ~5.3.3 version: 5.3.3 typescript-eslint-language-service: specifier: ^5.0.5 - version: 5.0.5(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3) + version: 5.0.5(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3) vite: - specifier: ^5.0.12 - version: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + specifier: ^5.4.10 + version: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) vite-plugin-eslint: specifier: ^1.8.1 - version: 1.8.1(eslint@8.56.0)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + version: 1.8.1(eslint@8.57.1)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) vite-plugin-package-version: specifier: ^1.1.0 - version: 1.1.0(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + version: 1.1.0(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - - '@adraffy/ens-normalize@1.10.0': - resolution: {integrity: sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==} + '@adraffy/ens-normalize@1.10.1': + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - '@ampproject/remapping@2.2.1': - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.23.5': - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + '@babel/code-frame@7.26.0': + resolution: {integrity: sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.23.5': - resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + '@babel/compat-data@7.26.0': + resolution: {integrity: sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==} engines: {node: '>=6.9.0'} - '@babel/core@7.23.9': - resolution: {integrity: sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==} + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} - '@babel/generator@7.23.6': - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + '@babel/generator@7.26.0': + resolution: {integrity: sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.22.5': - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9': + resolution: {integrity: sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.23.6': - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + '@babel/helper-compilation-targets@7.25.9': + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.23.7': - resolution: {integrity: sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==} + '@babel/helper-create-class-features-plugin@7.25.9': + resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.22.15': - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + '@babel/helper-create-regexp-features-plugin@7.25.9': + resolution: {integrity: sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.4.4': - resolution: {integrity: sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==} + '@babel/helper-define-polyfill-provider@0.6.2': + resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-define-polyfill-provider@0.5.0': - resolution: {integrity: sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - - '@babel/helper-environment-visitor@7.22.20': - resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.23.0': - resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.22.5': - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-member-expression-to-functions@7.23.0': - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.22.15': - resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.23.3': - resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.22.5': - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.22.5': - resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + '@babel/helper-plugin-utils@7.25.9': + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.22.20': - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.22.20': - resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + '@babel/helper-replace-supers@7.25.9': + resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.22.5': - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-split-export-declaration@7.22.6': - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + '@babel/helper-simple-access@7.25.9': + resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.23.4': - resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.23.5': - resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.22.20': - resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.23.9': - resolution: {integrity: sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==} + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.23.4': - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + '@babel/helpers@7.26.0': + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.23.6': - resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.23.9': - resolution: {integrity: sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==} + '@babel/parser@7.26.1': + resolution: {integrity: sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3': - resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3': - resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.7': - resolution: {integrity: sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.0.0 - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-dynamic-import@7.8.3': - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-export-namespace-from@7.8.3': - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.13.0 - '@babel/plugin-syntax-import-assertions@7.23.3': - resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.0.0 - '@babel/plugin-syntax-import-attributes@7.23.3': - resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -585,308 +485,320 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.23.3': - resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.23.7': - resolution: {integrity: sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==} + '@babel/plugin-transform-async-generator-functions@7.25.9': + resolution: {integrity: sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.23.3': - resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==} + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.23.3': - resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} + '@babel/plugin-transform-block-scoped-functions@7.25.9': + resolution: {integrity: sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.23.4': - resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} + '@babel/plugin-transform-block-scoping@7.25.9': + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.23.3': - resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.23.4': - resolution: {integrity: sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==} + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.23.8': - resolution: {integrity: sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==} + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.23.3': - resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.23.3': - resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.23.3': - resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.23.3': - resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==} + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dynamic-import@7.23.4': - resolution: {integrity: sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.23.3': - resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==} + '@babel/plugin-transform-exponentiation-operator@7.25.9': + resolution: {integrity: sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.23.4': - resolution: {integrity: sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==} + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.23.6': - resolution: {integrity: sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==} + '@babel/plugin-transform-for-of@7.25.9': + resolution: {integrity: sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.23.3': - resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.23.4': - resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==} + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.23.3': - resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.23.4': - resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==} + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-member-expression-literals@7.23.3': - resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-amd@7.23.3': - resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.23.3': - resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + '@babel/plugin-transform-modules-commonjs@7.25.9': + resolution: {integrity: sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.23.3': - resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-umd@7.23.3': - resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==} + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5': - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.23.3': - resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==} + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.23.4': - resolution: {integrity: sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==} + '@babel/plugin-transform-nullish-coalescing-operator@7.25.9': + resolution: {integrity: sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.23.4': - resolution: {integrity: sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==} + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.23.4': - resolution: {integrity: sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==} + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.23.3': - resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.23.4': - resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==} + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.23.4': - resolution: {integrity: sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==} + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.23.3': - resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.23.3': - resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.23.4': - resolution: {integrity: sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==} + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.23.3': - resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-self@7.23.3': - resolution: {integrity: sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==} + '@babel/plugin-transform-react-jsx-self@7.25.9': + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-react-jsx-source@7.23.3': - resolution: {integrity: sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==} + '@babel/plugin-transform-react-jsx-source@7.25.9': + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.23.3': - resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==} + '@babel/plugin-transform-regenerator@7.25.9': + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-reserved-words@7.23.3': - resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==} + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.23.3': - resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.23.3': - resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-sticky-regex@7.23.3': - resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-template-literals@7.23.3': - resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} + '@babel/plugin-transform-template-literals@7.25.9': + resolution: {integrity: sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.23.3': - resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} + '@babel/plugin-transform-typeof-symbol@7.25.9': + resolution: {integrity: sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.23.3': - resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==} + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.23.3': - resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==} + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-regex@7.23.3': - resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==} + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.23.3': - resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==} + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.23.8': - resolution: {integrity: sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==} + '@babel/preset-env@7.26.0': + resolution: {integrity: sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -896,35 +808,20 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/regjsgen@0.8.0': - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - - '@babel/runtime@7.23.8': - resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.22.15': - resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.23.9': - resolution: {integrity: sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.23.7': - resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==} + '@babel/runtime@7.26.0': + resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.23.9': - resolution: {integrity: sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==} + '@babel/template@7.25.9': + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} - '@babel/types@7.23.6': - resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + '@babel/traverse@7.25.9': + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} engines: {node: '>=6.9.0'} - '@babel/types@7.23.9': - resolution: {integrity: sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==} + '@babel/types@7.26.0': + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} engines: {node: '>=6.9.0'} '@bundled-es-modules/cookie@2.0.0': @@ -933,52 +830,49 @@ packages: '@bundled-es-modules/statuses@1.0.1': resolution: {integrity: sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==} - '@csstools/css-parser-algorithms@2.5.0': - resolution: {integrity: sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==} + '@bundled-es-modules/tough-cookie@0.1.6': + resolution: {integrity: sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==} + + '@csstools/css-parser-algorithms@2.7.1': + resolution: {integrity: sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - '@csstools/css-tokenizer': ^2.2.3 + '@csstools/css-tokenizer': ^2.4.1 - '@csstools/css-tokenizer@2.2.3': - resolution: {integrity: sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg==} + '@csstools/css-tokenizer@2.4.1': + resolution: {integrity: sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==} engines: {node: ^14 || ^16 || >=18} - '@csstools/media-query-list-parser@2.1.7': - resolution: {integrity: sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==} + '@csstools/media-query-list-parser@2.1.13': + resolution: {integrity: sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - '@csstools/css-parser-algorithms': ^2.5.0 - '@csstools/css-tokenizer': ^2.2.3 + '@csstools/css-parser-algorithms': ^2.7.1 + '@csstools/css-tokenizer': ^2.4.1 - '@csstools/selector-specificity@3.0.1': - resolution: {integrity: sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==} + '@csstools/selector-specificity@3.1.1': + resolution: {integrity: sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss-selector-parser: ^6.0.13 - '@emotion/babel-plugin@11.11.0': - resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} - - '@emotion/cache@11.11.0': - resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} - - '@emotion/hash@0.9.1': - resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + '@emotion/babel-plugin@11.12.0': + resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==} - '@emotion/is-prop-valid@0.8.8': - resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + '@emotion/cache@11.13.1': + resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==} - '@emotion/is-prop-valid@1.2.1': - resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==} + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - '@emotion/memoize@0.7.4': - resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + '@emotion/is-prop-valid@1.3.1': + resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} - '@emotion/memoize@0.8.1': - resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - '@emotion/react@11.11.3': - resolution: {integrity: sha512-Cnn0kuq4DoONOMcnoVsTOR8E+AdnKFf//6kUWc4LCdnxj31pZWn7rIULd6Y7/Js1PiPHzn7SKCM9vB/jBni8eA==} + '@emotion/react@11.13.3': + resolution: {integrity: sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==} peerDependencies: '@types/react': '*' react: '>=16.8.0' @@ -986,14 +880,14 @@ packages: '@types/react': optional: true - '@emotion/serialize@1.1.3': - resolution: {integrity: sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==} + '@emotion/serialize@1.3.2': + resolution: {integrity: sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==} - '@emotion/sheet@1.2.2': - resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} + '@emotion/sheet@1.4.0': + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - '@emotion/styled@11.11.0': - resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} + '@emotion/styled@11.13.0': + resolution: {integrity: sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 '@types/react': '*' @@ -1002,196 +896,340 @@ packages: '@types/react': optional: true - '@emotion/unitless@0.8.1': - resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@emotion/use-insertion-effect-with-fallbacks@1.0.1': - resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} + '@emotion/use-insertion-effect-with-fallbacks@1.1.0': + resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==} peerDependencies: react: '>=16.8.0' - '@emotion/utils@1.2.1': - resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} + '@emotion/utils@1.4.1': + resolution: {integrity: sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==} - '@emotion/weak-memoize@0.3.1': - resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} + '@emotion/weak-memoize@0.4.0': + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.19.12': - resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.19.12': - resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.19.12': - resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.19.12': - resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.19.12': - resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.19.12': - resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.19.12': - resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.19.12': - resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.19.12': - resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.19.12': - resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.19.12': - resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.19.12': - resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.19.12': - resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.19.12': - resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.19.12': - resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.19.12': - resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.19.12': - resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.19.12': - resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-x64@0.19.12': - resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.19.12': - resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.19.12': - resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.19.12': - resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.19.12': - resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@8.56.0': - resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@floating-ui/core@1.6.0': - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + '@floating-ui/core@1.6.8': + resolution: {integrity: sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==} - '@floating-ui/dom@1.6.0': - resolution: {integrity: sha512-SZ0BEXzsaaS6THZfZJUcAobbZTD+MvfGM42bxgeg0Tnkp4/an/avqwAXiVLsFtIBZtfsx3Ymvwx0+KnnhdA/9g==} + '@floating-ui/dom@1.6.11': + resolution: {integrity: sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==} - '@floating-ui/react-dom@2.0.7': - resolution: {integrity: sha512-B5GJxKUyPcGsvE1vua+Abvw0t6zVMyTbtG+Jk7BoI4hfc5Ahv50dstRIAn0nS0274kR9gnKwxIXyGA8EzBZJrA==} + '@floating-ui/react-dom@2.1.2': + resolution: {integrity: sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/react@0.26.7': - resolution: {integrity: sha512-0uMI9IBJBPPt8N+8uRg4gazJvQReWTu/fVUHHLfAOuy1WB6f242jtjWm52hLJG8nzuZVuU+2crW4lJbJQoqeIA==} + '@floating-ui/react@0.26.25': + resolution: {integrity: sha512-hZOmgN0NTOzOuZxI1oIrDu3Gcl8WViIkvPMpB4xdd4QD6xAMtwgwr3VPoiyH/bLtRcS1cDnhxLSD1NsMJmwh/A==} peerDependencies: react: '>=16.8.0' react-dom: '>=16.8.0' - '@floating-ui/utils@0.2.1': - resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + '@floating-ui/utils@0.2.8': + resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} '@github/webauthn-json@2.1.1': resolution: {integrity: sha512-XrftRn4z75SnaJOmZQbt7Mk+IIjqVHw+glDGOxuHwXkZBZh/MBoRS7MHjSZMDaLhT4RjN2VqiEU7EOYleuJWSQ==} @@ -1203,13 +1241,13 @@ packages: react: ^16.8.0 || ^17 || ^18 react-dom: ^16.8.0 || ^17 || ^18 - '@hookform/resolvers@3.3.4': - resolution: {integrity: sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==} + '@hookform/resolvers@3.9.1': + resolution: {integrity: sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug==} peerDependencies: react-hook-form: ^7.0.0 - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead @@ -1217,38 +1255,54 @@ packages: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.2': - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead '@hutson/parse-repository-url@3.0.2': resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==} engines: {node: '>=6.9.0'} - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@inquirer/confirm@5.0.1': + resolution: {integrity: sha512-6ycMm7k7NUApiMGfVc32yIPp28iPKxhGRMqoNDiUjq2RyTAkbs5Fx0TdzBqhabcKvniDdAAvHCmsRjnNfTsogw==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + + '@inquirer/core@10.0.1': + resolution: {integrity: sha512-KKTgjViBQUi3AAssqjUFMnMO3CM3qwCHvePV9EW+zTKGKafFGFF01sc1yOIYjLJ7QU52G/FbzKc+c01WLzXmVQ==} + engines: {node: '>=18'} + + '@inquirer/figures@1.0.7': + resolution: {integrity: sha512-m+Trk77mp54Zma6xLkLuY+mvanPxlE4A7yNKs2HBiyZ4UkVs28Mv5c/pgWrHeInx+USHeX/WEPzjrWrcJiQgjw==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.0': + resolution: {integrity: sha512-YYykfbw/lefC7yKj7nanzQXILM7r3suIvyFlCcMskc99axmsSewXWkAfXKwMbgxL76iAFVmRwmYdwNZNc8gjog==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' - '@jridgewell/gen-mapping@0.3.3': - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} - '@jridgewell/resolve-uri@3.1.1': - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.1.2': - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} engines: {node: '>=6.0.0'} - '@jridgewell/source-map@0.3.5': - resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@jridgewell/trace-mapping@0.3.22': - resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} '@ladle/react-context@1.0.1': resolution: {integrity: sha512-xVQ8siyOEQG6e4Knibes1uA3PTyXnqiMmfSmd5pIbkzeDty8NCBtYHhTXSlfmcDNEsw/G8OzNWo4VbyQAVDl2A==} @@ -1256,19 +1310,19 @@ packages: react: '>=16.14.0' react-dom: '>=16.14.0' - '@ladle/react@4.0.2': - resolution: {integrity: sha512-SnYniR/U7kJX1Zh199jhjxqiFa5e5eA8chuX6uYEZYAUtCCY/hQqGr7/7Grr0j6Q4FYu9iQyyV2K1NJKDdUZIw==} - engines: {node: '>=18.0.0'} + '@ladle/react@4.1.2': + resolution: {integrity: sha512-6nMIPCsnkGCjIRz5kpRojJyieqcFPsq34QeqJp5mFpT1xFeX7sKwdCpQJ92d5ORsejmxTyp9gkQA+AXG3i3AGw==} + engines: {node: '>=20.0.0'} hasBin: true peerDependencies: react: '>=18.0.0' react-dom: '>=18.0.0' - '@mdx-js/mdx@3.0.0': - resolution: {integrity: sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==} + '@mdx-js/mdx@3.1.0': + resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} - '@mdx-js/react@3.0.0': - resolution: {integrity: sha512-nDctevR9KyYFyV+m+/+S4cpzCWHqj+iHDHq3QrsWezcC+B17uZdIWgCguESUkwFhM3n/56KxWVE3V6EokrmONQ==} + '@mdx-js/react@3.1.0': + resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} peerDependencies: '@types/react': '>=16' react: '>=16' @@ -1277,12 +1331,8 @@ packages: resolution: {integrity: sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ==} engines: {node: '>=14.0.0'} - '@mswjs/cookies@1.1.0': - resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} - engines: {node: '>=18'} - - '@mswjs/interceptors@0.25.14': - resolution: {integrity: sha512-2dnIxl+obqIqjoPXTFldhe6pcdOrqiz+GcLaQQ6hmL02OldAF7nIC+rUgTWm+iF6lvmyCVhFFqbgbapNhR8eag==} + '@mswjs/interceptors@0.36.6': + resolution: {integrity: sha512-issnYydStyH0wPEeU7CMwfO7kI668ffVtzKRMRS7H7BliOYuPuwEZxh9dwiXV+oeHBxT5SXT0wPwV8T7V2PJUA==} engines: {node: '>=18'} '@noble/curves@1.2.0': @@ -1313,9 +1363,81 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} + '@parcel/watcher-android-arm64@2.4.1': + resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.4.1': + resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.4.1': + resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.4.1': + resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.4.1': + resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.4.1': + resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.4.1': + resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.4.1': + resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.4.1': + resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.4.1': + resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.4.1': + resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.4.1': + resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.4.1': + resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} + engines: {node: '>= 10.0.0'} '@pkgr/core@0.1.1': resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} @@ -1330,51 +1452,63 @@ packages: react: '>=16.8.0' rxjs: '>=7' - '@remix-run/router@1.14.2': - resolution: {integrity: sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==} + '@remix-run/router@1.20.0': + resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==} engines: {node: '>=14.0.0'} '@rollup/pluginutils@4.2.1': resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} - '@rollup/wasm-node@4.24.0': - resolution: {integrity: sha512-LL6oALR6fKG6GihtH0K0uWLAl19Q/QJst+oKJT1VWwFo4sPLA0/7JeZaSqrpFWq8OPloiKx/NDG4BWppFSX2vQ==} + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: npm:@rollup/wasm-node + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/wasm-node@4.24.2': + resolution: {integrity: sha512-IguLcLWwK36BDePr5B6qpLTygh2CFVVCXF2Wc+cPnTe93J6t6gGQipwV3W0Cb9eTcFj8IvYpZF/BLl2jIMMKyA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@rx-state/core@0.1.4': resolution: {integrity: sha512-Z+3hjU2xh1HisLxt+W5hlYX/eGSDaXXP+ns82gq/PLZpkXLu0uwcNUh9RLY3Clq4zT+hSsA3vcpIGt6+UAb8rQ==} peerDependencies: rxjs: '>=7' - '@sindresorhus/merge-streams@1.0.0': - resolution: {integrity: sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==} + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} engines: {node: '>=18'} - '@stablelib/base64@1.0.1': - resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} + '@stablelib/base64@2.0.0': + resolution: {integrity: sha512-ffSfySa1ZpZYzM5FQ2xILQ2jifQ+GlgbDJzRTCtaB0sqta88KYghB/tlSV2VS2iHRCvMdUvJlLOW1rmSkziWnw==} - '@stablelib/binary@1.0.1': - resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} + '@stablelib/binary@2.0.0': + resolution: {integrity: sha512-dHejKHMtq5OtNwDSMcFx+djhixVAnZ76Rqga3WOOKe6KV3NlnE7JBXlmdLIn04G4FxqhRSEx+zkoO4Izdw10ZA==} - '@stablelib/bytes@1.0.1': - resolution: {integrity: sha512-Kre4Y4kdwuqL8BR2E9hV/R5sOrUj6NanZaZis0V6lX5yzqC3hBuVSDXUIBqQv/sCpmuWRiHLwqiT1pqqjuBXoQ==} + '@stablelib/bytes@2.0.0': + resolution: {integrity: sha512-oSfT6VTfk/XK5s/BUi1L8Obp1Uoh/RFJHWDAG9Yj5D/kiGTnR7sEnzJIRenbIFDbzkb+lXP3OSDp+ttgI51Nng==} - '@stablelib/int@1.0.1': - resolution: {integrity: sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==} + '@stablelib/int@2.0.0': + resolution: {integrity: sha512-EiSYDisTYKk1wuCqoh7wuBySmE0A1isq7TQbsijQ6XFi6nIAozchgAT7Zv2PCl2iY8BTe0URScC4PdYHOe3Yow==} - '@stablelib/keyagreement@1.0.1': - resolution: {integrity: sha512-VKL6xBwgJnI6l1jKrBAfn265cspaWBPAPEc62VBQrWHLqVgNRE09gQ/AnOEyKUWrrqfD+xSQ3u42gJjLDdMDQg==} + '@stablelib/keyagreement@2.0.0': + resolution: {integrity: sha512-SryWYB3S8w9EyjSJ1OdJb375Foj1Ujxgd4S6mh7L+ESiPVD/24EQWMbFANyhtpaPmpsAmgIBGyXlR+LfHW5X0Q==} - '@stablelib/random@1.0.2': - resolution: {integrity: sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==} + '@stablelib/random@2.0.0': + resolution: {integrity: sha512-qvOSbiPq2B3ajvn/IDftC1mzL/W89OGv59gdJ7klMjm327Yk/54NyGl4Jtrwcz35GjCPy/ScVnQXC8YQk8uAUQ==} - '@stablelib/wipe@1.0.1': - resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@stablelib/wipe@2.0.0': + resolution: {integrity: sha512-VBMpCJx8py9j9F5DxV5dGmSSO+vkYDnXHXG4alkfpaD08UTfNTqsQoRlUh5obeqBNHiO+3Iv40GxKpM0gfd5xA==} - '@stablelib/x25519@1.0.3': - resolution: {integrity: sha512-KnTbKmUhPhHavzobclVJQG5kuivH+qDLpe84iRqX3CLrKp881cF160JvXJ+hjn1aMyCwYOKeIZefIH/P5cJoRw==} + '@stablelib/x25519@2.0.0': + resolution: {integrity: sha512-mnl4U+1dE73rgrnhL2jPuT2u6TVOJPCwWKnC+A18JkYZaRKXERKVXJzuhc+jSNEnWHdv3BDMut50v8bpIdZCCQ==} '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} @@ -1461,83 +1595,83 @@ packages: peerDependencies: '@svgr/core': '*' - '@swc/core-darwin-arm64@1.3.106': - resolution: {integrity: sha512-XYcbViNyHnnm7RWOAO1YipMmthM7m2aXF32b0y+JMLYFBEyFpjVX9btLkzeL7wRx/5B3I35yJNhE+xyx0Q1Gkw==} + '@swc/core-darwin-arm64@1.7.40': + resolution: {integrity: sha512-LRRrCiRJLb1kpQtxMNNsr5W82Inr0dy5Imho+4HQzVx/Ismi0qX4hQBgzJAnyOBNLK1+OBVb/912UVhKXppdfQ==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.3.106': - resolution: {integrity: sha512-YKDPhUdfuwhmOUS9+CaIwl/0Tp+f1b73BH2EIESuxSNsogZf18a8HQ8O0fQEwdiwmA5LEqw47cj+kfOWV/0+kw==} + '@swc/core-darwin-x64@1.7.40': + resolution: {integrity: sha512-Lpl0XK/4fLzS5jsK48opUuGXrqJXwqJckYYPwyGbCfCXm4MsBe+7dX2hq/Kc4YMY25+NeTmzAXhla8TT4WYD/g==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.3.106': - resolution: {integrity: sha512-bHxxJXogvFfocLL5inZxxtx/x/WgKozigp80Vbx0viac1fPDJrqKBw2X4MzpMiuTRAGVQ03jJI6pDwbSBf+yDw==} + '@swc/core-linux-arm-gnueabihf@1.7.40': + resolution: {integrity: sha512-4bEvvjptpoc5BRPr/R419h6fXTEuub+frpxxlxBOEKxgXjAF/S3xdxyPijUAakmW/xXBF0u7OC4KYI+38yQp6g==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.3.106': - resolution: {integrity: sha512-c7jue++CHLgtpeaakEukoCLT9eNrImizbleE9Y7Is8CHqLq/7DG4s+7ma9DFKXIzW2MpTg9byIEQfpqSphVW6A==} + '@swc/core-linux-arm64-gnu@1.7.40': + resolution: {integrity: sha512-v2fBlHJ/6Ovz0L2xFAI9TRiKyl9DTdx139PuAHD9gyzp16Utl/W0MPd4t2cYdkI6hPXE9PsJCSzMOrduh+YoDg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.3.106': - resolution: {integrity: sha512-51EaC3Q8qAhLtWVnAVqoYX/gk3tK31cCBzUpwCcmhianhEBM2/WtKRAS4MqPhE8VVZuN3WjO2c2JaF2mX0yuoA==} + '@swc/core-linux-arm64-musl@1.7.40': + resolution: {integrity: sha512-uMkduQuU4LFVkW6txv8AVArT8GjJVJ5IHoWloXaUBMT447iE8NALmpePdZWhMyj6KV7j0y23CM5rzV/I2eNGLg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.3.106': - resolution: {integrity: sha512-tOUi8BB6jAeCXgx7ESLNnX7nrbMVKQ/XajK77v7Ad4SXf9HYArnimBJpXUUyVFJTXLSv4e6c7s6XHHqXb5Lwcg==} + '@swc/core-linux-x64-gnu@1.7.40': + resolution: {integrity: sha512-4LZdY1MBSnXyTpW5fpBU/+JGAhkuHT+VnFTDNegRboN5nSPh7y0Yvn4LmIioESV+sWzjKkEXujJPGjrp+oSp5w==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.3.106': - resolution: {integrity: sha512-binLw4Lbd83NPy4/m/teH2nbaifxveSD+sKDvpxywRbvYW2I0w/iCBpUBcbnl16TQF4TPOGpq5YwG9lVxPVw5g==} + '@swc/core-linux-x64-musl@1.7.40': + resolution: {integrity: sha512-FPjOwT3SgI6PAwH1O8bhOGBPzuvzOlzKeCtxLaCjruHJu9V8KKBrMTWOZT/FJyYC9mX5Ip1+l9j30UqUZdQxtA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.3.106': - resolution: {integrity: sha512-n4ttBWr8tM7DPzwcEOIBTyTMHZTzCmbic/HTtxEsPyMAf/Daen+yrTKzjPP6k2usfSrjkxA780RSJJxI1N8r2w==} + '@swc/core-win32-arm64-msvc@1.7.40': + resolution: {integrity: sha512-//ovXdD9GsTmhPmXJlXnIbRQkeuL6PSrYSr7uCMNcclrUdJG0YkO0GMM2afUKYbdJcunylDDWsSS8PFWn0QxmA==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.3.106': - resolution: {integrity: sha512-GhDNIwxE5FhkujESI6h/4ysT3wxwmrzTUlZYaR8rRui6a6SdX9feIPUHPEE5o5hpyp+xqlmvRxKkRxOnwsq8iA==} + '@swc/core-win32-ia32-msvc@1.7.40': + resolution: {integrity: sha512-iD/1auVhHGlhWAPrWmfRWL3w4AvXIWGVXZiSA109/xnRIPiHKb/HqqTp/qB94E/ZHMPRgLKkLTNwamlkueUs8g==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.3.106': - resolution: {integrity: sha512-2M6yWChuMS1+/MPo3Dor0SOMkvmiugonWlzsZBAu/oZboH2xKrHSRv7brsBujb2Oe47r+NsbV+vq9tnnP9Vl1Q==} + '@swc/core-win32-x64-msvc@1.7.40': + resolution: {integrity: sha512-ZlFAV1WFPhhWQ/8esiygmetkb905XIcMMtHRRG0FBGCllO+HVL5nikUaLDgTClz1onmEY9sMXUFQeoPtvliV+w==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.3.106': - resolution: {integrity: sha512-++QPSPkFq2qELYVScxNHJC42hKQChjiTWS2P0QQ5JWT4NHb9lmNSfrc1ylFIyImwRnxsW2MTBALLYLf95EFAsg==} + '@swc/core@1.7.40': + resolution: {integrity: sha512-0HIzM5vigVT5IvNum+pPuST9p8xFhN6mhdIKju7qYYeNuZG78lwms/2d8WgjTJJlzp6JlPguXGrMMNzjQw0qNg==} engines: {node: '>=10'} peerDependencies: - '@swc/helpers': ^0.5.0 + '@swc/helpers': '*' peerDependenciesMeta: '@swc/helpers': optional: true - '@swc/counter@0.1.2': - resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - '@swc/types@0.1.5': - resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} + '@swc/types@0.1.13': + resolution: {integrity: sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==} - '@tanstack/match-sorter-utils@8.11.7': - resolution: {integrity: sha512-4PUKgaaFpiB7MK406N5VAiLu2VUhDumojGWhEC8kNQ767RGU2vsJDI7Xp4D8lMBzijqswRWz3U8ioa2zUKnFeQ==} + '@tanstack/match-sorter-utils@8.19.4': + resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} engines: {node: '>=12'} '@tanstack/query-core@4.36.1': @@ -1572,8 +1706,8 @@ packages: resolution: {integrity: sha512-Aaku1DMatF8GNbAZj2ahGN9F3l6KLe2n1jzgAUO8IT07D1spoZ9jCeazOQ7gvCIIEZjceuL9klx08MnsFJdCqg==} engines: {node: '>=12'} - '@tauri-apps/api@1.5.3': - resolution: {integrity: sha512-zxnDjHHKjOsrIzZm6nO5Xapb/BxqUq1tc7cGkFXsFkGTsSWgCPH1D8mm0XS9weJY2OaR73I3k3S+b7eSzJDfqA==} + '@tauri-apps/api@1.6.0': + resolution: {integrity: sha512-rqI++FWClU5I2UBp4HXFvl+sBWkdigBkxnpJDQUWttNyG7IZP4FwQGhTNL5EOw0vI8i6eSAJ5frLqO7n7jbJdg==} engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'} '@trysound/sax@0.2.0': @@ -1592,8 +1726,8 @@ packages: '@types/babel__template@7.4.4': resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - '@types/babel__traverse@7.20.5': - resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} '@types/byte-size@8.1.2': resolution: {integrity: sha512-jGyVzYu6avI8yuqQCNTZd65tzI8HZrLjKX9sdMqZrGWVlNChu0rf6p368oVEDCYJe5BMx2Ov04tD1wqtgTwGSA==} @@ -1613,8 +1747,8 @@ packages: '@types/d3-interpolate@3.0.4': resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} - '@types/d3-path@3.0.2': - resolution: {integrity: sha512-WAIEVlOCdd/NKRYTsqCpOMHQHemKBEINf8YXMYOtXH0GA7SY0dqMB78P3Uhgfy+4X+/Mlw2wDtlETkN6kQUCMA==} + '@types/d3-path@3.1.0': + resolution: {integrity: sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==} '@types/d3-scale@4.0.8': resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} @@ -1631,14 +1765,11 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} - '@types/eslint@8.56.2': - resolution: {integrity: sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==} + '@types/eslint@8.56.12': + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} - '@types/estree-jsx@1.0.3': - resolution: {integrity: sha512-pvQ+TKeRHeiUGRhvYwRrQ/ISnohKkSJR14fT2yqyZ4e9K5vqc7hrtY2Y1Dw0ZwAzQ6DQsxsaCUuSIIi8v0Cq6w==} - - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -1646,8 +1777,8 @@ packages: '@types/file-saver@2.0.7': resolution: {integrity: sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==} - '@types/hast@3.0.3': - resolution: {integrity: sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==} + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} '@types/history@4.7.11': resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} @@ -1661,14 +1792,14 @@ packages: '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} - '@types/lodash@4.14.202': - resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + '@types/lodash@4.17.12': + resolution: {integrity: sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==} - '@types/mdast@4.0.3': - resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - '@types/mdx@2.0.10': - resolution: {integrity: sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} '@types/minimist@1.2.5': resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} @@ -1676,11 +1807,11 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} - '@types/node@18.15.13': - resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + '@types/node@20.17.2': + resolution: {integrity: sha512-OOHK4sjXqkL7yQ7VEEHcf6+0jSvKjWqwnaCtY7AKD/VLEvRHMsxxu7eI8ErnjxHS8VwmekD4PeVCpu4qZEZSxg==} - '@types/node@20.11.7': - resolution: {integrity: sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==} + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1688,14 +1819,14 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} - '@types/prismjs@1.26.3': - resolution: {integrity: sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==} + '@types/prismjs@1.26.5': + resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==} - '@types/prop-types@15.7.11': - resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} + '@types/prop-types@15.7.13': + resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} - '@types/react-dom@18.2.18': - resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==} + '@types/react-dom@18.3.1': + resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} '@types/react-router-dom@5.3.3': resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} @@ -1709,26 +1840,26 @@ packages: '@types/react-window@1.8.8': resolution: {integrity: sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==} - '@types/react@18.2.48': - resolution: {integrity: sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==} + '@types/react@18.3.12': + resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} - '@types/scheduler@0.16.8': - resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/semver@7.5.6': - resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} + '@types/statuses@2.0.5': + resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} - '@types/statuses@2.0.4': - resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - '@types/unist@2.0.10': - resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.2': - resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@typescript-eslint/eslint-plugin@6.19.1': - resolution: {integrity: sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==} + '@typescript-eslint/eslint-plugin@6.21.0': + resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -1738,8 +1869,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@6.19.1': - resolution: {integrity: sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==} + '@typescript-eslint/parser@6.21.0': + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1748,12 +1879,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@6.19.1': - resolution: {integrity: sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==} + '@typescript-eslint/scope-manager@6.21.0': + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/type-utils@6.19.1': - resolution: {integrity: sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==} + '@typescript-eslint/type-utils@6.21.0': + resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -1762,12 +1893,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@6.19.1': - resolution: {integrity: sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==} + '@typescript-eslint/types@6.21.0': + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/typescript-estree@6.19.1': - resolution: {integrity: sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==} + '@typescript-eslint/typescript-estree@6.21.0': + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' @@ -1775,33 +1906,33 @@ packages: typescript: optional: true - '@typescript-eslint/utils@6.19.1': - resolution: {integrity: sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==} + '@typescript-eslint/utils@6.21.0': + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 - '@typescript-eslint/visitor-keys@6.19.1': - resolution: {integrity: sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==} + '@typescript-eslint/visitor-keys@6.21.0': + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} engines: {node: ^16.0.0 || >=18.0.0} '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-legacy@5.3.0': - resolution: {integrity: sha512-BhW+WcJmEgW5G/1UQRiVQ7wz9/ZPnxqzExT9n0zAk4RlqQQ/26udIeXzdU8+03AGnaF61wmZlCspexgEnxFWMA==} + '@vitejs/plugin-legacy@5.4.3': + resolution: {integrity: sha512-wsyXK9mascyplcqvww1gA1xYiy29iRHfyciw+a0t7qRNdzX6PdfSWmOoCi74epr87DujM+5J+rnnSv+4PazqVg==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: terser: ^5.4.0 vite: ^5.0.0 - '@vitejs/plugin-react-swc@3.5.0': - resolution: {integrity: sha512-1PrOvAaDpqlCV+Up8RkAh9qaiUjoDUcjtttyhXDKw53XA6Ve16SOp6cCOpRs8Dj8DqUQs6eTW5YkLcLJjrXAig==} + '@vitejs/plugin-react-swc@3.7.1': + resolution: {integrity: sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==} peerDependencies: vite: ^4 || ^5 - '@vitejs/plugin-react@4.2.1': - resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} + '@vitejs/plugin-react@4.3.3': + resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 @@ -1819,8 +1950,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true @@ -1833,8 +1964,8 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -1847,8 +1978,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} ansi-sequence-parser@1.1.1: @@ -1873,25 +2004,31 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} - array-includes@3.1.7: - resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array.prototype.findlastindex@1.2.3: - resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} engines: {node: '>= 0.4'} array.prototype.flat@1.3.2: @@ -1902,11 +2039,12 @@ packages: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} - array.prototype.tosorted@1.1.2: - resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} arrify@1.0.1: @@ -1920,57 +2058,51 @@ packages: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} - astring@1.8.6: - resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true - asynciterator.prototype@1.0.0: - resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} - asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - autoprefixer@10.4.17: - resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 - available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.7.0: - resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} - engines: {node: '>=4'} - - axe-core@4.8.3: - resolution: {integrity: sha512-d5ZQHPSPkF9Tw+yfyDcRoUOc4g/8UloJJe5J8m4L5+c7AtDdjDLRxew/knnI4CxvtdxEUVgWz4x3OIQUIFiMfw==} + axe-core@4.10.2: + resolution: {integrity: sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==} engines: {node: '>=4'} - axios@1.6.7: - resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} - axobject-query@3.2.1: - resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} - babel-plugin-polyfill-corejs2@0.4.8: - resolution: {integrity: sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==} + babel-plugin-polyfill-corejs2@0.4.11: + resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.8.7: - resolution: {integrity: sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==} + babel-plugin-polyfill-corejs3@0.10.6: + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.5.5: - resolution: {integrity: sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==} + babel-plugin-polyfill-regenerator@0.6.2: + resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1983,26 +2115,16 @@ packages: balanced-match@2.0.0: resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - bcp-47-match@2.0.3: resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} - big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - bignumber.js@9.1.2: resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} - binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} - bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2010,10 +2132,6 @@ packages: resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} engines: {node: '>=14.16'} - bplist-parser@0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -2024,31 +2142,36 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.22.2: - resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} + browserslist-to-esbuild@2.1.1: + resolution: {integrity: sha512-KN+mty6C3e9AN8Z5dI1xeN15ExcRNeISoC3g7V0Kax/MMF9MSoYA2G7lkTTcVUFntiEjkpI0HNgqJC1NjdyNUw==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + browserslist: '*' + + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - - bundle-name@3.0.0: - resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} - engines: {node: '>=12'} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} - byte-size@8.1.1: - resolution: {integrity: sha512-tUkzZWK0M/qdoLEqikxBWe4kumyuwjl3HO6zHTr4yEI23EojPtLYXdG1+AQY7MN0cGyNDvEaJ8wiYQm6P2bPxg==} + byte-size@9.0.0: + resolution: {integrity: sha512-xrJ8Hki7eQ6xew55mM6TG9zHI852OoAHcPfduWWtR6yxk2upTuIZy13VioRBDyHReHDdbeDPifUboeNkK/sXXA==} engines: {node: '>=12.17'} cache-content-type@1.0.1: resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} engines: {node: '>= 6.0.0'} - call-bind@1.0.5: - resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -2070,8 +2193,8 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-lite@1.0.30001580: - resolution: {integrity: sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==} + caniuse-lite@1.0.30001674: + resolution: {integrity: sha512-jOsKlZVRnzfhLojb+Ykb+gyUSp9Xb57So+fAiFlLzzTKpqg8xxSav0e40c8/4F/v9N8QSvrRRaLeVzQbLqomYw==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2100,13 +2223,14 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - - chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -2114,17 +2238,9 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} - cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} - - cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - - cli-width@3.0.0: - resolution: {integrity: sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==} - engines: {node: '>= 10'} + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} @@ -2136,12 +2252,8 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - - clsx@2.1.0: - resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} co@4.6.0: @@ -2174,9 +2286,9 @@ packages: comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -2199,9 +2311,9 @@ packages: resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} engines: {'0': node >= 6.0} - concurrently@8.2.2: - resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} - engines: {node: ^14.13.0 || >=16.0.0} + concurrently@9.0.1: + resolution: {integrity: sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==} + engines: {node: '>=18'} hasBin: true content-disposition@0.5.4: @@ -2300,11 +2412,11 @@ packages: resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} engines: {node: '>=12.13'} - core-js-compat@3.35.1: - resolution: {integrity: sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==} + core-js-compat@3.38.1: + resolution: {integrity: sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==} - core-js@3.35.1: - resolution: {integrity: sha512-IgdsbxNyMskrTFxa9lWHyMwAJU5gXOPP+1yO+K59d50VLVAIDAbs7gIv705KzALModfK3ZrSZTPNpC0PQgIZuw==} + core-js@3.38.1: + resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -2335,15 +2447,15 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - css-functions-list@3.2.1: - resolution: {integrity: sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==} + css-functions-list@3.2.3: + resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==} engines: {node: '>=12 || >=16'} css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - css-selector-parser@3.0.4: - resolution: {integrity: sha512-pnmS1dbKsz6KA4EW4BznyPL2xxkNDRg62hcD0v8g6DEw2W7hxOln5M953jsp9hmw5Dg57S6o/A8GOn37mbAgcQ==} + css-selector-parser@3.0.5: + resolution: {integrity: sha512-3itoDFbKUNx1eKmVpYMFyqKX04Ww9osZ+dLgrk6GEv6KMVeXUhUnp4I5X+evw+u3ZxVU6RFXSSRxlTeMh8bA+g==} css-tree@2.2.1: resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} @@ -2353,6 +2465,10 @@ packages: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-tree@3.0.0: + resolution: {integrity: sha512-o88DVQ6GzsABn1+6+zo2ct801dBO5OASVyxbbvA2W20ue2puSh/VOuqUj90eUeMSX/xqGqBmOKiRQN7tJOuBXw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2424,15 +2540,23 @@ packages: resolution: {integrity: sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==} engines: {node: '>=4'} - date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} dateformat@3.0.3: resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==} - dayjs@1.11.10: - resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} @@ -2442,8 +2566,8 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -2479,19 +2603,16 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - default-browser-id@3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - - default-browser@4.0.0: - resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} - engines: {node: '>=14.16'} + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} - define-data-property@1.1.1: - resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} define-lazy-prop@3.0.0: @@ -2532,6 +2653,11 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -2558,8 +2684,8 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} - dom-helpers@3.4.0: - resolution: {integrity: sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==} + dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -2591,8 +2717,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.4.645: - resolution: {integrity: sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==} + electron-to-chromium@1.5.49: + resolution: {integrity: sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2600,9 +2726,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encode-utf8@1.0.3: - resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} - encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -2618,15 +2741,28 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.22.3: - resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} engines: {node: '>= 0.4'} - es-iterator-helpers@1.0.15: - resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.1.0: + resolution: {integrity: sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw==} + engines: {node: '>= 0.4'} - es-set-tostringtag@2.0.2: - resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} engines: {node: '>= 0.4'} es-shim-unscopables@1.0.2: @@ -2636,20 +2772,24 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} - esbuild-plugin-browserslist@0.10.0: - resolution: {integrity: sha512-rZWFcp3l+73xDiJB+Vl9UqP1VVs+L4E0lygbwJl6UTmW2qQago7DLT56hBu0vocH/TtZsAcRHj0+qHqkkB5Gww==} - engines: {node: '>=18'} - peerDependencies: - browserslist: ^4.21.8 - esbuild: ~0.19.2 + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} - esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true - escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} escape-html@1.0.3: @@ -2676,8 +2816,8 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-module-utils@2.8.0: - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -2697,24 +2837,24 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-plugin-import@2.29.1: - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 peerDependenciesMeta: '@typescript-eslint/parser': optional: true - eslint-plugin-jsx-a11y@6.8.0: - resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} engines: {node: '>=4.0'} peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -2727,22 +2867,22 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-react-hooks@4.6.0: - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react-refresh@0.4.5: - resolution: {integrity: sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==} + eslint-plugin-react-refresh@0.4.14: + resolution: {integrity: sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==} peerDependencies: eslint: '>=7' - eslint-plugin-react@7.33.2: - resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==} + eslint-plugin-react@7.37.2: + resolution: {integrity: sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==} engines: {node: '>=4'} peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint-plugin-simple-import-sort@10.0.0: resolution: {integrity: sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==} @@ -2757,17 +2897,18 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.56.0: - resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -2787,6 +2928,9 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + estree-util-to-js@2.0.0: resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} @@ -2803,8 +2947,8 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - ethers@6.10.0: - resolution: {integrity: sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==} + ethers@6.13.4: + resolution: {integrity: sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==} engines: {node: '>=14.0.0'} eventemitter3@4.0.7: @@ -2814,21 +2958,9 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2849,12 +2981,15 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} - fastq@1.16.0: - resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} @@ -2902,15 +3037,15 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.0: - resolution: {integrity: sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - follow-redirects@1.15.5: - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -2921,23 +3056,22 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - - form-data@4.0.0: - resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@11.0.3: - resolution: {integrity: sha512-6x2poQpIWBdbZwLd73w6cKZ1I9IEPIU94C6/Swp1Zt3LJ+sB5bPe1E2wC6EH5hSISXNkMJ4afH7AdwS7MrtkWw==} + framer-motion@11.11.10: + resolution: {integrity: sha512-061Bt1jL/vIm+diYIiA4dP/Yld7vD47ROextS7ESBW5hr4wQFhxB5D5T5zAc3c/5me3cOa+iO5LqhA38WDln/A==} peerDependencies: + '@emotion/is-prop-valid': '*' react: ^18.0.0 react-dom: ^18.0.0 peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true react: optional: true react-dom: @@ -2973,24 +3107,21 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} get-pkg-repo@4.2.1: resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} engines: {node: '>=6.9.0'} hasBin: true - get-port@7.0.0: - resolution: {integrity: sha512-mDHFgApoQd+azgMdwylJrv2DX47ywGq1i5VFJE7fZ0dttNq3iQMfsU4IvEgBHojA3KqEudyu7Vq+oN8kNaNkWw==} + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} engines: {node: '>=16'} - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} get-text-width@1.0.3: @@ -3021,11 +3152,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -3051,16 +3177,16 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - globby@14.0.0: - resolution: {integrity: sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==} + globby@14.0.2: + resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} engines: {node: '>=18'} globjoin@0.1.4: @@ -3078,8 +3204,8 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - graphql@16.8.1: - resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + graphql@16.9.0: + resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} handlebars@4.7.8: @@ -3102,23 +3228,23 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.1: - resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} engines: {node: '>= 0.4'} has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} - has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} hast-util-classnames@3.0.0: @@ -3133,23 +3259,23 @@ packages: hast-util-parse-selector@4.0.0: resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} - hast-util-raw@9.0.2: - resolution: {integrity: sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==} + hast-util-raw@9.0.4: + resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} - hast-util-select@6.0.2: - resolution: {integrity: sha512-hT/SD/d/Meu+iobvgkffo1QecV8WeKWxwsNMzcTJsKw1cKTQKSR/7ArJeURLNJF9HDjp9nVoORyNNJxrvBye8Q==} + hast-util-select@6.0.3: + resolution: {integrity: sha512-OVRQlQ1XuuLP8aFVLYmC2atrfWHS5UD3shonxpnyrjcCkwtvmt/+N6kYJdcY4mkMJhxp4kj2EFIxQ9kvkkt/eQ==} hast-util-to-estree@3.1.0: resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==} - hast-util-to-jsx-runtime@2.3.0: - resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} + hast-util-to-jsx-runtime@2.3.2: + resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==} hast-util-to-parse5@8.0.0: resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} - hast-util-to-string@3.0.0: - resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} @@ -3157,8 +3283,8 @@ packages: hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} - headers-polyfill@4.0.2: - resolution: {integrity: sha512-EWGTfnTqAO2L/j5HZgoM/3z82L7necsJ0pO9Tp0X1wil3PDLrkypTBRgVO2ExehEEvUycejZD3FuRaXpZZc3kw==} + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} hex-rgb@5.0.0: resolution: {integrity: sha512-NQO+lgVUCtHxZ792FodgW0zflK+ozS9X9dwGp9XvvmPlH7pyxd588cn24TD3rmPm/N0AIRXF10Otah8yKqGw4w==} @@ -3177,20 +3303,24 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - html-dom-parser@5.0.7: - resolution: {integrity: sha512-2YD2/yB0QgrlkBIn0CsGaRXC89E1gtuPVpiOGC52NTzPCC83n0WMdGD+5q7lpcKqbCpnWValQbovuy/NI/0kag==} + html-dom-parser@5.0.10: + resolution: {integrity: sha512-GwArYL3V3V8yU/mLKoFF7HlLBv80BZ2Ey1BzfVNRpAci0cEKhFHI/Qh8o8oyt3qlAMLlK250wsxLdYX4viedvg==} - html-react-parser@5.1.1: - resolution: {integrity: sha512-L5VK0rKN3VM7uzRH+4wxAL9elvHuCNDjyWKKjcCDR+YWW5Qr7WWSK7+e627DcePVAFi5IMqc+rAU8j/1DpC/Tw==} + html-react-parser@5.1.18: + resolution: {integrity: sha512-65BwC0zzrdeW96jB2FRr5f1ovBhRMpLPJNvwkY5kA8Ay5xdL9t/RH2/uUTM7p+cl5iM88i6dDk4LXtfMnRmaJQ==} peerDependencies: + '@types/react': 0.14 || 15 || 16 || 17 || 18 react: 0.14 || 15 || 16 || 17 || 18 + peerDependenciesMeta: + '@types/react': + optional: true html-tags@3.3.1: resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} engines: {node: '>=8'} - html-url-attributes@3.0.0: - resolution: {integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==} + html-url-attributes@3.0.1: + resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -3206,27 +3336,12 @@ packages: resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} engines: {node: '>= 0.6'} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@5.3.0: - resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - immutable@4.3.4: - resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + immutable@4.3.7: + resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -3253,15 +3368,11 @@ packages: inline-style-parser@0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} - inline-style-parser@0.2.2: - resolution: {integrity: sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==} + inline-style-parser@0.2.4: + resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - inquirer@8.2.6: - resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==} - engines: {node: '>=12.0.0'} - - internal-slot@1.0.6: - resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} internmap@2.0.3: @@ -3274,8 +3385,9 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -3295,16 +3407,17 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} - is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} - is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -3313,11 +3426,6 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -3350,15 +3458,12 @@ packages: engines: {node: '>=14.16'} hasBin: true - is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - - is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} - is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} is-node-process@1.2.0: @@ -3392,26 +3497,17 @@ packages: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} - is-reference@3.0.2: - resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} - is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} - is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - - is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} @@ -3425,30 +3521,28 @@ packages: resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} engines: {node: '>=0.10.0'} - is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} engines: {node: '>= 0.4'} - is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - - is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} is-what@4.1.16: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -3459,15 +3553,12 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - - itertools@2.2.3: - resolution: {integrity: sha512-TV4TDJ2FrLxhRJDX/AgdyI76i6cHi2Z1hml/d+HLcGVHxmgfxsLpoQBN2ZE9OizPt10+VW+LamLfCDASlnxvNg==} + iterator.prototype@1.1.3: + resolution: {integrity: sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==} + engines: {node: '>= 0.4'} - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} + itertools@2.3.2: + resolution: {integrity: sha512-urRg24zOOKt4qQHm3gzQLK5Mima/kMSP3DUfcVw05W3veUHxxqHPTEW08aKY9GIZm9CKvnULVqXdjZWNYalJHQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3476,13 +3567,9 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} hasBin: true json-buffer@3.0.1: @@ -3515,8 +3602,8 @@ packages: engines: {node: '>=6'} hasBin: true - jsonc-parser@3.2.1: - resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} @@ -3540,6 +3627,9 @@ packages: known-css-properties@0.29.0: resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==} + known-css-properties@0.34.0: + resolution: {integrity: sha512-tBECoUqNFbyAY4RrbqsBQqDFpGXAEbdD5QKr8kACx3+rnArmuuR22nKQWKazvp07N9yjTyDZaw/20UIH8tL9DQ==} + koa-compose@4.1.0: resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} @@ -3550,12 +3640,12 @@ packages: resolution: {integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==} engines: {node: '>= 10'} - koa@2.15.0: - resolution: {integrity: sha512-KEL/vU1knsoUvfP4MC4/GthpQrY/p6dzwaaGI6Rt4NQuFqkw3qrvsdYF5pz3wOfi7IGTvMPHC9aZIcUKYFNxsw==} + koa@2.15.3: + resolution: {integrity: sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} - language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} language-tags@1.0.9: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} @@ -3611,10 +3701,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -3625,10 +3711,6 @@ packages: lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - lru-cache@10.1.0: - resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} - engines: {node: 14 || >=16.14} - lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3639,9 +3721,8 @@ packages: lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} - magic-string@0.30.5: - resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} - engines: {node: '>=12'} + magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} @@ -3655,8 +3736,8 @@ packages: resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} engines: {node: '>=16'} - markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} @@ -3669,11 +3750,11 @@ packages: mdast-util-find-and-replace@3.0.1: resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} - mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} - mdast-util-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} mdast-util-gfm-footnote@2.0.0: resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} @@ -3690,11 +3771,11 @@ packages: mdast-util-gfm@3.0.0: resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} - mdast-util-mdx-expression@2.0.0: - resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==} + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - mdast-util-mdx-jsx@3.0.0: - resolution: {integrity: sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==} + mdast-util-mdx-jsx@3.1.3: + resolution: {integrity: sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==} mdast-util-mdx@3.0.0: resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} @@ -3702,11 +3783,11 @@ packages: mdast-util-mdxjs-esm@2.0.1: resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - mdast-util-phrasing@4.0.0: - resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==} + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - mdast-util-to-hast@13.1.0: - resolution: {integrity: sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==} + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} mdast-util-to-markdown@2.1.0: resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} @@ -3720,6 +3801,12 @@ packages: mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + mdn-data@2.10.0: + resolution: {integrity: sha512-qq7C3EtK3yJXMwz1zAab65pjl+UhohqMOctTgcqjLOWABqmwj+me02LSsCuEUxnst9X1lCBpoE0WArGKgdGDzw==} + + mdn-data@2.12.1: + resolution: {integrity: sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -3727,41 +3814,38 @@ packages: memoize-one@5.2.1: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} - meow@13.1.0: - resolution: {integrity: sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA==} + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} meow@8.1.2: resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} engines: {node: '>=10'} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - micromark-core-commonmark@2.0.0: - resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + micromark-core-commonmark@2.0.1: + resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} - micromark-extension-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - micromark-extension-gfm-footnote@2.0.0: - resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - micromark-extension-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - micromark-extension-gfm-table@2.0.0: - resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + micromark-extension-gfm-table@2.1.0: + resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} micromark-extension-gfm-tagfilter@2.0.0: resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - micromark-extension-gfm-task-list-item@2.0.1: - resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} micromark-extension-gfm@3.0.0: resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} @@ -3769,8 +3853,8 @@ packages: micromark-extension-mdx-expression@3.0.0: resolution: {integrity: sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==} - micromark-extension-mdx-jsx@3.0.0: - resolution: {integrity: sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==} + micromark-extension-mdx-jsx@3.0.1: + resolution: {integrity: sha512-vNuFb9czP8QCtAQcEJn0UJQJZA8Dk6DXKBqx+bg/w0WGuSxDxNr7hErW89tHUY31dUW4NqEOWwmEUNhjTFmHkg==} micromark-extension-mdx-md@2.0.0: resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} @@ -3787,8 +3871,8 @@ packages: micromark-factory-label@2.0.0: resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} - micromark-factory-mdx-expression@2.0.1: - resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==} + micromark-factory-mdx-expression@2.0.2: + resolution: {integrity: sha512-5E5I2pFzJyg2CtemqAbcyCktpHXuJbABnsb32wX2U8IQKhhVFBqkcZR5LRm1WVoFqa4kTueZK4abep7wdo9nrw==} micromark-factory-space@2.0.0: resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} @@ -3799,8 +3883,8 @@ packages: micromark-factory-whitespace@2.0.0: resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} - micromark-util-character@2.0.1: - resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} micromark-util-chunked@2.0.0: resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} @@ -3835,8 +3919,8 @@ packages: micromark-util-sanitize-uri@2.0.0: resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} - micromark-util-subtokenize@2.0.0: - resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + micromark-util-subtokenize@2.0.1: + resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} micromark-util-symbol@2.0.0: resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} @@ -3847,8 +3931,8 @@ packages: micromark@4.0.0: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -3859,14 +3943,6 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -3882,6 +3958,10 @@ packages: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -3889,32 +3969,26 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - modify-values@1.0.1: resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==} engines: {node: '>=0.10.0'} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.1.4: - resolution: {integrity: sha512-YyIQpfLqAJf/O1kYPWBSbDqjgv71kRBmEbGLxkkai1Btcs/LcxKiAwT1My3COa9J/vTh9Ua41B/ReuiW9cXmkw==} + msw@2.6.0: + resolution: {integrity: sha512-n3tx2w0MZ3H4pxY0ozrQ4sNPzK/dGtlr2cIIyuEsgq2Bhy4wvcW6ZH2w/gXM9+MEUY6HC1fWhqtcXDxVZr5Jxw==} engines: {node: '>=18'} hasBin: true peerDependencies: - typescript: '>= 4.7.x <= 5.3.x' + typescript: '>= 4.8.x' peerDependenciesMeta: typescript: optional: true - mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} @@ -3934,8 +4008,11 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -3952,29 +4029,19 @@ packages: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} - not@0.1.0: - resolution: {integrity: sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - npm-run-path@5.2.0: - resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - numbro@2.4.0: - resolution: {integrity: sha512-t6rVkO1CcKvffvOJJu/zMo70VIcQSR6w3AmIhfHGvmk4vHbNe6zHgomB0aWFAPZWM9JBVWBM0efJv9DBiRoSTA==} + numbro@2.5.0: + resolution: {integrity: sha512-xDcctDimhzko/e+y+Q2/8i3qNC9Svw1QgOkSkQoO0kIPI473tR9QRbo2KP88Ty9p8WbPy+3OpTaAIzehtuHq+A==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} @@ -3984,22 +4051,20 @@ packages: resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} engines: {node: '>= 0.4'} - object.entries@1.1.7: - resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} + object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} engines: {node: '>= 0.4'} - object.fromentries@2.0.7: - resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} - object.groupby@1.0.1: - resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} - - object.hasown@1.1.3: - resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} - object.values@1.1.7: - resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} engines: {node: '>= 0.4'} on-finished@2.4.1: @@ -4009,35 +4074,19 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - only@0.0.2: resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} - open@9.1.0: - resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} - engines: {node: '>=14.16'} + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - - outvariant@1.4.2: - resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==} + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} p-limit@1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} @@ -4090,8 +4139,8 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} - parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -4113,19 +4162,11 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - - path-to-regexp@6.2.1: - resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} path-type@3.0.0: resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} @@ -4139,16 +4180,17 @@ packages: resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} engines: {node: '>=12'} - periscopic@3.1.0: - resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} - - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -4161,14 +4203,18 @@ packages: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + postcss-media-query-parser@0.2.3: resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} - postcss-resolve-nested-selector@0.1.1: - resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} + postcss-resolve-nested-selector@0.1.6: + resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} - postcss-safe-parser@7.0.0: - resolution: {integrity: sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==} + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} engines: {node: '>=18.0'} peerDependencies: postcss: ^8.4.31 @@ -4179,15 +4225,15 @@ packages: peerDependencies: postcss: ^8.4.29 - postcss-selector-parser@6.0.15: - resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.33: - resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -4203,13 +4249,13 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.2.4: - resolution: {integrity: sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true - prism-react-renderer@2.3.1: - resolution: {integrity: sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==} + prism-react-renderer@2.4.0: + resolution: {integrity: sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw==} peerDependencies: react: '>=16.0.0' @@ -4219,12 +4265,15 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - property-information@6.4.1: - resolution: {integrity: sha512-OHYtXfu5aI2sS2LWFSN5rgJjrQ4pCy8i1jubJLe2QvMF8JJ++HXTUIVWFLfXJoaOfvYYjk2SN8J2wFUWIGXT4w==} + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4240,14 +4289,17 @@ packages: qr.js@0.0.0: resolution: {integrity: sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==} - qrcode@1.5.3: - resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} engines: {node: '>=10.13.0'} hasBin: true - query-string@8.1.0: - resolution: {integrity: sha512-BFQeWxJOZxZGix7y+SByG3F36dA0AbTy9o6pSmKFcFz7DAj0re9Frkty3saBn3nHo3D0oZJ/+rx3r8H8r8Jbpw==} - engines: {node: '>=14.16'} + query-string@9.1.1: + resolution: {integrity: sha512-MWkCOVIcJP9QSKU52Ngow6bsAWAPlPK2MludXvcrS2bGZSl+T1qX9MZvRIkqUIkGLJquMJHWfsT6eRqUpp4aWg==} + engines: {node: '>=18'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4256,8 +4308,8 @@ packages: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} - radash@11.0.0: - resolution: {integrity: sha512-CRWxTFTDff0IELGJ/zz58yY4BDgyI14qSM5OLNKbCItJrff7m7dXbVF0kWYVCXQtPb3SXIVhXvAImH6eT7VLSg==} + radash@12.1.0: + resolution: {integrity: sha512-b0Zcf09AhqKS83btmUeYBS8tFK7XL2e3RvLmZcm0sTdF1/UUlHSsjXdCcWNxe7yfmAlPve5ym0DmKGtTzP6kVQ==} engines: {node: '>=14.18.0'} react-click-away-listener@2.2.3: @@ -4266,19 +4318,19 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom@18.2.0: - resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: - react: ^18.2.0 + react: ^18.3.1 - react-hook-form@7.49.3: - resolution: {integrity: sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==} - engines: {node: '>=18', pnpm: '8'} + react-hook-form@7.53.1: + resolution: {integrity: sha512-6aiQeBda4zjcuaugWvim9WsGqisoUk+etmFEsSUMm451/Ic8L/UAb7sRtMj3V+Hdzm6mMjU1VhiSzYUZeBm0Vg==} + engines: {node: '>=18.0.0'} peerDependencies: - react: ^16.8.0 || ^17 || ^18 + react: ^16.8.0 || ^17 || ^18 || ^19 - react-hotkeys-hook@4.4.4: - resolution: {integrity: sha512-wzZmqb/Obr0ds9Myc1sIFPJ52GA/Eeg/vXBWV0HA1LvHlVAW5Va3KB0q6EZNlNSHQWscWZ2K8+6w0GYSie2o7A==} + react-hotkeys-hook@4.5.1: + resolution: {integrity: sha512-scAEJOh3Irm0g95NIn6+tQVf/OICCjsQsC9NBHfQws/Vxw4sfq1tDQut5fhTEvPraXhu/sHxRd9lOtxzyYuNAg==} peerDependencies: react: '>=16.8.1' react-dom: '>=16.8.1' @@ -4297,14 +4349,11 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - react-lifecycles-compat@3.0.4: - resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} - - react-loading-skeleton@3.3.1: - resolution: {integrity: sha512-NilqqwMh2v9omN7LteiDloEVpFyMIa0VGqF+ukqp0ncVlYu1sKYbYGX9JEl+GtOT9TKsh04zCHAbavnQ2USldA==} + react-loading-skeleton@3.5.0: + resolution: {integrity: sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==} peerDependencies: react: '>=16.8.0' @@ -4317,28 +4366,24 @@ packages: react-property@2.0.2: resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==} - react-qr-code@2.0.12: - resolution: {integrity: sha512-k+pzP5CKLEGBRwZsDPp98/CAJeXlsYRHM2iZn1Sd5Th/HnKhIZCSg27PXO58zk8z02RaEryg+60xa4vyywMJwg==} + react-qr-code@2.0.15: + resolution: {integrity: sha512-MkZcjEXqVKqXEIMVE0mbcGgDpkfSdd8zhuzXEl9QzYeNcw8Hq2oVIzDLWuZN2PQBwM5PWjc2S31K8Q1UbcFMfw==} peerDependencies: - react: ^16.x || ^17.x || ^18.x - react-native-svg: '*' - peerDependenciesMeta: - react-native-svg: - optional: true + react: '*' - react-refresh@0.14.0: - resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} - react-router-dom@6.21.3: - resolution: {integrity: sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==} + react-router-dom@6.27.0: + resolution: {integrity: sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' - react-router@6.21.3: - resolution: {integrity: sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==} + react-router@6.27.0: + resolution: {integrity: sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' @@ -4348,21 +4393,20 @@ packages: peerDependencies: react-dom: ^16.8.0 || ^17 || ^18 - react-smooth@2.0.5: - resolution: {integrity: sha512-BMP2Ad42tD60h0JW6BFaib+RJuV5dsXJK9Baxiv/HlNFjvRLqA9xrNKxVWnUIZPQfzUwGXIlU/dSYLU+54YGQA==} + react-smooth@4.0.1: + resolution: {integrity: sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==} peerDependencies: - prop-types: ^15.6.0 - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-transition-group@2.9.0: - resolution: {integrity: sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==} + react-transition-group@4.4.5: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: - react: '>=15.0.0' - react-dom: '>=15.0.0' + react: '>=16.6.0' + react-dom: '>=16.6.0' - react-virtualized-auto-sizer@1.0.21: - resolution: {integrity: sha512-RedZxj452+ITLfqIrR02BjvCaXV63YVIcVrvmruDZXFpJGazg4gHNs1AShPGVLvEuLGZdZ9AtkGKhWvzEujL8g==} + react-virtualized-auto-sizer@1.0.24: + resolution: {integrity: sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==} peerDependencies: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 @@ -4374,8 +4418,8 @@ packages: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react@18.2.0: - resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} read-pkg-up@3.0.0: @@ -4405,27 +4449,42 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} - recharts@2.10.4: - resolution: {integrity: sha512-/Q7/wdf8bW91lN3NEeCjL9RWfaiXQViJFgdnas4Eix/I8B9HAI3tHHK/CW/zDfgRMh4fzW1zlfjoz1IAapLO1Q==} + recharts@2.13.0: + resolution: {integrity: sha512-sbfxjWQ+oLWSZEWmvbq/DFVdeRLqqA6d0CDjKx2PkxVVdoXo16jvENCE+u/x7HxOO+/fwx//nYRwb8p8X6s/lQ==} engines: {node: '>=14'} peerDependencies: - prop-types: ^15.6.0 react: ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.0: + resolution: {integrity: sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==} + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} - reflect.getprototypeof@1.0.4: - resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} + reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} engines: {node: '>=4'} regenerate@1.4.2: @@ -4437,41 +4496,47 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + regexp.prototype.flags@1.5.3: + resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} engines: {node: '>= 0.4'} - regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + regexpu-core@6.1.1: + resolution: {integrity: sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==} engines: {node: '>=4'} - regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.11.2: + resolution: {integrity: sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==} hasBin: true - rehype-class-names@1.0.14: - resolution: {integrity: sha512-eFBt6Qxb7K77y6P82tUtN9rKpU7guWlaK4XA4RrrSFHkUTCvr2D3cgb9OR5d4t1AaGOvR59FH9nRwUnbpn9AEg==} + rehype-class-names@2.0.0: + resolution: {integrity: sha512-jldCIiAEvXKdq8hqr5f5PzNdIDkvHC6zfKhwta9oRoMu7bn0W7qLES/JrrjBvr9rKz3nJ8x4vY1EWI+dhjHVZQ==} rehype-raw@7.0.0: resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + remark-gfm@4.0.0: resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} - remark-mdx@3.0.0: - resolution: {integrity: sha512-O7yfjuC6ra3NHPbRVxfflafAj3LTwx3b73aBvkEFU5z4PsD6FD4vrqJAkE5iNGLz71GdjXfgRqm3SQ0h0VuE7g==} + remark-mdx@3.1.0: + resolution: {integrity: sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==} remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - remark-rehype@11.1.0: - resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} + remark-rehype@11.1.1: + resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==} remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - remove-accents@0.4.2: - resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -4484,6 +4549,9 @@ packages: require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -4500,10 +4568,6 @@ packages: resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true - restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -4513,23 +4577,14 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} - hasBin: true - - rollup-plugin-preserve-directives@0.3.1: - resolution: {integrity: sha512-Jn1gWU7G55A1sU6eFpXmwknfBasF0XbBzRqsE6nqrb/gun+mGV7nx++CwOSGPJQpFzFqvKm5U4XNKo3LTLi4Hg==} + rollup-plugin-preserve-directives@0.4.0: + resolution: {integrity: sha512-gx4nBxYm5BysmEQS+e2tAMrtFxrGvk+Pe5ppafRibQi0zlW7VYAbEGk6IKDw9sJGPdFWgVTE0o4BU4cdG0Fylg==} peerDependencies: rollup: npm:@rollup/wasm-node - run-applescript@5.0.0: - resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} - engines: {node: '>=12'} - - run-async@2.4.1: - resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} - engines: {node: '>=0.12.0'} + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -4537,8 +4592,8 @@ packages: rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - safe-array-concat@1.1.0: - resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} safe-buffer@5.1.2: @@ -4547,20 +4602,17 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-regex-test@1.0.2: - resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - sass@1.70.0: - resolution: {integrity: sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==} + sass@1.80.4: + resolution: {integrity: sha512-rhMQ2tSF5CsuuspvC94nPM9rToiAFw2h3JTrLlgmNw1MH79v8Cr3DH6KF6o6r+8oofY3iYVPUf66KzC8yuVN1w==} engines: {node: '>=14.0.0'} hasBin: true - scheduler@0.23.0: - resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} @@ -4570,20 +4622,20 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.2.0: - resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} setprototypeof@1.2.0: @@ -4603,11 +4655,9 @@ packages: shiki@0.14.7: resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} - side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} @@ -4628,8 +4678,8 @@ packages: snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} - source-map-js@1.0.2: - resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} source-map-support@0.5.21: @@ -4650,20 +4700,17 @@ packages: space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - spawn-command@0.0.2: - resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} - spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - spdx-exceptions@2.4.0: - resolution: {integrity: sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==} + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.16: - resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + spdx-license-ids@3.0.20: + resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} split-on-first@3.0.0: resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} @@ -4699,18 +4746,27 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string.prototype.matchall@4.0.10: - resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} - string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + string.prototype.matchall@4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -4718,8 +4774,8 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - stringify-entities@4.0.3: - resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} stringify-package@1.0.1: resolution: {integrity: sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==} @@ -4737,14 +4793,6 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -4753,14 +4801,14 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - style-to-js@1.1.10: - resolution: {integrity: sha512-VC7MBJa+y0RZhpnLKDPmVRLRswsASLmixkiZ5R8xZpNT9VyjeRzwnXd2pBzAWdgSGv/pCNNH01gPCCUsB9exYg==} + style-to-js@1.1.16: + resolution: {integrity: sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==} style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} - style-to-object@1.0.5: - resolution: {integrity: sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==} + style-to-object@1.0.8: + resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} stylelint-config-prettier-scss@1.0.0: resolution: {integrity: sha512-Gr2qLiyvJGKeDk0E/+awNTrZB/UtNVPLqCDOr07na/sLekZwm26Br6yYIeBYz3ulsEcQgs5j+2IIMXCC+wsaQA==} @@ -4769,40 +4817,40 @@ packages: peerDependencies: stylelint: '>=15.0.0' - stylelint-config-recommended-scss@14.0.0: - resolution: {integrity: sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==} + stylelint-config-recommended-scss@14.1.0: + resolution: {integrity: sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==} engines: {node: '>=18.12.0'} peerDependencies: postcss: ^8.3.3 - stylelint: ^16.0.2 + stylelint: ^16.6.1 peerDependenciesMeta: postcss: optional: true - stylelint-config-recommended@14.0.0: - resolution: {integrity: sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==} + stylelint-config-recommended@14.0.1: + resolution: {integrity: sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==} engines: {node: '>=18.12.0'} peerDependencies: - stylelint: ^16.0.0 + stylelint: ^16.1.0 - stylelint-config-standard-scss@13.0.0: - resolution: {integrity: sha512-WaLvkP689qSYUpJQPCo30TFJSSc3VzvvoWnrgp+7PpVby5o8fRUY1cZcP0sePZfjrFl9T8caGhcKg0GO34VDiQ==} + stylelint-config-standard-scss@13.1.0: + resolution: {integrity: sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==} engines: {node: '>=18.12.0'} peerDependencies: postcss: ^8.3.3 - stylelint: ^16.1.0 + stylelint: ^16.3.1 peerDependenciesMeta: postcss: optional: true - stylelint-config-standard@36.0.0: - resolution: {integrity: sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==} + stylelint-config-standard@36.0.1: + resolution: {integrity: sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==} engines: {node: '>=18.12.0'} peerDependencies: stylelint: ^16.1.0 - stylelint-scss@6.1.0: - resolution: {integrity: sha512-kCfK8TQzthGwb4vaZniZgxRsVbCM4ZckmT1b/H5m4FU3I8Dz0id9llKsy1NMp3XXqC8+OPD4rVKtUbSxXlJb5g==} + stylelint-scss@6.8.1: + resolution: {integrity: sha512-al+5eRb72bKrFyVAY+CLWKUMX+k+wsDCgyooSfhISJA2exqnJq1PX1iIIpdrvhu3GtJgNJZl9/BIW6EVSMCxdg==} engines: {node: '>=18.12.0'} peerDependencies: stylelint: ^16.0.2 @@ -4831,8 +4879,8 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-hyperlinks@3.0.0: - resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + supports-hyperlinks@3.1.0: + resolution: {integrity: sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==} engines: {node: '>=14.18'} supports-preserve-symlinks-flag@1.0.0: @@ -4845,27 +4893,27 @@ packages: svg-tags@1.0.0: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - svgo@3.2.0: - resolution: {integrity: sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==} + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} engines: {node: '>=14.0.0'} hasBin: true - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + synckit@0.9.2: + resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} engines: {node: ^14.18.0 || >=16.0.0} - systemjs@6.14.3: - resolution: {integrity: sha512-hQv45irdhXudAOr8r6SVSpJSGtogdGZUbJBRKCE5nsIS7tsxxvnIHqT4IOPWj+P+HcSzeWzHlGCGpmhPDIKe+w==} + systemjs@6.15.1: + resolution: {integrity: sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==} tabbable@6.2.0: resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - table@6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} + table@6.8.2: + resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} engines: {node: '>=10.0.0'} - terser@5.27.0: - resolution: {integrity: sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==} + terser@5.36.0: + resolution: {integrity: sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==} engines: {node: '>=10'} hasBin: true @@ -4885,20 +4933,8 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - - titleize@3.0.0: - resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} - engines: {node: '>=12'} - - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} @@ -4908,6 +4944,10 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -4919,17 +4959,17 @@ packages: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} - trough@2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - ts-api-utils@1.0.3: - resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} - engines: {node: '>=16.13.0'} + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} peerDependencies: typescript: '>=4.2.0' - tsconfck@3.0.1: - resolution: {integrity: sha512-7ppiBlF3UEddCLeI1JRx5m2Ryq+xk4JrZuq4EuYXykipebaq1dV0Fhgr1hb7CkmHt32QSgOZlcqVLEtHBG4/mg==} + tsconfck@3.1.4: + resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -4941,11 +4981,11 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@2.4.0: - resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} tsscmp@1.0.6: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} @@ -4979,38 +5019,39 @@ packages: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} - type-fest@4.10.1: - resolution: {integrity: sha512-7ZnJYTp6uc04uYRISWtiX3DSKB/fxNQT0B5o1OUeCqiQiwF+JC9+rJiZIDrPrNCLLuTqyQmh4VdQqh/ZOkv9MQ==} + type-fest@4.26.1: + resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} engines: {node: '>=16'} type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} engines: {node: '>= 0.4'} - typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typedoc@0.25.7: - resolution: {integrity: sha512-m6A6JjQRg39p2ZVRIN3NKXgrN8vzlHhOS+r9ymUYtcUP/TIQPvWSq7YgE5ZjASfv5Vd5BW5xrir6Gm2XNNcOow==} + typedoc@0.25.13: + resolution: {integrity: sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==} engines: {node: '>= 16'} hasBin: true peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x typesafe-i18n@5.26.2: resolution: {integrity: sha512-2QAriFmiY5JwUAJtG7yufoE/XZ1aFBY++wj7YFS2yo89a3jLBfKoWSdq5JfQYk1V2BS7V2c/u+KEcaCQoE65hw==} @@ -5030,27 +5071,27 @@ packages: engines: {node: '>=14.17'} hasBin: true - uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} engines: {node: '>=0.8.0'} hasBin: true unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} engines: {node: '>=4'} unicode-match-property-ecmascript@2.0.0: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} engines: {node: '>=4'} unicode-property-aliases-ecmascript@2.1.0: @@ -5061,11 +5102,8 @@ packages: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} engines: {node: '>=18'} - unified@10.1.2: - resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} - - unified@11.0.4: - resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} @@ -5076,12 +5114,6 @@ packages: unist-util-position@5.0.0: resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} - unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} - - unist-util-stringify-position@3.0.3: - resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} - unist-util-stringify-position@4.0.0: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} @@ -5091,12 +5123,12 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} - update-browserslist-db@1.0.13: - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -5104,6 +5136,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-breakpoint@4.0.1: resolution: {integrity: sha512-Fa5Duxv3BY3bw8kmj/lmryTETXVUmBQeYJpBgPJ2yJRiIaGVG8rlMNKQE+JS2rywCZHWaggVUz+ytbr7sH/yyg==} peerDependencies: @@ -5116,8 +5151,8 @@ packages: peerDependencies: react: '>=16.13' - use-sync-external-store@1.2.0: - resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==} + use-sync-external-store@1.2.2: + resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -5135,23 +5170,17 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vfile-location@5.0.2: - resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} - - vfile-message@3.1.4: - resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} vfile-message@4.0.2: resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} - vfile@5.3.7: - resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} - - vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - victory-vendor@36.8.2: - resolution: {integrity: sha512-NfSQi7ISCdBbDpn3b6rg+8RpFZmWIM9mcks48BbogHE2F6h1XKdA34oiCKP5hP1OGvTotDRzsexiJKzrK4Exuw==} + victory-vendor@36.9.2: + resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} vite-plugin-eslint@1.8.1: resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==} @@ -5164,16 +5193,16 @@ packages: peerDependencies: vite: '>=2.0.0-beta.69' - vite-tsconfig-paths@4.3.1: - resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} + vite-tsconfig-paths@4.3.2: + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} peerDependencies: vite: '*' peerDependenciesMeta: vite: optional: true - vite@5.0.12: - resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} + vite@5.4.10: + resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -5181,6 +5210,7 @@ packages: less: '*' lightningcss: ^1.21.0 sass: '*' + sass-embedded: '*' stylus: '*' sugarss: '*' terser: ^5.4.0 @@ -5193,6 +5223,8 @@ packages: optional: true sass: optional: true + sass-embedded: + optional: true stylus: optional: true sugarss: @@ -5206,27 +5238,25 @@ packages: vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + which-builtin-type@1.1.4: + resolution: {integrity: sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==} engines: {node: '>= 0.4'} - which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} engines: {node: '>= 0.4'} which@1.3.1: @@ -5242,6 +5272,10 @@ packages: resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} engines: {node: '>=12'} + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} @@ -5264,12 +5298,12 @@ packages: resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ws@8.5.0: - resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 + utf-8-validate: '>=5.0.2' peerDependenciesMeta: bufferutil: optional: true @@ -5321,19 +5355,23 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - ylru@1.3.2: - resolution: {integrity: sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==} + ylru@1.4.0: + resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} engines: {node: '>= 4.0.0'} yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + yoctocolors-cjs@2.1.2: + resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} + engines: {node: '>=18'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zustand@4.5.0: - resolution: {integrity: sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==} + zustand@4.5.5: + resolution: {integrity: sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==} engines: {node: '>=12.7.0'} peerDependencies: '@types/react': '>=16.8' @@ -5352,768 +5390,679 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} + '@adraffy/ens-normalize@1.10.1': {} - '@adraffy/ens-normalize@1.10.0': {} - - '@ampproject/remapping@2.2.1': + '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.23.5': + '@babel/code-frame@7.26.0': dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - - '@babel/compat-data@7.23.5': {} - - '@babel/core@7.23.9': - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) - '@babel/helpers': 7.23.9 - '@babel/parser': 7.23.9 - '@babel/template': 7.23.9 - '@babel/traverse': 7.23.9 - '@babel/types': 7.23.9 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.0': {} + + '@babel/core@7.26.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.3.4 + debug: 4.3.7 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.23.6': + '@babel/generator@7.26.0': dependencies: - '@babel/types': 7.23.6 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.22 - jsesc: 2.5.2 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 - '@babel/helper-annotate-as-pure@7.22.5': + '@babel/helper-annotate-as-pure@7.25.9': dependencies: - '@babel/types': 7.23.6 + '@babel/types': 7.26.0 - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': + '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9': dependencies: - '@babel/types': 7.23.6 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color - '@babel/helper-compilation-targets@7.23.6': + '@babel/helper-compilation-targets@7.25.9': dependencies: - '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.23.5 - browserslist: 4.22.2 + '@babel/compat-data': 7.26.0 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.9) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.25.9 semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.9)': + '@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.1.1 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.4.4(@babel/core@7.23.9)': + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - debug: 4.3.4 + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + debug: 4.3.7 lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: - supports-color - '@babel/helper-define-polyfill-provider@0.5.0(@babel/core@7.23.9)': + '@babel/helper-member-expression-to-functions@7.25.9': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.8 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 transitivePeerDependencies: - supports-color - '@babel/helper-environment-visitor@7.22.20': {} - - '@babel/helper-function-name@7.23.0': - dependencies: - '@babel/template': 7.22.15 - '@babel/types': 7.23.6 - - '@babel/helper-hoist-variables@7.22.5': - dependencies: - '@babel/types': 7.23.6 - - '@babel/helper-member-expression-to-functions@7.23.0': - dependencies: - '@babel/types': 7.23.6 - - '@babel/helper-module-imports@7.22.15': - dependencies: - '@babel/types': 7.23.6 - - '@babel/helper-module-transforms@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - - '@babel/helper-optimise-call-expression@7.22.5': - dependencies: - '@babel/types': 7.23.6 - - '@babel/helper-plugin-utils@7.22.5': {} - - '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.20 - - '@babel/helper-replace-supers@7.22.20(@babel/core@7.23.9)': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - - '@babel/helper-simple-access@7.22.5': - dependencies: - '@babel/types': 7.23.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/types': 7.23.6 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/helper-split-export-declaration@7.22.6': + '@babel/helper-optimise-call-expression@7.25.9': dependencies: - '@babel/types': 7.23.6 - - '@babel/helper-string-parser@7.23.4': {} - - '@babel/helper-validator-identifier@7.22.20': {} + '@babel/types': 7.26.0 - '@babel/helper-validator-option@7.23.5': {} + '@babel/helper-plugin-utils@7.25.9': {} - '@babel/helper-wrap-function@7.22.20': + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.22.15 - '@babel/types': 7.23.6 - - '@babel/helpers@7.23.9': - dependencies: - '@babel/template': 7.23.9 - '@babel/traverse': 7.23.9 - '@babel/types': 7.23.9 + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.25.9 transitivePeerDependencies: - supports-color - '@babel/highlight@7.23.4': + '@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - - '@babel/parser@7.23.6': - dependencies: - '@babel/types': 7.23.6 - - '@babel/parser@7.23.9': - dependencies: - '@babel/types': 7.23.9 + '@babel/core': 7.26.0 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.23.9)': + '@babel/helper-simple-access@7.25.9': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.23.9)': + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.9) + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.7(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-string-parser@7.25.9': {} - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option@7.25.9': {} - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.9)': + '@babel/helper-wrap-function@7.25.9': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.9)': + '@babel/helpers@7.26.0': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.9)': + '@babel/parser@7.26.1': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/types': 7.26.0 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.9)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.9)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.9)': + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.9)': + '@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.9)': + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.9)': + '@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.9)': + '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-async-generator-functions@7.23.7(@babel/core@7.23.9)': + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/traverse': 7.25.9 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/template': 7.25.9 - '@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-classes@7.23.8(@babel/core@7.23.9)': + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.9) - '@babel/helper-split-export-declaration': 7.22.6 - globals: 11.12.0 + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/template': 7.22.15 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-for-of@7.23.6(@babel/core@7.23.9)': + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-literals@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-simple-access': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-simple-access': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.9)': + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-new-target@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.23.9 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-object-super@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-parameters@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.23.9)': + '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + regenerator-transform: 0.15.2 - '@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-react-jsx-self@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-react-jsx-source@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.23.9)': + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - regenerator-transform: 0.15.2 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - - '@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.23.9)': - dependencies: - '@babel/core': 7.23.9 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.9) - '@babel/helper-plugin-utils': 7.22.5 - - '@babel/preset-env@7.23.8(@babel/core@7.23.9)': - dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.23.9 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.7(@babel/core@7.23.9) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.9) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.9) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.9) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.9) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.9) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.9) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.9) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.9) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.9) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.23.9) - '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-async-generator-functions': 7.23.7(@babel/core@7.23.9) - '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-classes': 7.23.8(@babel/core@7.23.9) - '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-for-of': 7.23.6(@babel/core@7.23.9) - '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-modules-systemjs': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.23.9) - '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.23.9) - '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.23.9) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.23.9) - babel-plugin-polyfill-corejs2: 0.4.8(@babel/core@7.23.9) - babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.23.9) - babel-plugin-polyfill-regenerator: 0.5.5(@babel/core@7.23.9) - core-js-compat: 3.35.1 + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/preset-env@7.26.0(@babel/core@7.26.0)': + dependencies: + '@babel/compat-data': 7.26.0 + '@babel/core': 7.26.0 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.0) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.26.0) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.26.0) + core-js-compat: 3.38.1 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.9)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/types': 7.23.6 + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/types': 7.26.0 esutils: 2.0.3 - '@babel/regjsgen@0.8.0': {} - - '@babel/runtime@7.23.8': + '@babel/runtime@7.26.0': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.22.15': + '@babel/template@7.25.9': dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.23.6 - '@babel/types': 7.23.6 + '@babel/code-frame': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 - '@babel/template@7.23.9': + '@babel/traverse@7.25.9': dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.23.9 - '@babel/types': 7.23.9 - - '@babel/traverse@7.23.7': - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.6 - '@babel/types': 7.23.6 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/traverse@7.23.9': - dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.9 - '@babel/types': 7.23.9 - debug: 4.3.4 + '@babel/code-frame': 7.26.0 + '@babel/generator': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + debug: 4.3.7 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.23.6': + '@babel/types@7.26.0': dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - - '@babel/types@7.23.9': - dependencies: - '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 '@bundled-es-modules/cookie@2.0.0': dependencies: @@ -6123,189 +6072,264 @@ snapshots: dependencies: statuses: 2.0.1 - '@csstools/css-parser-algorithms@2.5.0(@csstools/css-tokenizer@2.2.3)': + '@bundled-es-modules/tough-cookie@0.1.6': + dependencies: + '@types/tough-cookie': 4.0.5 + tough-cookie: 4.1.4 + + '@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1)': dependencies: - '@csstools/css-tokenizer': 2.2.3 + '@csstools/css-tokenizer': 2.4.1 - '@csstools/css-tokenizer@2.2.3': {} + '@csstools/css-tokenizer@2.4.1': {} - '@csstools/media-query-list-parser@2.1.7(@csstools/css-parser-algorithms@2.5.0(@csstools/css-tokenizer@2.2.3))(@csstools/css-tokenizer@2.2.3)': + '@csstools/media-query-list-parser@2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1)': dependencies: - '@csstools/css-parser-algorithms': 2.5.0(@csstools/css-tokenizer@2.2.3) - '@csstools/css-tokenizer': 2.2.3 + '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) + '@csstools/css-tokenizer': 2.4.1 - '@csstools/selector-specificity@3.0.1(postcss-selector-parser@6.0.15)': + '@csstools/selector-specificity@3.1.1(postcss-selector-parser@6.1.2)': dependencies: - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.1.2 - '@emotion/babel-plugin@11.11.0': + '@emotion/babel-plugin@11.12.0': dependencies: - '@babel/helper-module-imports': 7.22.15 - '@babel/runtime': 7.23.8 - '@emotion/hash': 0.9.1 - '@emotion/memoize': 0.8.1 - '@emotion/serialize': 1.1.3 + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.26.0 + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/serialize': 1.3.2 babel-plugin-macros: 3.1.0 convert-source-map: 1.9.0 escape-string-regexp: 4.0.0 find-root: 1.1.0 source-map: 0.5.7 stylis: 4.2.0 + transitivePeerDependencies: + - supports-color - '@emotion/cache@11.11.0': + '@emotion/cache@11.13.1': dependencies: - '@emotion/memoize': 0.8.1 - '@emotion/sheet': 1.2.2 - '@emotion/utils': 1.2.1 - '@emotion/weak-memoize': 0.3.1 + '@emotion/memoize': 0.9.0 + '@emotion/sheet': 1.4.0 + '@emotion/utils': 1.4.1 + '@emotion/weak-memoize': 0.4.0 stylis: 4.2.0 - '@emotion/hash@0.9.1': {} - - '@emotion/is-prop-valid@0.8.8': - dependencies: - '@emotion/memoize': 0.7.4 - optional: true + '@emotion/hash@0.9.2': {} - '@emotion/is-prop-valid@1.2.1': + '@emotion/is-prop-valid@1.3.1': dependencies: - '@emotion/memoize': 0.8.1 - - '@emotion/memoize@0.7.4': - optional: true + '@emotion/memoize': 0.9.0 - '@emotion/memoize@0.8.1': {} + '@emotion/memoize@0.9.0': {} - '@emotion/react@11.11.3(@types/react@18.2.48)(react@18.2.0)': + '@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.8 - '@emotion/babel-plugin': 11.11.0 - '@emotion/cache': 11.11.0 - '@emotion/serialize': 1.1.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) - '@emotion/utils': 1.2.1 - '@emotion/weak-memoize': 0.3.1 + '@babel/runtime': 7.26.0 + '@emotion/babel-plugin': 11.12.0 + '@emotion/cache': 11.13.1 + '@emotion/serialize': 1.3.2 + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) + '@emotion/utils': 1.4.1 + '@emotion/weak-memoize': 0.4.0 hoist-non-react-statics: 3.3.2 - react: 18.2.0 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.12 + transitivePeerDependencies: + - supports-color - '@emotion/serialize@1.1.3': + '@emotion/serialize@1.3.2': dependencies: - '@emotion/hash': 0.9.1 - '@emotion/memoize': 0.8.1 - '@emotion/unitless': 0.8.1 - '@emotion/utils': 1.2.1 + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/unitless': 0.10.0 + '@emotion/utils': 1.4.1 csstype: 3.1.3 - '@emotion/sheet@1.2.2': {} + '@emotion/sheet@1.4.0': {} - '@emotion/styled@11.11.0(@emotion/react@11.11.3(@types/react@18.2.48)(react@18.2.0))(@types/react@18.2.48)(react@18.2.0)': + '@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.8 - '@emotion/babel-plugin': 11.11.0 - '@emotion/is-prop-valid': 1.2.1 - '@emotion/react': 11.11.3(@types/react@18.2.48)(react@18.2.0) - '@emotion/serialize': 1.1.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) - '@emotion/utils': 1.2.1 - react: 18.2.0 + '@babel/runtime': 7.26.0 + '@emotion/babel-plugin': 11.12.0 + '@emotion/is-prop-valid': 1.3.1 + '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1) + '@emotion/serialize': 1.3.2 + '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1) + '@emotion/utils': 1.4.1 + react: 18.3.1 optionalDependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.12 + transitivePeerDependencies: + - supports-color - '@emotion/unitless@0.8.1': {} + '@emotion/unitless@0.10.0': {} - '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0)': + '@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1)': dependencies: - react: 18.2.0 + react: 18.3.1 + + '@emotion/utils@1.4.1': {} + + '@emotion/weak-memoize@0.4.0': {} + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.24.0': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.24.0': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.24.0': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.24.0': + optional: true - '@emotion/utils@1.2.1': {} + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.24.0': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.24.0': + optional: true - '@emotion/weak-memoize@0.3.1': {} + '@esbuild/freebsd-arm64@0.21.5': + optional: true - '@esbuild/aix-ppc64@0.19.12': + '@esbuild/freebsd-arm64@0.24.0': optional: true - '@esbuild/android-arm64@0.19.12': + '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/android-arm@0.19.12': + '@esbuild/freebsd-x64@0.24.0': optional: true - '@esbuild/android-x64@0.19.12': + '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.19.12': + '@esbuild/linux-arm64@0.24.0': optional: true - '@esbuild/darwin-x64@0.19.12': + '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.19.12': + '@esbuild/linux-arm@0.24.0': optional: true - '@esbuild/freebsd-x64@0.19.12': + '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-arm64@0.19.12': + '@esbuild/linux-ia32@0.24.0': optional: true - '@esbuild/linux-arm@0.19.12': + '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-ia32@0.19.12': + '@esbuild/linux-loong64@0.24.0': optional: true - '@esbuild/linux-loong64@0.19.12': + '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.19.12': + '@esbuild/linux-mips64el@0.24.0': optional: true - '@esbuild/linux-ppc64@0.19.12': + '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.19.12': + '@esbuild/linux-ppc64@0.24.0': optional: true - '@esbuild/linux-s390x@0.19.12': + '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-x64@0.19.12': + '@esbuild/linux-riscv64@0.24.0': optional: true - '@esbuild/netbsd-x64@0.19.12': + '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/openbsd-x64@0.19.12': + '@esbuild/linux-s390x@0.24.0': optional: true - '@esbuild/sunos-x64@0.19.12': + '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/win32-arm64@0.19.12': + '@esbuild/linux-x64@0.24.0': optional: true - '@esbuild/win32-ia32@0.19.12': + '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.19.12': + '@esbuild/netbsd-x64@0.24.0': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.56.0)': + '@esbuild/openbsd-arm64@0.24.0': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.24.0': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.24.0': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.24.0': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.24.0': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.24.0': + optional: true + + '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': dependencies: - eslint: 8.56.0 + eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} + '@eslint-community/regexpp@4.12.1': {} '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.7 espree: 9.6.1 globals: 13.24.0 - ignore: 5.3.0 + ignore: 5.3.2 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -6313,205 +6337,225 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.56.0': {} + '@eslint/js@8.57.1': {} - '@floating-ui/core@1.6.0': + '@floating-ui/core@1.6.8': dependencies: - '@floating-ui/utils': 0.2.1 + '@floating-ui/utils': 0.2.8 - '@floating-ui/dom@1.6.0': + '@floating-ui/dom@1.6.11': dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.1 + '@floating-ui/core': 1.6.8 + '@floating-ui/utils': 0.2.8 - '@floating-ui/react-dom@2.0.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/dom': 1.6.0 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@floating-ui/dom': 1.6.11 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@floating-ui/react@0.26.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@floating-ui/react@0.26.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@floating-ui/react-dom': 2.0.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@floating-ui/utils': 0.2.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/utils': 0.2.8 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) tabbable: 6.2.0 - '@floating-ui/utils@0.2.1': {} + '@floating-ui/utils@0.2.8': {} '@github/webauthn-json@2.1.1': {} - '@hookform/devtools@4.3.1(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@hookform/devtools@4.3.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@emotion/react': 11.11.3(@types/react@18.2.48)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.3(@types/react@18.2.48)(react@18.2.0))(@types/react@18.2.48)(react@18.2.0) - '@types/lodash': 4.14.202 - little-state-machine: 4.8.0(react@18.2.0) + '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1) + '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1))(@types/react@18.3.12)(react@18.3.1) + '@types/lodash': 4.17.12 + little-state-machine: 4.8.0(react@18.3.1) lodash: 4.17.21 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-simple-animate: 3.5.2(react-dom@18.2.0(react@18.2.0)) - use-deep-compare-effect: 1.8.1(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-simple-animate: 3.5.2(react-dom@18.3.1(react@18.3.1)) + use-deep-compare-effect: 1.8.1(react@18.3.1) uuid: 8.3.2 transitivePeerDependencies: - '@types/react' + - supports-color - '@hookform/resolvers@3.3.4(react-hook-form@7.49.3(react@18.2.0))': + '@hookform/resolvers@3.9.1(react-hook-form@7.53.1(react@18.3.1))': dependencies: - react-hook-form: 7.49.3(react@18.2.0) + react-hook-form: 7.53.1(react@18.3.1) - '@humanwhocodes/config-array@0.11.14': + '@humanwhocodes/config-array@0.13.0': dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4 + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.7 minimatch: 3.1.2 transitivePeerDependencies: - supports-color '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.2': {} + '@humanwhocodes/object-schema@2.0.3': {} '@hutson/parse-repository-url@3.0.2': {} - '@isaacs/cliui@8.0.2': + '@inquirer/confirm@5.0.1(@types/node@20.17.2)': dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + '@inquirer/core': 10.0.1(@types/node@20.17.2) + '@inquirer/type': 3.0.0(@types/node@20.17.2) + '@types/node': 20.17.2 - '@jridgewell/gen-mapping@0.3.3': + '@inquirer/core@10.0.1(@types/node@20.17.2)': dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.22 + '@inquirer/figures': 1.0.7 + '@inquirer/type': 3.0.0(@types/node@20.17.2) + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + transitivePeerDependencies: + - '@types/node' - '@jridgewell/resolve-uri@3.1.1': {} + '@inquirer/figures@1.0.7': {} - '@jridgewell/set-array@1.1.2': {} + '@inquirer/type@3.0.0(@types/node@20.17.2)': + dependencies: + '@types/node': 20.17.2 - '@jridgewell/source-map@0.3.5': + '@jridgewell/gen-mapping@0.3.5': dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.22 + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 - '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/trace-mapping@0.3.22': + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} - '@ladle/react-context@1.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@jridgewell/trace-mapping@0.3.25': dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 - '@ladle/react@4.0.2(@types/node@20.11.7)(@types/react@18.2.48)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(sass@1.70.0)(terser@5.27.0)(typescript@5.3.3)': + '@ladle/react-context@1.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/code-frame': 7.23.5 - '@babel/core': 7.23.9 - '@babel/generator': 7.23.6 - '@babel/parser': 7.23.6 - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.7 - '@babel/types': 7.23.6 - '@ladle/react-context': 1.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - '@mdx-js/mdx': 3.0.0 - '@mdx-js/react': 3.0.0(@types/react@18.2.48)(react@18.2.0) - '@vitejs/plugin-react': 4.2.1(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) - '@vitejs/plugin-react-swc': 3.5.0(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) - axe-core: 4.8.3 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@ladle/react@4.1.2(@types/node@20.17.2)(@types/react@18.3.12)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.4)(terser@5.36.0)(typescript@5.3.3)': + dependencies: + '@babel/code-frame': 7.26.0 + '@babel/core': 7.26.0 + '@babel/generator': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + '@ladle/react-context': 1.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mdx-js/mdx': 3.1.0(acorn@8.14.0) + '@mdx-js/react': 3.1.0(@types/react@18.3.12)(react@18.3.1) + '@vitejs/plugin-react': 4.3.3(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) + '@vitejs/plugin-react-swc': 3.7.1(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) + axe-core: 4.10.2 boxen: 7.1.1 - chokidar: 3.5.3 + chokidar: 3.6.0 classnames: 2.5.1 - commander: 11.1.0 + commander: 12.1.0 cross-spawn: 7.0.3 - debug: 4.3.4 - get-port: 7.0.0 - globby: 14.0.0 + debug: 4.3.7 + get-port: 7.1.0 + globby: 14.0.2 history: 5.3.0 - koa: 2.15.0 + koa: 2.15.3 koa-connect: 2.1.0 lodash.merge: 4.6.2 - msw: 2.1.4(typescript@5.3.3) - open: 9.1.0 - prism-react-renderer: 2.3.1(react@18.2.0) + msw: 2.6.0(@types/node@20.17.2)(typescript@5.3.3) + open: 10.1.0 + prism-react-renderer: 2.4.0(react@18.3.1) prop-types: 15.8.1 - query-string: 8.1.0 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-hotkeys-hook: 4.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react-inspector: 6.0.2(react@18.2.0) - rehype-class-names: 1.0.14 + query-string: 9.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-hotkeys-hook: 4.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-inspector: 6.0.2(react@18.3.1) + rehype-class-names: 2.0.0 rehype-raw: 7.0.0 remark-gfm: 4.0.0 source-map: 0.7.4 - vfile: 6.0.1 - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) - vite-tsconfig-paths: 4.3.1(typescript@5.3.3)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)) + vfile: 6.0.3 + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) + vite-tsconfig-paths: 4.3.2(typescript@5.3.3)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)) transitivePeerDependencies: - '@swc/helpers' - '@types/node' - '@types/react' + - acorn - less - lightningcss - sass + - sass-embedded - stylus - sugarss - supports-color - terser - typescript - '@mdx-js/mdx@3.0.0': + '@mdx-js/mdx@3.1.0(acorn@8.14.0)': dependencies: - '@types/estree': 1.0.5 - '@types/estree-jsx': 1.0.3 - '@types/hast': 3.0.3 - '@types/mdx': 2.0.10 + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 collapse-white-space: 2.1.0 devlop: 1.1.0 - estree-util-build-jsx: 3.0.1 estree-util-is-identifier-name: 3.0.0 - estree-util-to-js: 2.0.0 + estree-util-scope: 1.0.0 estree-walker: 3.0.3 - hast-util-to-estree: 3.1.0 - hast-util-to-jsx-runtime: 2.3.0 + hast-util-to-jsx-runtime: 2.3.2 markdown-extensions: 2.0.0 - periscopic: 3.1.0 - remark-mdx: 3.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.0(acorn@8.14.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.0 remark-parse: 11.0.0 - remark-rehype: 11.1.0 + remark-rehype: 11.1.1 source-map: 0.7.4 - unified: 11.0.4 + unified: 11.0.5 unist-util-position-from-estree: 2.0.0 unist-util-stringify-position: 4.0.0 unist-util-visit: 5.0.0 - vfile: 6.0.1 + vfile: 6.0.3 transitivePeerDependencies: + - acorn - supports-color - '@mdx-js/react@3.0.0(@types/react@18.2.48)(react@18.2.0)': + '@mdx-js/react@3.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: - '@types/mdx': 2.0.10 - '@types/react': 18.2.48 - react: 18.2.0 + '@types/mdx': 2.0.13 + '@types/react': 18.3.12 + react: 18.3.1 '@metamask/detect-provider@2.0.0': {} - '@mswjs/cookies@1.1.0': {} - - '@mswjs/interceptors@0.25.14': + '@mswjs/interceptors@0.36.6': dependencies: '@open-draft/deferred-promise': 2.2.0 '@open-draft/logger': 0.3.0 '@open-draft/until': 2.1.0 is-node-process: 1.2.0 - outvariant: 1.4.2 + outvariant: 1.4.3 strict-event-emitter: 0.5.1 '@noble/curves@1.2.0': @@ -6530,120 +6574,183 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.16.0 + fastq: 1.17.1 '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': dependencies: is-node-process: 1.2.0 - outvariant: 1.4.2 + outvariant: 1.4.3 '@open-draft/until@2.1.0': {} - '@pkgjs/parseargs@0.11.0': + '@parcel/watcher-android-arm64@2.4.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.4.1': + optional: true + + '@parcel/watcher-darwin-x64@2.4.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.4.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.4.1': optional: true + '@parcel/watcher-linux-arm64-glibc@2.4.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.4.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.4.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.4.1': + optional: true + + '@parcel/watcher-win32-arm64@2.4.1': + optional: true + + '@parcel/watcher-win32-ia32@2.4.1': + optional: true + + '@parcel/watcher-win32-x64@2.4.1': + optional: true + + '@parcel/watcher@2.4.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.4.1 + '@parcel/watcher-darwin-arm64': 2.4.1 + '@parcel/watcher-darwin-x64': 2.4.1 + '@parcel/watcher-freebsd-x64': 2.4.1 + '@parcel/watcher-linux-arm-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-glibc': 2.4.1 + '@parcel/watcher-linux-arm64-musl': 2.4.1 + '@parcel/watcher-linux-x64-glibc': 2.4.1 + '@parcel/watcher-linux-x64-musl': 2.4.1 + '@parcel/watcher-win32-arm64': 2.4.1 + '@parcel/watcher-win32-ia32': 2.4.1 + '@parcel/watcher-win32-x64': 2.4.1 + '@pkgr/core@0.1.1': {} '@reach/observe-rect@1.2.0': {} - '@react-rxjs/core@0.10.7(react@18.2.0)(rxjs@7.8.1)': + '@react-rxjs/core@0.10.7(react@18.3.1)(rxjs@7.8.1)': dependencies: '@rx-state/core': 0.1.4(rxjs@7.8.1) - react: 18.2.0 + react: 18.3.1 rxjs: 7.8.1 - use-sync-external-store: 1.2.0(react@18.2.0) + use-sync-external-store: 1.2.2(react@18.3.1) - '@remix-run/router@1.14.2': {} + '@remix-run/router@1.20.0': {} '@rollup/pluginutils@4.2.1': dependencies: estree-walker: 2.0.2 picomatch: 2.3.1 - '@rollup/wasm-node@4.24.0': + '@rollup/pluginutils@5.1.3(@rollup/wasm-node@4.24.2)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: '@rollup/wasm-node@4.24.2' + + '@rollup/wasm-node@4.24.2': dependencies: '@types/estree': 1.0.6 optionalDependencies: fsevents: 2.3.3 + '@rtsao/scc@1.1.0': {} + '@rx-state/core@0.1.4(rxjs@7.8.1)': dependencies: rxjs: 7.8.1 - '@sindresorhus/merge-streams@1.0.0': {} + '@sindresorhus/merge-streams@2.3.0': {} - '@stablelib/base64@1.0.1': {} + '@stablelib/base64@2.0.0': {} - '@stablelib/binary@1.0.1': + '@stablelib/binary@2.0.0': dependencies: - '@stablelib/int': 1.0.1 + '@stablelib/int': 2.0.0 - '@stablelib/bytes@1.0.1': {} + '@stablelib/bytes@2.0.0': {} - '@stablelib/int@1.0.1': {} + '@stablelib/int@2.0.0': {} - '@stablelib/keyagreement@1.0.1': + '@stablelib/keyagreement@2.0.0': dependencies: - '@stablelib/bytes': 1.0.1 + '@stablelib/bytes': 2.0.0 - '@stablelib/random@1.0.2': + '@stablelib/random@2.0.0': dependencies: - '@stablelib/binary': 1.0.1 - '@stablelib/wipe': 1.0.1 + '@stablelib/binary': 2.0.0 + '@stablelib/wipe': 2.0.0 - '@stablelib/wipe@1.0.1': {} + '@stablelib/wipe@2.0.0': {} - '@stablelib/x25519@1.0.3': + '@stablelib/x25519@2.0.0': dependencies: - '@stablelib/keyagreement': 1.0.1 - '@stablelib/random': 1.0.2 - '@stablelib/wipe': 1.0.1 + '@stablelib/keyagreement': 2.0.0 + '@stablelib/random': 2.0.0 + '@stablelib/wipe': 2.0.0 - '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.23.9)': + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 + '@babel/core': 7.26.0 - '@svgr/babel-preset@8.1.0(@babel/core@7.23.9)': + '@svgr/babel-preset@8.1.0(@babel/core@7.26.0)': dependencies: - '@babel/core': 7.23.9 - '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.23.9) - '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.23.9) - '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.26.0) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.26.0) '@svgr/cli@8.1.0(typescript@5.3.3)': dependencies: @@ -6663,8 +6770,8 @@ snapshots: '@svgr/core@8.1.0(typescript@5.3.3)': dependencies: - '@babel/core': 7.23.9 - '@svgr/babel-preset': 8.1.0(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.26.0) camelcase: 6.3.0 cosmiconfig: 8.3.6(typescript@5.3.3) snake-case: 3.0.4 @@ -6674,13 +6781,13 @@ snapshots: '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - '@babel/types': 7.23.6 + '@babel/types': 7.26.0 entities: 4.5.0 '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.3.3))': dependencies: - '@babel/core': 7.23.9 - '@svgr/babel-preset': 8.1.0(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.26.0) '@svgr/core': 8.1.0(typescript@5.3.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 @@ -6698,120 +6805,122 @@ snapshots: '@svgr/core': 8.1.0(typescript@5.3.3) cosmiconfig: 8.3.6(typescript@5.3.3) deepmerge: 4.3.1 - svgo: 3.2.0 + svgo: 3.3.2 transitivePeerDependencies: - typescript - '@swc/core-darwin-arm64@1.3.106': + '@swc/core-darwin-arm64@1.7.40': optional: true - '@swc/core-darwin-x64@1.3.106': + '@swc/core-darwin-x64@1.7.40': optional: true - '@swc/core-linux-arm-gnueabihf@1.3.106': + '@swc/core-linux-arm-gnueabihf@1.7.40': optional: true - '@swc/core-linux-arm64-gnu@1.3.106': + '@swc/core-linux-arm64-gnu@1.7.40': optional: true - '@swc/core-linux-arm64-musl@1.3.106': + '@swc/core-linux-arm64-musl@1.7.40': optional: true - '@swc/core-linux-x64-gnu@1.3.106': + '@swc/core-linux-x64-gnu@1.7.40': optional: true - '@swc/core-linux-x64-musl@1.3.106': + '@swc/core-linux-x64-musl@1.7.40': optional: true - '@swc/core-win32-arm64-msvc@1.3.106': + '@swc/core-win32-arm64-msvc@1.7.40': optional: true - '@swc/core-win32-ia32-msvc@1.3.106': + '@swc/core-win32-ia32-msvc@1.7.40': optional: true - '@swc/core-win32-x64-msvc@1.3.106': + '@swc/core-win32-x64-msvc@1.7.40': optional: true - '@swc/core@1.3.106': + '@swc/core@1.7.40': dependencies: - '@swc/counter': 0.1.2 - '@swc/types': 0.1.5 + '@swc/counter': 0.1.3 + '@swc/types': 0.1.13 optionalDependencies: - '@swc/core-darwin-arm64': 1.3.106 - '@swc/core-darwin-x64': 1.3.106 - '@swc/core-linux-arm-gnueabihf': 1.3.106 - '@swc/core-linux-arm64-gnu': 1.3.106 - '@swc/core-linux-arm64-musl': 1.3.106 - '@swc/core-linux-x64-gnu': 1.3.106 - '@swc/core-linux-x64-musl': 1.3.106 - '@swc/core-win32-arm64-msvc': 1.3.106 - '@swc/core-win32-ia32-msvc': 1.3.106 - '@swc/core-win32-x64-msvc': 1.3.106 + '@swc/core-darwin-arm64': 1.7.40 + '@swc/core-darwin-x64': 1.7.40 + '@swc/core-linux-arm-gnueabihf': 1.7.40 + '@swc/core-linux-arm64-gnu': 1.7.40 + '@swc/core-linux-arm64-musl': 1.7.40 + '@swc/core-linux-x64-gnu': 1.7.40 + '@swc/core-linux-x64-musl': 1.7.40 + '@swc/core-win32-arm64-msvc': 1.7.40 + '@swc/core-win32-ia32-msvc': 1.7.40 + '@swc/core-win32-x64-msvc': 1.7.40 - '@swc/counter@0.1.2': {} + '@swc/counter@0.1.3': {} - '@swc/types@0.1.5': {} + '@swc/types@0.1.13': + dependencies: + '@swc/counter': 0.1.3 - '@tanstack/match-sorter-utils@8.11.7': + '@tanstack/match-sorter-utils@8.19.4': dependencies: - remove-accents: 0.4.2 + remove-accents: 0.5.0 '@tanstack/query-core@4.36.1': {} - '@tanstack/react-query-devtools@4.36.1(@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@tanstack/react-query-devtools@4.36.1(@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/match-sorter-utils': 8.11.7 - '@tanstack/react-query': 4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@tanstack/match-sorter-utils': 8.19.4 + '@tanstack/react-query': 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) superjson: 1.13.3 - use-sync-external-store: 1.2.0(react@18.2.0) + use-sync-external-store: 1.2.2(react@18.3.1) - '@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@tanstack/react-query@4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/query-core': 4.36.1 - react: 18.2.0 - use-sync-external-store: 1.2.0(react@18.2.0) + react: 18.3.1 + use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: - react-dom: 18.2.0(react@18.2.0) + react-dom: 18.3.1(react@18.3.1) - '@tanstack/react-virtual@3.0.0-beta.9(react@18.2.0)': + '@tanstack/react-virtual@3.0.0-beta.9(react@18.3.1)': dependencies: '@reach/observe-rect': 1.2.0 - react: 18.2.0 + react: 18.3.1 '@tanstack/virtual-core@3.0.0-beta.9': dependencies: '@reach/observe-rect': 1.2.0 - '@tauri-apps/api@1.5.3': {} + '@tauri-apps/api@1.6.0': {} '@trysound/sax@0.2.0': {} '@types/acorn@4.0.6': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.23.6 - '@babel/types': 7.23.6 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.5 + '@types/babel__traverse': 7.20.6 '@types/babel__generator@7.6.8': dependencies: - '@babel/types': 7.23.6 + '@babel/types': 7.26.0 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.23.6 - '@babel/types': 7.23.6 + '@babel/parser': 7.26.1 + '@babel/types': 7.26.0 - '@types/babel__traverse@7.20.5': + '@types/babel__traverse@7.20.6': dependencies: - '@babel/types': 7.23.6 + '@babel/types': 7.26.0 '@types/byte-size@8.1.2': {} @@ -6827,7 +6936,7 @@ snapshots: dependencies: '@types/d3-color': 3.1.3 - '@types/d3-path@3.0.2': {} + '@types/d3-path@3.1.0': {} '@types/d3-scale@4.0.8': dependencies: @@ -6835,7 +6944,7 @@ snapshots: '@types/d3-shape@3.1.6': dependencies: - '@types/d3-path': 3.0.2 + '@types/d3-path': 3.1.0 '@types/d3-time@3.0.3': {} @@ -6845,24 +6954,22 @@ snapshots: dependencies: '@types/ms': 0.7.34 - '@types/eslint@8.56.2': + '@types/eslint@8.56.12': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 - '@types/estree-jsx@1.0.3': + '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.5 - - '@types/estree@1.0.5': {} + '@types/estree': 1.0.6 '@types/estree@1.0.6': {} '@types/file-saver@2.0.7': {} - '@types/hast@3.0.3': + '@types/hast@3.0.4': dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 '@types/history@4.7.11': {} @@ -6872,192 +6979,192 @@ snapshots: '@types/lodash-es@4.17.12': dependencies: - '@types/lodash': 4.14.202 + '@types/lodash': 4.17.12 - '@types/lodash@4.14.202': {} + '@types/lodash@4.17.12': {} - '@types/mdast@4.0.3': + '@types/mdast@4.0.4': dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 - '@types/mdx@2.0.10': {} + '@types/mdx@2.0.13': {} '@types/minimist@1.2.5': {} '@types/ms@0.7.34': {} - '@types/node@18.15.13': {} + '@types/node@20.17.2': + dependencies: + undici-types: 6.19.8 - '@types/node@20.11.7': + '@types/node@22.7.5': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/normalize-package-data@2.4.4': {} '@types/parse-json@4.0.2': {} - '@types/prismjs@1.26.3': {} + '@types/prismjs@1.26.5': {} - '@types/prop-types@15.7.11': {} + '@types/prop-types@15.7.13': {} - '@types/react-dom@18.2.18': + '@types/react-dom@18.3.1': dependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.12 '@types/react-router-dom@5.3.3': dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.48 + '@types/react': 18.3.12 '@types/react-router': 5.1.20 '@types/react-router@5.1.20': dependencies: '@types/history': 4.7.11 - '@types/react': 18.2.48 + '@types/react': 18.3.12 '@types/react-virtualized-auto-sizer@1.0.4': dependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.12 '@types/react-window@1.8.8': dependencies: - '@types/react': 18.2.48 + '@types/react': 18.3.12 - '@types/react@18.2.48': + '@types/react@18.3.12': dependencies: - '@types/prop-types': 15.7.11 - '@types/scheduler': 0.16.8 + '@types/prop-types': 15.7.13 csstype: 3.1.3 - '@types/scheduler@0.16.8': {} + '@types/semver@7.5.8': {} - '@types/semver@7.5.6': {} + '@types/statuses@2.0.5': {} - '@types/statuses@2.0.4': {} + '@types/tough-cookie@4.0.5': {} - '@types/unist@2.0.10': {} + '@types/unist@2.0.11': {} - '@types/unist@3.0.2': {} + '@types/unist@3.0.3': {} - '@typescript-eslint/eslint-plugin@6.19.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/type-utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.1 - debug: 4.3.4 - eslint: 8.56.0 + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 + eslint: 8.57.1 graphemer: 1.4.0 - ignore: 5.3.0 + ignore: 5.3.2 natural-compare: 1.4.0 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.3.3) + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3)': + '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) - '@typescript-eslint/visitor-keys': 6.19.1 - debug: 4.3.4 - eslint: 8.56.0 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 + eslint: 8.57.1 optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@6.19.1': + '@typescript-eslint/scope-manager@6.21.0': dependencies: - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/visitor-keys': 6.19.1 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 - '@typescript-eslint/type-utils@6.19.1(eslint@8.56.0)(typescript@5.3.3)': + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) - '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - debug: 4.3.4 - eslint: 8.56.0 - ts-api-utils: 1.0.3(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + debug: 4.3.7 + eslint: 8.57.1 + ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@6.19.1': {} + '@typescript-eslint/types@6.21.0': {} - '@typescript-eslint/typescript-estree@6.19.1(typescript@5.3.3)': + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.3.3)': dependencies: - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/visitor-keys': 6.19.1 - debug: 4.3.4 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.3.3) + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.19.1(eslint@8.56.0)(typescript@5.3.3)': + '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 6.19.1 - '@typescript-eslint/types': 6.19.1 - '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) - eslint: 8.56.0 - semver: 7.5.4 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) + eslint: 8.57.1 + semver: 7.6.3 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@6.19.1': + '@typescript-eslint/visitor-keys@6.21.0': dependencies: - '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/types': 6.21.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-legacy@5.3.0(esbuild@0.19.12)(terser@5.27.0)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0))': + '@vitejs/plugin-legacy@5.4.3(terser@5.36.0)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0))': dependencies: - '@babel/core': 7.23.9 - '@babel/preset-env': 7.23.8(@babel/core@7.23.9) - browserslist: 4.22.2 - core-js: 3.35.1 - esbuild-plugin-browserslist: 0.10.0(browserslist@4.22.2)(esbuild@0.19.12) - magic-string: 0.30.5 + '@babel/core': 7.26.0 + '@babel/preset-env': 7.26.0(@babel/core@7.26.0) + browserslist: 4.24.2 + browserslist-to-esbuild: 2.1.1(browserslist@4.24.2) + core-js: 3.38.1 + magic-string: 0.30.12 regenerator-runtime: 0.14.1 - systemjs: 6.14.3 - terser: 5.27.0 - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + systemjs: 6.15.1 + terser: 5.36.0 + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) transitivePeerDependencies: - - esbuild - supports-color - '@vitejs/plugin-react-swc@3.5.0(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0))': + '@vitejs/plugin-react-swc@3.7.1(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0))': dependencies: - '@swc/core': 1.3.106 - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + '@swc/core': 1.7.40 + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.2.1(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0))': + '@vitejs/plugin-react@4.3.3(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0))': dependencies: - '@babel/core': 7.23.9 - '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.23.9) - '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) '@types/babel__core': 7.20.5 - react-refresh: 0.14.0 - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + react-refresh: 0.14.2 + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) transitivePeerDependencies: - supports-color @@ -7071,11 +7178,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: - acorn: 8.11.3 + acorn: 8.14.0 - acorn@8.11.3: {} + acorn@8.14.0: {} add-stream@1.0.0: {} @@ -7088,12 +7195,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.12.0: + ajv@8.17.1: dependencies: fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - uri-js: 4.4.1 ansi-align@3.0.1: dependencies: @@ -7105,7 +7212,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.0.1: {} + ansi-regex@6.1.0: {} ansi-sequence-parser@1.1.1: {} @@ -7126,66 +7233,76 @@ snapshots: argparse@2.0.1: {} - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 + aria-query@5.3.2: {} - array-buffer-byte-length@1.0.0: + array-buffer-byte-length@1.0.1: dependencies: - call-bind: 1.0.5 - is-array-buffer: 3.0.2 + call-bind: 1.0.7 + is-array-buffer: 3.0.4 array-ify@1.0.0: {} - array-includes@3.1.7: + array-includes@3.1.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 is-string: 1.0.7 array-union@2.1.0: {} - array.prototype.findlastindex@1.2.3: + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.findlastindex@1.2.5: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 array.prototype.flat@1.3.2: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 array.prototype.flatmap@1.3.2: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 es-shim-unscopables: 1.0.2 - array.prototype.tosorted@1.1.2: + array.prototype.tosorted@1.1.4: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 + es-errors: 1.3.0 es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 - arraybuffer.prototype.slice@1.0.2: + arraybuffer.prototype.slice@1.0.3: dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.5 + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 arrify@1.0.1: {} @@ -7193,69 +7310,63 @@ snapshots: astral-regex@2.0.0: {} - astring@1.8.6: {} - - asynciterator.prototype@1.0.0: - dependencies: - has-symbols: 1.0.3 + astring@1.9.0: {} asynckit@0.4.0: {} - autoprefixer@10.4.17(postcss@8.4.33): + autoprefixer@10.4.20(postcss@8.4.47): dependencies: - browserslist: 4.22.2 - caniuse-lite: 1.0.30001580 + browserslist: 4.24.2 + caniuse-lite: 1.0.30001674 fraction.js: 4.3.7 normalize-range: 0.1.2 - picocolors: 1.0.0 - postcss: 8.4.33 + picocolors: 1.1.1 + postcss: 8.4.47 postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.5: {} - - axe-core@4.7.0: {} + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 - axe-core@4.8.3: {} + axe-core@4.10.2: {} - axios@1.6.7: + axios@1.7.7: dependencies: - follow-redirects: 1.15.5 - form-data: 4.0.0 + follow-redirects: 1.15.9 + form-data: 4.0.1 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - axobject-query@3.2.1: - dependencies: - dequal: 2.0.3 + axobject-query@4.1.0: {} babel-plugin-macros@3.1.0: dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 cosmiconfig: 7.1.0 resolve: 1.22.8 - babel-plugin-polyfill-corejs2@0.4.8(@babel/core@7.23.9): + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.26.0): dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.23.9 - '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.23.9) + '@babel/compat-data': 7.26.0 + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.8.7(@babel/core@7.23.9): + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0): dependencies: - '@babel/core': 7.23.9 - '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.23.9) - core-js-compat: 3.35.1 + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) + core-js-compat: 3.38.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.5.5(@babel/core@7.23.9): + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.26.0): dependencies: - '@babel/core': 7.23.9 - '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.23.9) + '@babel/core': 7.26.0 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0) transitivePeerDependencies: - supports-color @@ -7265,21 +7376,11 @@ snapshots: balanced-match@2.0.0: {} - base64-js@1.5.1: {} - bcp-47-match@2.0.3: {} - big-integer@1.6.52: {} - bignumber.js@9.1.2: {} - binary-extensions@2.2.0: {} - - bl@4.1.0: - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 + binary-extensions@2.3.0: {} boolbase@1.0.0: {} @@ -7294,10 +7395,6 @@ snapshots: widest-line: 4.0.1 wrap-ansi: 8.1.0 - bplist-parser@0.2.0: - dependencies: - big-integer: 1.6.52 - brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -7311,36 +7408,38 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.22.2: + browserslist-to-esbuild@2.1.1(browserslist@4.24.2): dependencies: - caniuse-lite: 1.0.30001580 - electron-to-chromium: 1.4.645 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.22.2) + browserslist: 4.24.2 + meow: 13.2.0 - buffer-from@1.1.2: {} - - buffer@5.7.1: + browserslist@4.24.2: dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 + caniuse-lite: 1.0.30001674 + electron-to-chromium: 1.5.49 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + + buffer-from@1.1.2: {} - bundle-name@3.0.0: + bundle-name@4.1.0: dependencies: - run-applescript: 5.0.0 + run-applescript: 7.0.0 - byte-size@8.1.1: {} + byte-size@9.0.0: {} cache-content-type@1.0.1: dependencies: mime-types: 2.1.35 - ylru: 1.3.2 + ylru: 1.4.0 - call-bind@1.0.5: + call-bind@1.0.7: dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.2 - set-function-length: 1.2.0 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 callsites@3.1.0: {} @@ -7356,7 +7455,7 @@ snapshots: camelcase@7.0.1: {} - caniuse-lite@1.0.30001580: {} + caniuse-lite@1.0.30001674: {} ccount@2.0.1: {} @@ -7381,9 +7480,7 @@ snapshots: character-reference-invalid@2.0.1: {} - chardet@0.7.0: {} - - chokidar@3.5.3: + chokidar@3.6.0: dependencies: anymatch: 3.1.3 braces: 3.0.3 @@ -7395,17 +7492,15 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + classnames@2.5.1: {} cli-boxes@3.0.0: {} - cli-cursor@3.1.0: - dependencies: - restore-cursor: 3.1.0 - - cli-spinners@2.9.2: {} - - cli-width@3.0.0: {} + cli-width@4.1.0: {} cliui@6.0.0: dependencies: @@ -7425,9 +7520,7 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - clone@1.0.4: {} - - clsx@2.1.0: {} + clsx@2.1.1: {} co@4.6.0: {} @@ -7453,7 +7546,7 @@ snapshots: comma-separated-tokens@2.0.3: {} - commander@11.1.0: {} + commander@12.1.0: {} commander@2.20.3: {} @@ -7475,14 +7568,12 @@ snapshots: readable-stream: 3.6.2 typedarray: 0.0.6 - concurrently@8.2.2: + concurrently@9.0.1: dependencies: chalk: 4.1.2 - date-fns: 2.30.0 lodash: 4.17.21 rxjs: 7.8.1 shell-quote: 1.8.1 - spawn-command: 0.0.2 supports-color: 8.1.1 tree-kill: 1.2.2 yargs: 17.7.2 @@ -7620,11 +7711,11 @@ snapshots: dependencies: is-what: 4.1.16 - core-js-compat@3.35.1: + core-js-compat@3.38.1: dependencies: - browserslist: 4.22.2 + browserslist: 4.24.2 - core-js@3.35.1: {} + core-js@3.38.1: {} core-util-is@1.0.3: {} @@ -7660,7 +7751,7 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-functions-list@3.2.1: {} + css-functions-list@3.2.3: {} css-select@5.1.0: dependencies: @@ -7670,17 +7761,22 @@ snapshots: domutils: 3.1.0 nth-check: 2.1.1 - css-selector-parser@3.0.4: {} + css-selector-parser@3.0.5: {} css-tree@2.2.1: dependencies: mdn-data: 2.0.28 - source-map-js: 1.0.2 + source-map-js: 1.2.1 css-tree@2.3.1: dependencies: mdn-data: 2.0.30 - source-map-js: 1.0.2 + source-map-js: 1.2.1 + + css-tree@3.0.0: + dependencies: + mdn-data: 2.10.0 + source-map-js: 1.2.1 css-what@6.1.0: {} @@ -7736,21 +7832,35 @@ snapshots: dashify@2.0.0: {} - date-fns@2.30.0: + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: dependencies: - '@babel/runtime': 7.23.8 + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 dateformat@3.0.3: {} - dayjs@1.11.10: {} + dayjs@1.11.13: {} debug@3.2.7: dependencies: ms: 2.1.3 - debug@4.3.4: + debug@4.3.7: dependencies: - ms: 2.1.2 + ms: 2.1.3 decamelize-keys@1.1.1: dependencies: @@ -7773,34 +7883,25 @@ snapshots: deepmerge@4.3.1: {} - default-browser-id@3.0.0: - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - - default-browser@4.0.0: - dependencies: - bundle-name: 3.0.0 - default-browser-id: 3.0.0 - execa: 7.2.0 - titleize: 3.0.0 + default-browser-id@5.0.0: {} - defaults@1.0.4: + default-browser@5.2.1: dependencies: - clone: 1.0.4 + bundle-name: 4.1.0 + default-browser-id: 5.0.0 - define-data-property@1.1.1: + define-data-property@1.1.4: dependencies: - get-intrinsic: 1.2.2 + es-define-property: 1.0.0 + es-errors: 1.3.0 gopd: 1.0.1 - has-property-descriptors: 1.0.1 define-lazy-prop@3.0.0: {} define-properties@1.2.1: dependencies: - define-data-property: 1.1.1 - has-property-descriptors: 1.0.1 + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 object-keys: 1.1.1 delayed-stream@1.0.0: {} @@ -7819,6 +7920,8 @@ snapshots: detect-indent@6.1.0: {} + detect-libc@1.0.3: {} + detect-newline@3.1.0: {} devlop@1.1.0: @@ -7841,9 +7944,10 @@ snapshots: dependencies: esutils: 2.0.3 - dom-helpers@3.4.0: + dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 + csstype: 3.1.3 dom-serializer@2.0.0: dependencies: @@ -7866,7 +7970,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.0 dot-prop@5.3.0: dependencies: @@ -7881,14 +7985,12 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.4.645: {} + electron-to-chromium@1.5.49: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} - encode-utf8@1.0.3: {} - encodeurl@1.0.2: {} entities@4.5.0: {} @@ -7899,74 +8001,91 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.22.3: - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - es-set-tostringtag: 2.0.2 + es-abstract@1.23.3: + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 - get-intrinsic: 1.2.2 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.4 gopd: 1.0.1 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 has-symbols: 1.0.3 - hasown: 2.0.0 - internal-slot: 1.0.6 - is-array-buffer: 3.0.2 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 is-callable: 1.2.7 - is-negative-zero: 2.0.2 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 + is-shared-array-buffer: 1.0.3 is-string: 1.0.7 - is-typed-array: 1.1.12 + is-typed-array: 1.1.13 is-weakref: 1.0.2 - object-inspect: 1.13.1 + object-inspect: 1.13.2 object-keys: 1.1.1 object.assign: 4.1.5 - regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.1.0 - safe-regex-test: 1.0.2 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 + regexp.prototype.flags: 1.5.3 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 unbox-primitive: 1.0.2 - which-typed-array: 1.1.13 + which-typed-array: 1.1.15 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} - es-iterator-helpers@1.0.15: + es-iterator-helpers@1.1.0: dependencies: - asynciterator.prototype: 1.0.0 - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - es-set-tostringtag: 2.0.2 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 function-bind: 1.1.2 - get-intrinsic: 1.2.2 - globalthis: 1.0.3 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 has-symbols: 1.0.3 - internal-slot: 1.0.6 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.0 + internal-slot: 1.0.7 + iterator.prototype: 1.1.3 + safe-array-concat: 1.1.2 - es-set-tostringtag@2.0.2: + es-object-atoms@1.0.0: dependencies: - get-intrinsic: 1.2.2 - has-tostringtag: 1.0.0 - hasown: 2.0.0 + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 es-shim-unscopables@1.0.2: dependencies: - hasown: 2.0.0 + hasown: 2.0.2 es-to-primitive@1.2.1: dependencies: @@ -7974,42 +8093,74 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 - esbuild-plugin-browserslist@0.10.0(browserslist@4.22.2)(esbuild@0.19.12): + esast-util-from-estree@2.0.0: dependencies: - browserslist: 4.22.2 - debug: 4.3.4 - esbuild: 0.19.12 - zod: 3.22.4 - transitivePeerDependencies: - - supports-color + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.14.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.2 - esbuild@0.19.12: + esbuild@0.21.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.19.12 - '@esbuild/android-arm': 0.19.12 - '@esbuild/android-arm64': 0.19.12 - '@esbuild/android-x64': 0.19.12 - '@esbuild/darwin-arm64': 0.19.12 - '@esbuild/darwin-x64': 0.19.12 - '@esbuild/freebsd-arm64': 0.19.12 - '@esbuild/freebsd-x64': 0.19.12 - '@esbuild/linux-arm': 0.19.12 - '@esbuild/linux-arm64': 0.19.12 - '@esbuild/linux-ia32': 0.19.12 - '@esbuild/linux-loong64': 0.19.12 - '@esbuild/linux-mips64el': 0.19.12 - '@esbuild/linux-ppc64': 0.19.12 - '@esbuild/linux-riscv64': 0.19.12 - '@esbuild/linux-s390x': 0.19.12 - '@esbuild/linux-x64': 0.19.12 - '@esbuild/netbsd-x64': 0.19.12 - '@esbuild/openbsd-x64': 0.19.12 - '@esbuild/sunos-x64': 0.19.12 - '@esbuild/win32-arm64': 0.19.12 - '@esbuild/win32-ia32': 0.19.12 - '@esbuild/win32-x64': 0.19.12 - - escalade@3.1.1: {} + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -8019,116 +8170,119 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-prettier@9.1.0(eslint@8.56.0): + eslint-config-prettier@9.1.0(eslint@8.57.1): dependencies: - eslint: 8.56.0 + eslint: 8.57.1 eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 - is-core-module: 2.13.1 + is-core-module: 2.15.1 resolve: 1.22.8 transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - eslint: 8.56.0 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1): dependencies: - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.56.0 + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) - hasown: 2.0.0 - is-core-module: 2.13.1 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + hasown: 2.0.2 + is-core-module: 2.15.1 is-glob: 4.0.3 minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 semver: 6.3.1 + string.prototype.trimend: 1.0.8 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.8.0(eslint@8.56.0): + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1): dependencies: - '@babel/runtime': 7.23.8 - aria-query: 5.3.0 - array-includes: 3.1.7 + aria-query: 5.3.2 + array-includes: 3.1.8 array.prototype.flatmap: 1.3.2 ast-types-flow: 0.0.8 - axe-core: 4.7.0 - axobject-query: 3.2.1 + axe-core: 4.10.2 + axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - es-iterator-helpers: 1.0.15 - eslint: 8.56.0 - hasown: 2.0.0 + eslint: 8.57.1 + hasown: 2.0.2 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 + object.fromentries: 2.0.8 + safe-regex-test: 1.0.3 + string.prototype.includes: 2.0.1 - eslint-plugin-prettier@5.1.3(@types/eslint@8.56.2)(eslint-config-prettier@9.1.0(eslint@8.56.0))(eslint@8.56.0)(prettier@3.2.4): + eslint-plugin-prettier@5.2.1(@types/eslint@8.56.12)(eslint-config-prettier@9.1.0(eslint@8.57.1))(eslint@8.57.1)(prettier@3.3.3): dependencies: - eslint: 8.56.0 - prettier: 3.2.4 + eslint: 8.57.1 + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.2 optionalDependencies: - '@types/eslint': 8.56.2 - eslint-config-prettier: 9.1.0(eslint@8.56.0) + '@types/eslint': 8.56.12 + eslint-config-prettier: 9.1.0(eslint@8.57.1) - eslint-plugin-react-hooks@4.6.0(eslint@8.56.0): + eslint-plugin-react-hooks@4.6.2(eslint@8.57.1): dependencies: - eslint: 8.56.0 + eslint: 8.57.1 - eslint-plugin-react-refresh@0.4.5(eslint@8.56.0): + eslint-plugin-react-refresh@0.4.14(eslint@8.57.1): dependencies: - eslint: 8.56.0 + eslint: 8.57.1 - eslint-plugin-react@7.33.2(eslint@8.56.0): + eslint-plugin-react@7.37.2(eslint@8.57.1): dependencies: - array-includes: 3.1.7 + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.2 - array.prototype.tosorted: 1.1.2 + array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.0.15 - eslint: 8.56.0 + es-iterator-helpers: 1.1.0 + eslint: 8.57.1 estraverse: 5.3.0 + hasown: 2.0.2 jsx-ast-utils: 3.3.5 minimatch: 3.1.2 - object.entries: 1.1.7 - object.fromentries: 2.0.7 - object.hasown: 1.1.3 - object.values: 1.1.7 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.values: 1.2.0 prop-types: 15.8.1 resolve: 2.0.0-next.5 semver: 6.3.1 - string.prototype.matchall: 4.0.10 + string.prototype.matchall: 4.0.11 + string.prototype.repeat: 1.0.0 - eslint-plugin-simple-import-sort@10.0.0(eslint@8.56.0): + eslint-plugin-simple-import-sort@10.0.0(eslint@8.57.1): dependencies: - eslint: 8.56.0 + eslint: 8.57.1 eslint-scope@7.2.2: dependencies: @@ -8137,26 +8291,26 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint@8.56.0: + eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - '@eslint-community/regexpp': 4.10.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.1 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.7 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - esquery: 1.5.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 @@ -8164,7 +8318,7 @@ snapshots: glob-parent: 6.0.2 globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.3.0 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -8174,7 +8328,7 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: @@ -8182,11 +8336,11 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 3.4.3 - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -8198,45 +8352,50 @@ snapshots: estree-util-attach-comments@3.0.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 estree-util-build-jsx@3.0.1: dependencies: - '@types/estree-jsx': 1.0.3 + '@types/estree-jsx': 1.0.5 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 estree-walker: 3.0.3 estree-util-is-identifier-name@3.0.0: {} + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.6 + devlop: 1.1.0 + estree-util-to-js@2.0.0: dependencies: - '@types/estree-jsx': 1.0.3 - astring: 1.8.6 + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 source-map: 0.7.4 estree-util-visit@2.0.0: dependencies: - '@types/estree-jsx': 1.0.3 - '@types/unist': 3.0.2 + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 estree-walker@2.0.2: {} estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 esutils@2.0.3: {} - ethers@6.10.0: + ethers@6.13.4: dependencies: - '@adraffy/ens-normalize': 1.10.0 + '@adraffy/ens-normalize': 1.10.1 '@noble/curves': 1.2.0 '@noble/hashes': 1.3.2 - '@types/node': 18.15.13 + '@types/node': 22.7.5 aes-js: 4.0.0-beta.5 - tslib: 2.4.0 - ws: 8.5.0 + tslib: 2.7.0 + ws: 8.17.1 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -8245,38 +8404,8 @@ snapshots: events@3.3.0: {} - execa@5.1.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - execa@7.2.0: - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.1 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.2.0 - onetime: 6.0.0 - signal-exit: 3.0.7 - strip-final-newline: 3.0.0 - extend@3.0.2: {} - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -8289,15 +8418,17 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.8 fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} + fast-uri@3.0.3: {} + fastest-levenshtein@1.0.16: {} - fastq@1.16.0: + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -8311,7 +8442,7 @@ snapshots: file-entry-cache@8.0.0: dependencies: - flat-cache: 4.0.0 + flat-cache: 4.0.1 file-saver@2.0.5: {} @@ -8343,30 +8474,24 @@ snapshots: flat-cache@3.2.0: dependencies: - flatted: 3.2.9 + flatted: 3.3.1 keyv: 4.5.4 rimraf: 3.0.2 - flat-cache@4.0.0: + flat-cache@4.0.1: dependencies: - flatted: 3.2.9 + flatted: 3.3.1 keyv: 4.5.4 - rimraf: 5.0.5 - flatted@3.2.9: {} + flatted@3.3.1: {} - follow-redirects@1.15.5: {} + follow-redirects@1.15.9: {} for-each@0.3.3: dependencies: is-callable: 1.2.7 - foreground-child@3.1.1: - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - - form-data@4.0.0: + form-data@4.0.1: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 @@ -8374,13 +8499,13 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@11.0.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + framer-motion@11.11.10(@emotion/is-prop-valid@1.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - tslib: 2.6.2 + tslib: 2.8.0 optionalDependencies: - '@emotion/is-prop-valid': 0.8.8 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + '@emotion/is-prop-valid': 1.3.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) fresh@0.5.2: {} @@ -8393,9 +8518,9 @@ snapshots: function.prototype.name@1.1.6: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 functions-have-names: 1.2.3 functions-have-names@1.2.3: {} @@ -8404,12 +8529,13 @@ snapshots: get-caller-file@2.0.5: {} - get-intrinsic@1.2.2: + get-intrinsic@1.2.4: dependencies: + es-errors: 1.3.0 function-bind: 1.1.2 - has-proto: 1.0.1 + has-proto: 1.0.3 has-symbols: 1.0.3 - hasown: 2.0.0 + hasown: 2.0.2 get-pkg-repo@4.2.1: dependencies: @@ -8418,14 +8544,13 @@ snapshots: through2: 2.0.5 yargs: 16.2.0 - get-port@7.0.0: {} + get-port@7.1.0: {} - get-stream@6.0.1: {} - - get-symbol-description@1.0.0: + get-symbol-description@1.0.2: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 get-text-width@1.0.3: {} @@ -8459,14 +8584,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.3.10: - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -8500,24 +8617,25 @@ snapshots: dependencies: type-fest: 0.20.2 - globalthis@1.0.3: + globalthis@1.0.4: dependencies: define-properties: 1.2.1 + gopd: 1.0.1 globby@11.1.0: dependencies: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.0 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 - globby@14.0.0: + globby@14.0.2: dependencies: - '@sindresorhus/merge-streams': 1.0.0 + '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.2 - ignore: 5.3.0 + ignore: 5.3.2 path-type: 5.0.0 slash: 5.1.0 unicorn-magic: 0.1.0 @@ -8528,13 +8646,13 @@ snapshots: gopd@1.0.1: dependencies: - get-intrinsic: 1.2.2 + get-intrinsic: 1.2.4 graceful-fs@4.2.11: {} graphemer@1.4.0: {} - graphql@16.8.1: {} + graphql@16.9.0: {} handlebars@4.7.8: dependencies: @@ -8543,7 +8661,7 @@ snapshots: source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.17.4 + uglify-js: 3.19.3 hard-rejection@2.1.0: {} @@ -8553,95 +8671,94 @@ snapshots: has-flag@4.0.0: {} - has-property-descriptors@1.0.1: + has-property-descriptors@1.0.2: dependencies: - get-intrinsic: 1.2.2 + es-define-property: 1.0.0 - has-proto@1.0.1: {} + has-proto@1.0.3: {} has-symbols@1.0.3: {} - has-tostringtag@1.0.0: + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - hasown@2.0.0: + hasown@2.0.2: dependencies: function-bind: 1.1.2 hast-util-classnames@3.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 space-separated-tokens: 2.0.2 hast-util-from-parse5@8.0.1: dependencies: - '@types/hast': 3.0.3 - '@types/unist': 3.0.2 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 devlop: 1.1.0 hastscript: 8.0.0 - property-information: 6.4.1 - vfile: 6.0.1 - vfile-location: 5.0.2 + property-information: 6.5.0 + vfile: 6.0.3 + vfile-location: 5.0.3 web-namespaces: 2.0.1 hast-util-has-property@3.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 hast-util-parse-selector@4.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 - hast-util-raw@9.0.2: + hast-util-raw@9.0.4: dependencies: - '@types/hast': 3.0.3 - '@types/unist': 3.0.2 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 '@ungap/structured-clone': 1.2.0 hast-util-from-parse5: 8.0.1 hast-util-to-parse5: 8.0.0 html-void-elements: 3.0.0 - mdast-util-to-hast: 13.1.0 - parse5: 7.1.2 + mdast-util-to-hast: 13.2.0 + parse5: 7.2.1 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 - vfile: 6.0.1 + vfile: 6.0.3 web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-select@6.0.2: + hast-util-select@6.0.3: dependencies: - '@types/hast': 3.0.3 - '@types/unist': 3.0.2 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 bcp-47-match: 2.0.3 comma-separated-tokens: 2.0.3 - css-selector-parser: 3.0.4 + css-selector-parser: 3.0.5 devlop: 1.1.0 direction: 2.0.1 hast-util-has-property: 3.0.0 - hast-util-to-string: 3.0.0 + hast-util-to-string: 3.0.1 hast-util-whitespace: 3.0.0 - not: 0.1.0 nth-check: 2.1.1 - property-information: 6.4.1 + property-information: 6.5.0 space-separated-tokens: 2.0.2 unist-util-visit: 5.0.0 zwitch: 2.0.4 hast-util-to-estree@3.1.0: dependencies: - '@types/estree': 1.0.5 - '@types/estree-jsx': 1.0.3 - '@types/hast': 3.0.3 + '@types/estree': 1.0.6 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 devlop: 1.1.0 estree-util-attach-comments: 3.0.0 estree-util-is-identifier-name: 3.0.0 hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.0 - mdast-util-mdx-jsx: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 mdast-util-mdxjs-esm: 2.0.1 - property-information: 6.4.1 + property-information: 6.5.0 space-separated-tokens: 2.0.2 style-to-object: 0.4.4 unist-util-position: 5.0.0 @@ -8649,21 +8766,21 @@ snapshots: transitivePeerDependencies: - supports-color - hast-util-to-jsx-runtime@2.3.0: + hast-util-to-jsx-runtime@2.3.2: dependencies: - '@types/estree': 1.0.5 - '@types/hast': 3.0.3 - '@types/unist': 3.0.2 + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 comma-separated-tokens: 2.0.3 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.0 - mdast-util-mdx-jsx: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 mdast-util-mdxjs-esm: 2.0.1 - property-information: 6.4.1 + property-information: 6.5.0 space-separated-tokens: 2.0.2 - style-to-object: 1.0.5 + style-to-object: 1.0.8 unist-util-position: 5.0.0 vfile-message: 4.0.2 transitivePeerDependencies: @@ -8671,37 +8788,37 @@ snapshots: hast-util-to-parse5@8.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 devlop: 1.1.0 - property-information: 6.4.1 + property-information: 6.5.0 space-separated-tokens: 2.0.2 web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-to-string@3.0.0: + hast-util-to-string@3.0.1: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 hast-util-whitespace@3.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 hastscript@8.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 - property-information: 6.4.1 + property-information: 6.5.0 space-separated-tokens: 2.0.2 - headers-polyfill@4.0.2: {} + headers-polyfill@4.0.3: {} hex-rgb@5.0.0: {} history@5.3.0: dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 hoist-non-react-statics@3.3.2: dependencies: @@ -8713,22 +8830,24 @@ snapshots: dependencies: lru-cache: 6.0.0 - html-dom-parser@5.0.7: + html-dom-parser@5.0.10: dependencies: domhandler: 5.0.3 htmlparser2: 9.1.0 - html-react-parser@5.1.1(react@18.2.0): + html-react-parser@5.1.18(@types/react@18.3.12)(react@18.3.1): dependencies: domhandler: 5.0.3 - html-dom-parser: 5.0.7 - react: 18.2.0 + html-dom-parser: 5.0.10 + react: 18.3.1 react-property: 2.0.2 - style-to-js: 1.1.10 + style-to-js: 1.1.16 + optionalDependencies: + '@types/react': 18.3.12 html-tags@3.3.1: {} - html-url-attributes@3.0.0: {} + html-url-attributes@3.0.1: {} html-void-elements@3.0.0: {} @@ -8752,19 +8871,9 @@ snapshots: statuses: 1.5.0 toidentifier: 1.0.1 - human-signals@2.1.0: {} - - human-signals@4.3.1: {} - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - - ieee754@1.2.1: {} + ignore@5.3.2: {} - ignore@5.3.0: {} - - immutable@4.3.4: {} + immutable@4.3.7: {} import-fresh@3.3.0: dependencies: @@ -8786,31 +8895,13 @@ snapshots: inline-style-parser@0.1.1: {} - inline-style-parser@0.2.2: {} - - inquirer@8.2.6: - dependencies: - ansi-escapes: 4.3.2 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-width: 3.0.0 - external-editor: 3.1.0 - figures: 3.2.0 - lodash: 4.17.21 - mute-stream: 0.0.8 - ora: 5.4.1 - run-async: 2.4.1 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 + inline-style-parser@0.2.4: {} - internal-slot@1.0.6: + internal-slot@1.0.7: dependencies: - get-intrinsic: 1.2.2 - hasown: 2.0.0 - side-channel: 1.0.4 + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 internmap@2.0.3: {} @@ -8821,17 +8912,16 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 - is-array-buffer@3.0.2: + is-array-buffer@3.0.4: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 + call-bind: 1.0.7 + get-intrinsic: 1.2.4 is-arrayish@0.2.1: {} is-async-function@2.0.0: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-bigint@1.0.4: dependencies: @@ -8839,42 +8929,42 @@ snapshots: is-binary-path@2.1.0: dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 is-boolean-object@1.1.2: dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 - - is-buffer@2.0.5: {} + call-bind: 1.0.7 + has-tostringtag: 1.0.2 is-callable@1.2.7: {} - is-core-module@2.13.1: + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: dependencies: - hasown: 2.0.0 + is-typed-array: 1.1.13 is-date-object@1.0.5: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-decimal@2.0.1: {} - is-docker@2.2.1: {} - is-docker@3.0.0: {} is-extglob@2.1.1: {} is-finalizationregistry@1.0.2: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 is-fullwidth-code-point@3.0.0: {} is-generator-function@1.0.10: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-glob@4.0.3: dependencies: @@ -8886,17 +8976,15 @@ snapshots: dependencies: is-docker: 3.0.0 - is-interactive@1.0.0: {} + is-map@2.0.3: {} - is-map@2.0.2: {} - - is-negative-zero@2.0.2: {} + is-negative-zero@2.0.3: {} is-node-process@1.2.0: {} is-number-object@1.0.7: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-number@7.0.0: {} @@ -8910,28 +8998,20 @@ snapshots: is-plain-object@5.0.0: {} - is-reference@3.0.2: - dependencies: - '@types/estree': 1.0.5 - is-regex@1.1.4: dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 + call-bind: 1.0.7 + has-tostringtag: 1.0.2 - is-set@2.0.2: {} + is-set@2.0.3: {} - is-shared-array-buffer@1.0.2: + is-shared-array-buffer@1.0.3: dependencies: - call-bind: 1.0.5 - - is-stream@2.0.1: {} - - is-stream@3.0.0: {} + call-bind: 1.0.7 is-string@1.0.7: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-symbol@1.0.4: dependencies: @@ -8941,28 +9021,26 @@ snapshots: dependencies: text-extensions: 1.9.0 - is-typed-array@1.1.12: + is-typed-array@1.1.13: dependencies: - which-typed-array: 1.1.13 - - is-unicode-supported@0.1.0: {} + which-typed-array: 1.1.15 - is-weakmap@2.0.1: {} + is-weakmap@2.0.2: {} is-weakref@1.0.2: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 - is-weakset@2.0.2: + is-weakset@2.0.3: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 + call-bind: 1.0.7 + get-intrinsic: 1.2.4 is-what@4.1.16: {} - is-wsl@2.2.0: + is-wsl@3.1.0: dependencies: - is-docker: 2.2.1 + is-inside-container: 1.0.0 isarray@1.0.0: {} @@ -8970,21 +9048,15 @@ snapshots: isexe@2.0.0: {} - iterator.prototype@1.1.2: + iterator.prototype@1.1.3: dependencies: define-properties: 1.2.1 - get-intrinsic: 1.2.2 + get-intrinsic: 1.2.4 has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.4 - set-function-name: 2.0.1 - - itertools@2.2.3: {} + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 - jackspeak@2.3.6: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 + itertools@2.3.2: {} js-tokens@4.0.0: {} @@ -8992,9 +9064,7 @@ snapshots: dependencies: argparse: 2.0.1 - jsesc@0.5.0: {} - - jsesc@2.5.2: {} + jsesc@3.0.2: {} json-buffer@3.0.1: {} @@ -9016,16 +9086,16 @@ snapshots: json5@2.2.3: {} - jsonc-parser@3.2.1: {} + jsonc-parser@3.3.1: {} jsonparse@1.3.1: {} jsx-ast-utils@3.3.5: dependencies: - array-includes: 3.1.7 + array-includes: 3.1.8 array.prototype.flat: 1.3.2 object.assign: 4.1.5 - object.values: 1.1.7 + object.values: 1.2.0 keygrip@1.1.0: dependencies: @@ -9039,6 +9109,8 @@ snapshots: known-css-properties@0.29.0: {} + known-css-properties@0.34.0: {} + koa-compose@4.1.0: {} koa-connect@2.1.0: {} @@ -9048,14 +9120,14 @@ snapshots: co: 4.6.0 koa-compose: 4.1.0 - koa@2.15.0: + koa@2.15.3: dependencies: accepts: 1.3.8 cache-content-type: 1.0.1 content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.3.4 + debug: 4.3.7 delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -9076,11 +9148,11 @@ snapshots: transitivePeerDependencies: - supports-color - language-subtag-registry@0.3.22: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: dependencies: - language-subtag-registry: 0.3.22 + language-subtag-registry: 0.3.23 levn@0.4.1: dependencies: @@ -9089,9 +9161,9 @@ snapshots: lines-and-columns@1.2.4: {} - little-state-machine@4.8.0(react@18.2.0): + little-state-machine@4.8.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 load-json-file@4.0.0: dependencies: @@ -9130,11 +9202,6 @@ snapshots: lodash@4.17.21: {} - log-symbols@4.1.0: - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -9143,9 +9210,7 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.6.2 - - lru-cache@10.1.0: {} + tslib: 2.8.0 lru-cache@5.1.1: dependencies: @@ -9157,9 +9222,9 @@ snapshots: lunr@2.3.9: {} - magic-string@0.30.5: + magic-string@0.30.12: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 map-obj@1.0.1: {} @@ -9167,7 +9232,7 @@ snapshots: markdown-extensions@2.0.0: {} - markdown-table@3.0.3: {} + markdown-table@3.0.4: {} marked@4.3.0: {} @@ -9175,15 +9240,15 @@ snapshots: mdast-util-find-and-replace@3.0.1: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 escape-string-regexp: 5.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - mdast-util-from-markdown@2.0.0: + mdast-util-from-markdown@2.0.2: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 decode-named-character-reference: 1.0.2 devlop: 1.1.0 mdast-util-to-string: 4.0.0 @@ -9197,19 +9262,19 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-gfm-autolink-literal@2.0.0: + mdast-util-gfm-autolink-literal@2.0.1: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 ccount: 2.0.1 devlop: 1.1.0 mdast-util-find-and-replace: 3.0.1 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 mdast-util-gfm-footnote@2.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 micromark-util-normalize-identifier: 2.0.0 transitivePeerDependencies: @@ -9217,35 +9282,35 @@ snapshots: mdast-util-gfm-strikethrough@2.0.0: dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color mdast-util-gfm-table@2.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 devlop: 1.1.0 - markdown-table: 3.0.3 - mdast-util-from-markdown: 2.0.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color mdast-util-gfm-task-list-item@2.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color mdast-util-gfm@3.0.0: dependencies: - mdast-util-from-markdown: 2.0.0 - mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-gfm-autolink-literal: 2.0.1 mdast-util-gfm-footnote: 2.0.0 mdast-util-gfm-strikethrough: 2.0.0 mdast-util-gfm-table: 2.0.0 @@ -9254,30 +9319,29 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-mdx-expression@2.0.0: + mdast-util-mdx-expression@2.0.1: dependencies: - '@types/estree-jsx': 1.0.3 - '@types/hast': 3.0.3 - '@types/mdast': 4.0.3 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - mdast-util-mdx-jsx@3.0.0: + mdast-util-mdx-jsx@3.1.3: dependencies: - '@types/estree-jsx': 1.0.3 - '@types/hast': 3.0.3 - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 ccount: 2.0.1 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 parse-entities: 4.0.1 - stringify-entities: 4.0.3 - unist-util-remove-position: 5.0.0 + stringify-entities: 4.0.4 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 transitivePeerDependencies: @@ -9285,9 +9349,9 @@ snapshots: mdast-util-mdx@3.0.0: dependencies: - mdast-util-from-markdown: 2.0.0 - mdast-util-mdx-expression: 2.0.0 - mdast-util-mdx-jsx: 3.0.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.1.3 mdast-util-mdxjs-esm: 2.0.1 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: @@ -9295,38 +9359,38 @@ snapshots: mdast-util-mdxjs-esm@2.0.1: dependencies: - '@types/estree-jsx': 1.0.3 - '@types/hast': 3.0.3 - '@types/mdast': 4.0.3 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.0 + mdast-util-from-markdown: 2.0.2 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - mdast-util-phrasing@4.0.0: + mdast-util-phrasing@4.1.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 unist-util-is: 6.0.0 - mdast-util-to-hast@13.1.0: + mdast-util-to-hast@13.2.0: dependencies: - '@types/hast': 3.0.3 - '@types/mdast': 4.0.3 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 '@ungap/structured-clone': 1.2.0 devlop: 1.1.0 micromark-util-sanitize-uri: 2.0.0 trim-lines: 3.0.1 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 - vfile: 6.0.1 + vfile: 6.0.3 mdast-util-to-markdown@2.1.0: dependencies: - '@types/mdast': 4.0.3 - '@types/unist': 3.0.2 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 longest-streak: 3.1.0 - mdast-util-phrasing: 4.0.0 + mdast-util-phrasing: 4.1.0 mdast-util-to-string: 4.0.0 micromark-util-decode-string: 2.0.0 unist-util-visit: 5.0.0 @@ -9334,17 +9398,21 @@ snapshots: mdast-util-to-string@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdn-data@2.0.28: {} mdn-data@2.0.30: {} + mdn-data@2.10.0: {} + + mdn-data@2.12.1: {} + media-typer@0.3.0: {} memoize-one@5.2.1: {} - meow@13.1.0: {} + meow@13.2.0: {} meow@8.1.2: dependencies: @@ -9360,11 +9428,9 @@ snapshots: type-fest: 0.18.1 yargs-parser: 20.2.9 - merge-stream@2.0.0: {} - merge2@1.4.1: {} - micromark-core-commonmark@2.0.0: + micromark-core-commonmark@2.0.1: dependencies: decode-named-character-reference: 1.0.2 devlop: 1.1.0 @@ -9373,35 +9439,35 @@ snapshots: micromark-factory-space: 2.0.0 micromark-factory-title: 2.0.0 micromark-factory-whitespace: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-chunked: 2.0.0 micromark-util-classify-character: 2.0.0 micromark-util-html-tag-name: 2.0.0 micromark-util-normalize-identifier: 2.0.0 micromark-util-resolve-all: 2.0.0 - micromark-util-subtokenize: 2.0.0 + micromark-util-subtokenize: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-gfm-autolink-literal@2.0.0: + micromark-extension-gfm-autolink-literal@2.1.0: dependencies: - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-sanitize-uri: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-gfm-footnote@2.0.0: + micromark-extension-gfm-footnote@2.1.0: dependencies: devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 + micromark-core-commonmark: 2.0.1 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-normalize-identifier: 2.0.0 micromark-util-sanitize-uri: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-gfm-strikethrough@2.0.0: + micromark-extension-gfm-strikethrough@2.1.0: dependencies: devlop: 1.1.0 micromark-util-chunked: 2.0.0 @@ -9410,11 +9476,11 @@ snapshots: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-gfm-table@2.0.0: + micromark-extension-gfm-table@2.1.0: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 @@ -9422,45 +9488,46 @@ snapshots: dependencies: micromark-util-types: 2.0.0 - micromark-extension-gfm-task-list-item@2.0.1: + micromark-extension-gfm-task-list-item@2.1.0: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 micromark-extension-gfm@3.0.0: dependencies: - micromark-extension-gfm-autolink-literal: 2.0.0 - micromark-extension-gfm-footnote: 2.0.0 - micromark-extension-gfm-strikethrough: 2.0.0 - micromark-extension-gfm-table: 2.0.0 + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.0 micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.0.1 + micromark-extension-gfm-task-list-item: 2.1.0 micromark-util-combine-extensions: 2.0.0 micromark-util-types: 2.0.0 micromark-extension-mdx-expression@3.0.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 devlop: 1.1.0 - micromark-factory-mdx-expression: 2.0.1 + micromark-factory-mdx-expression: 2.0.2 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-events-to-acorn: 2.0.2 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-extension-mdx-jsx@3.0.0: + micromark-extension-mdx-jsx@3.0.1: dependencies: '@types/acorn': 4.0.6 - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 - micromark-factory-mdx-expression: 2.0.1 + micromark-factory-mdx-expression: 2.0.2 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 + micromark-util-events-to-acorn: 2.0.2 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 vfile-message: 4.0.2 @@ -9471,10 +9538,10 @@ snapshots: micromark-extension-mdxjs-esm@3.0.0: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 - micromark-util-character: 2.0.1 + micromark-core-commonmark: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-events-to-acorn: 2.0.2 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 @@ -9483,10 +9550,10 @@ snapshots: micromark-extension-mdxjs@3.0.0: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) micromark-extension-mdx-expression: 3.0.0 - micromark-extension-mdx-jsx: 3.0.0 + micromark-extension-mdx-jsx: 3.0.1 micromark-extension-mdx-md: 2.0.0 micromark-extension-mdxjs-esm: 3.0.0 micromark-util-combine-extensions: 2.0.0 @@ -9494,22 +9561,23 @@ snapshots: micromark-factory-destination@2.0.0: dependencies: - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 micromark-factory-label@2.0.0: dependencies: devlop: 1.1.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-factory-mdx-expression@2.0.1: + micromark-factory-mdx-expression@2.0.2: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 devlop: 1.1.0 - micromark-util-character: 2.0.1 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 micromark-util-events-to-acorn: 2.0.2 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 @@ -9518,24 +9586,24 @@ snapshots: micromark-factory-space@2.0.0: dependencies: - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-types: 2.0.0 micromark-factory-title@2.0.0: dependencies: micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 micromark-factory-whitespace@2.0.0: dependencies: micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - micromark-util-character@2.0.1: + micromark-util-character@2.1.0: dependencies: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 @@ -9546,7 +9614,7 @@ snapshots: micromark-util-classify-character@2.0.0: dependencies: - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 @@ -9562,7 +9630,7 @@ snapshots: micromark-util-decode-string@2.0.0: dependencies: decode-named-character-reference: 1.0.2 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-decode-numeric-character-reference: 2.0.1 micromark-util-symbol: 2.0.0 @@ -9571,8 +9639,8 @@ snapshots: micromark-util-events-to-acorn@2.0.2: dependencies: '@types/acorn': 4.0.6 - '@types/estree': 1.0.5 - '@types/unist': 3.0.2 + '@types/estree': 1.0.6 + '@types/unist': 3.0.3 devlop: 1.1.0 estree-util-visit: 2.0.0 micromark-util-symbol: 2.0.0 @@ -9591,11 +9659,11 @@ snapshots: micromark-util-sanitize-uri@2.0.0: dependencies: - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-encode: 2.0.0 micromark-util-symbol: 2.0.0 - micromark-util-subtokenize@2.0.0: + micromark-util-subtokenize@2.0.1: dependencies: devlop: 1.1.0 micromark-util-chunked: 2.0.0 @@ -9609,12 +9677,12 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.4 + debug: 4.3.7 decode-named-character-reference: 1.0.2 devlop: 1.1.0 - micromark-core-commonmark: 2.0.0 + micromark-core-commonmark: 2.0.1 micromark-factory-space: 2.0.0 - micromark-util-character: 2.0.1 + micromark-util-character: 2.1.0 micromark-util-chunked: 2.0.0 micromark-util-combine-extensions: 2.0.0 micromark-util-decode-numeric-character-reference: 2.0.1 @@ -9622,13 +9690,13 @@ snapshots: micromark-util-normalize-identifier: 2.0.0 micromark-util-resolve-all: 2.0.0 micromark-util-sanitize-uri: 2.0.0 - micromark-util-subtokenize: 2.0.0 + micromark-util-subtokenize: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 transitivePeerDependencies: - supports-color - micromatch@4.0.5: + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 @@ -9639,10 +9707,6 @@ snapshots: dependencies: mime-db: 1.52.0 - mimic-fn@2.1.0: {} - - mimic-fn@4.0.0: {} - min-indent@1.0.1: {} minimatch@3.1.2: @@ -9657,6 +9721,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + minimist-options@4.1.0: dependencies: arrify: 1.0.1 @@ -9665,38 +9733,36 @@ snapshots: minimist@1.2.8: {} - minipass@7.0.4: {} - modify-values@1.0.1: {} - ms@2.1.2: {} - ms@2.1.3: {} - msw@2.1.4(typescript@5.3.3): + msw@2.6.0(@types/node@20.17.2)(typescript@5.3.3): dependencies: '@bundled-es-modules/cookie': 2.0.0 '@bundled-es-modules/statuses': 1.0.1 - '@mswjs/cookies': 1.1.0 - '@mswjs/interceptors': 0.25.14 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.0.1(@types/node@20.17.2) + '@mswjs/interceptors': 0.36.6 + '@open-draft/deferred-promise': 2.2.0 '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 - '@types/statuses': 2.0.4 + '@types/statuses': 2.0.5 chalk: 4.1.2 - chokidar: 3.5.3 - graphql: 16.8.1 - headers-polyfill: 4.0.2 - inquirer: 8.2.6 + graphql: 16.9.0 + headers-polyfill: 4.0.3 is-node-process: 1.2.0 - outvariant: 1.4.2 - path-to-regexp: 6.2.1 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 strict-event-emitter: 0.5.1 - type-fest: 4.10.1 + type-fest: 4.26.1 yargs: 17.7.2 optionalDependencies: typescript: 5.3.3 + transitivePeerDependencies: + - '@types/node' - mute-stream@0.0.8: {} + mute-stream@2.0.0: {} nanoid@3.3.7: {} @@ -9709,9 +9775,11 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.6.2 + tslib: 2.8.0 - node-releases@2.0.14: {} + node-addon-api@7.1.1: {} + + node-releases@2.0.18: {} normalize-package-data@2.5.0: dependencies: @@ -9723,74 +9791,59 @@ snapshots: normalize-package-data@3.0.3: dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.13.1 - semver: 7.5.4 + is-core-module: 2.15.1 + semver: 7.6.3 validate-npm-package-license: 3.0.4 normalize-path@3.0.0: {} normalize-range@0.1.2: {} - not@0.1.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-run-path@5.2.0: - dependencies: - path-key: 4.0.0 - nth-check@2.1.1: dependencies: boolbase: 1.0.0 - numbro@2.4.0: + numbro@2.5.0: dependencies: bignumber.js: 9.1.2 object-assign@4.1.1: {} - object-inspect@1.13.1: {} + object-inspect@1.13.2: {} object-keys@1.1.1: {} object.assign@4.1.5: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - object.entries@1.1.7: - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - - object.fromentries@2.0.7: + object.entries@1.1.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.0.0 - object.groupby@1.0.1: + object.fromentries@2.0.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 - object.hasown@1.1.3: + object.groupby@1.0.3: dependencies: + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 - object.values@1.1.7: + object.values@1.2.0: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.0.0 on-finished@2.4.1: dependencies: @@ -9800,47 +9853,25 @@ snapshots: dependencies: wrappy: 1.0.2 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - only@0.0.2: {} - open@9.1.0: + open@10.1.0: dependencies: - default-browser: 4.0.0 + default-browser: 5.2.1 define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 - is-wsl: 2.2.0 + is-wsl: 3.1.0 - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 - ora@5.4.1: - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.9.2 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - - os-tmpdir@1.0.2: {} - - outvariant@1.4.2: {} + outvariant@1.4.3: {} p-limit@1.3.0: dependencies: @@ -9880,7 +9911,7 @@ snapshots: parse-entities@4.0.1: dependencies: - '@types/unist': 2.0.10 + '@types/unist': 2.0.11 character-entities: 2.0.2 character-entities-legacy: 3.0.0 character-reference-invalid: 2.0.1 @@ -9896,12 +9927,12 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.26.0 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - parse5@7.1.2: + parse5@7.2.1: dependencies: entities: 4.5.0 @@ -9915,16 +9946,9 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} - path-scurry@1.10.1: - dependencies: - lru-cache: 10.1.0 - minipass: 7.0.4 - - path-to-regexp@6.2.1: {} + path-to-regexp@6.3.0: {} path-type@3.0.0: dependencies: @@ -9934,46 +9958,44 @@ snapshots: path-type@5.0.0: {} - periscopic@3.1.0: - dependencies: - '@types/estree': 1.0.5 - estree-walker: 3.0.3 - is-reference: 3.0.2 - - picocolors@1.0.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pify@2.3.0: {} pify@3.0.0: {} pngjs@5.0.0: {} + possible-typed-array-names@1.0.0: {} + postcss-media-query-parser@0.2.3: {} - postcss-resolve-nested-selector@0.1.1: {} + postcss-resolve-nested-selector@0.1.6: {} - postcss-safe-parser@7.0.0(postcss@8.4.33): + postcss-safe-parser@7.0.1(postcss@8.4.47): dependencies: - postcss: 8.4.33 + postcss: 8.4.47 - postcss-scss@4.0.9(postcss@8.4.33): + postcss-scss@4.0.9(postcss@8.4.47): dependencies: - postcss: 8.4.33 + postcss: 8.4.47 - postcss-selector-parser@6.0.15: + postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 postcss-value-parser@4.2.0: {} - postcss@8.4.33: + postcss@8.4.47: dependencies: nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.0.2 + picocolors: 1.1.1 + source-map-js: 1.2.1 prelude-ls@1.2.1: {} @@ -9983,13 +10005,13 @@ snapshots: prettier@2.8.8: {} - prettier@3.2.4: {} + prettier@3.3.3: {} - prism-react-renderer@2.3.1(react@18.2.0): + prism-react-renderer@2.4.0(react@18.3.1): dependencies: - '@types/prismjs': 1.26.3 - clsx: 2.1.0 - react: 18.2.0 + '@types/prismjs': 1.26.5 + clsx: 2.1.1 + react: 18.3.1 process-nextick-args@2.0.1: {} @@ -9999,147 +10021,148 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 - property-information@6.4.1: {} + property-information@6.5.0: {} proxy-from-env@1.1.0: {} + psl@1.9.0: {} + punycode@2.3.1: {} q@1.5.1: {} qr.js@0.0.0: {} - qrcode@1.5.3: + qrcode@1.5.4: dependencies: dijkstrajs: 1.0.3 - encode-utf8: 1.0.3 pngjs: 5.0.0 yargs: 15.4.1 - query-string@8.1.0: + query-string@9.1.1: dependencies: decode-uri-component: 0.4.1 filter-obj: 5.1.0 split-on-first: 3.0.0 + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} quick-lru@4.0.1: {} - radash@11.0.0: {} + radash@12.1.0: {} - react-click-away-listener@2.2.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-click-away-listener@2.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-dom@18.2.0(react@18.2.0): + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 - react: 18.2.0 - scheduler: 0.23.0 + react: 18.3.1 + scheduler: 0.23.2 - react-hook-form@7.49.3(react@18.2.0): + react-hook-form@7.53.1(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 - react-hotkeys-hook@4.4.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-hotkeys-hook@4.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-idle-timer@5.7.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-idle-timer@5.7.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-inspector@6.0.2(react@18.2.0): + react-inspector@6.0.2(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 react-is@16.13.1: {} - react-is@18.2.0: {} - - react-lifecycles-compat@3.0.4: {} + react-is@18.3.1: {} - react-loading-skeleton@3.3.1(react@18.2.0): + react-loading-skeleton@3.5.0(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 - react-markdown@9.0.1(@types/react@18.2.48)(react@18.2.0): + react-markdown@9.0.1(@types/react@18.3.12)(react@18.3.1): dependencies: - '@types/hast': 3.0.3 - '@types/react': 18.2.48 + '@types/hast': 3.0.4 + '@types/react': 18.3.12 devlop: 1.1.0 - hast-util-to-jsx-runtime: 2.3.0 - html-url-attributes: 3.0.0 - mdast-util-to-hast: 13.1.0 - react: 18.2.0 + hast-util-to-jsx-runtime: 2.3.2 + html-url-attributes: 3.0.1 + mdast-util-to-hast: 13.2.0 + react: 18.3.1 remark-parse: 11.0.0 - remark-rehype: 11.1.0 - unified: 11.0.4 + remark-rehype: 11.1.1 + unified: 11.0.5 unist-util-visit: 5.0.0 - vfile: 6.0.1 + vfile: 6.0.3 transitivePeerDependencies: - supports-color react-property@2.0.2: {} - react-qr-code@2.0.12(react@18.2.0): + react-qr-code@2.0.15(react@18.3.1): dependencies: prop-types: 15.8.1 qr.js: 0.0.0 - react: 18.2.0 + react: 18.3.1 - react-refresh@0.14.0: {} + react-refresh@0.14.2: {} - react-router-dom@6.21.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-router-dom@6.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@remix-run/router': 1.14.2 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-router: 6.21.3(react@18.2.0) + '@remix-run/router': 1.20.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-router: 6.27.0(react@18.3.1) - react-router@6.21.3(react@18.2.0): + react-router@6.27.0(react@18.3.1): dependencies: - '@remix-run/router': 1.14.2 - react: 18.2.0 + '@remix-run/router': 1.20.0 + react: 18.3.1 - react-simple-animate@3.5.2(react-dom@18.2.0(react@18.2.0)): + react-simple-animate@3.5.2(react-dom@18.3.1(react@18.3.1)): dependencies: - react-dom: 18.2.0(react@18.2.0) + react-dom: 18.3.1(react@18.3.1) - react-smooth@2.0.5(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-smooth@4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: fast-equals: 5.0.1 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-transition-group: 2.9.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-transition-group@2.9.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - dom-helpers: 3.4.0 + '@babel/runtime': 7.26.0 + dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-lifecycles-compat: 3.0.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-virtualized-auto-sizer@1.0.21(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-virtualized-auto-sizer@1.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react-window@1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + react-window@1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 memoize-one: 5.2.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - react@18.2.0: + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -10187,39 +10210,71 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.0.2: {} + recharts-scale@0.4.5: dependencies: decimal.js-light: 2.5.1 - recharts@2.10.4(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + recharts@2.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - clsx: 2.1.0 + clsx: 2.1.1 eventemitter3: 4.0.7 lodash: 4.17.21 - prop-types: 15.8.1 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - react-is: 16.13.1 - react-smooth: 2.0.5(prop-types@15.8.1)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-is: 18.3.1 + react-smooth: 4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) recharts-scale: 0.4.5 - tiny-invariant: 1.3.1 - victory-vendor: 36.8.2 + tiny-invariant: 1.3.3 + victory-vendor: 36.9.2 + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.0(acorn@8.14.0): + dependencies: + acorn-jsx: 5.3.2(acorn@8.14.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - acorn + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.6 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.6 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 redent@3.0.0: dependencies: indent-string: 4.0.0 strip-indent: 3.0.0 - reflect.getprototypeof@1.0.4: + reflect.getprototypeof@1.0.6: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.4 + which-builtin-type: 1.1.4 - regenerate-unicode-properties@10.1.1: + regenerate-unicode-properties@10.2.0: dependencies: regenerate: 1.4.2 @@ -10229,52 +10284,63 @@ snapshots: regenerator-transform@0.15.2: dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 - regexp.prototype.flags@1.5.1: + regexp.prototype.flags@1.5.3: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - set-function-name: 2.0.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 - regexpu-core@5.3.2: + regexpu-core@6.1.1: dependencies: - '@babel/regjsgen': 0.8.0 regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.11.2 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 + unicode-match-property-value-ecmascript: 2.2.0 - regjsparser@0.9.1: + regjsgen@0.8.0: {} + + regjsparser@0.11.2: dependencies: - jsesc: 0.5.0 + jsesc: 3.0.2 - rehype-class-names@1.0.14: + rehype-class-names@2.0.0: dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 hast-util-classnames: 3.0.0 - hast-util-select: 6.0.2 - unified: 10.1.2 + hast-util-select: 6.0.3 + unified: 11.0.5 rehype-raw@7.0.0: dependencies: - '@types/hast': 3.0.3 - hast-util-raw: 9.0.2 - vfile: 6.0.1 + '@types/hast': 3.0.4 + hast-util-raw: 9.0.4 + vfile: 6.0.3 + + rehype-recma@1.0.0: + dependencies: + '@types/estree': 1.0.6 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.0 + transitivePeerDependencies: + - supports-color remark-gfm@4.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdast-util-gfm: 3.0.0 micromark-extension-gfm: 3.0.0 remark-parse: 11.0.0 remark-stringify: 11.0.0 - unified: 11.0.4 + unified: 11.0.5 transitivePeerDependencies: - supports-color - remark-mdx@3.0.0: + remark-mdx@3.1.0: dependencies: mdast-util-mdx: 3.0.0 micromark-extension-mdxjs: 3.0.0 @@ -10283,28 +10349,28 @@ snapshots: remark-parse@11.0.0: dependencies: - '@types/mdast': 4.0.3 - mdast-util-from-markdown: 2.0.0 + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 micromark-util-types: 2.0.0 - unified: 11.0.4 + unified: 11.0.5 transitivePeerDependencies: - supports-color - remark-rehype@11.1.0: + remark-rehype@11.1.1: dependencies: - '@types/hast': 3.0.3 - '@types/mdast': 4.0.3 - mdast-util-to-hast: 13.1.0 - unified: 11.0.4 - vfile: 6.0.1 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.0 + unified: 11.0.5 + vfile: 6.0.3 remark-stringify@11.0.0: dependencies: - '@types/mdast': 4.0.3 + '@types/mdast': 4.0.4 mdast-util-to-markdown: 2.1.0 - unified: 11.0.4 + unified: 11.0.5 - remove-accents@0.4.2: {} + remove-accents@0.5.0: {} require-directory@2.1.1: {} @@ -10312,47 +10378,37 @@ snapshots: require-main-filename@2.0.0: {} + requires-port@1.0.0: {} + resolve-from@4.0.0: {} resolve-from@5.0.0: {} resolve@1.22.8: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 resolve@2.0.0-next.5: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.15.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - restore-cursor@3.1.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - reusify@1.0.4: {} rimraf@3.0.2: dependencies: glob: 7.2.3 - rimraf@5.0.5: - dependencies: - glob: 10.3.10 - - rollup-plugin-preserve-directives@0.3.1(@rollup/wasm-node@4.24.0): - dependencies: - magic-string: 0.30.5 - rollup: '@rollup/wasm-node@4.24.0' - - run-applescript@5.0.0: + rollup-plugin-preserve-directives@0.4.0(@rollup/wasm-node@4.24.2): dependencies: - execa: 5.1.1 + '@rollup/pluginutils': 5.1.3(@rollup/wasm-node@4.24.2) + magic-string: 0.30.12 + rollup: '@rollup/wasm-node@4.24.2' - run-async@2.4.1: {} + run-applescript@7.0.0: {} run-parallel@1.2.0: dependencies: @@ -10360,12 +10416,12 @@ snapshots: rxjs@7.8.1: dependencies: - tslib: 2.6.2 + tslib: 2.8.0 - safe-array-concat@1.1.0: + safe-array-concat@1.1.2: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 + call-bind: 1.0.7 + get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 @@ -10373,21 +10429,20 @@ snapshots: safe-buffer@5.2.1: {} - safe-regex-test@1.0.2: + safe-regex-test@1.0.3: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 + call-bind: 1.0.7 + es-errors: 1.3.0 is-regex: 1.1.4 - safer-buffer@2.1.2: {} - - sass@1.70.0: + sass@1.80.4: dependencies: - chokidar: 3.5.3 - immutable: 4.3.4 - source-map-js: 1.0.2 + '@parcel/watcher': 2.4.1 + chokidar: 4.0.1 + immutable: 4.3.7 + source-map-js: 1.2.1 - scheduler@0.23.0: + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -10395,25 +10450,25 @@ snapshots: semver@6.3.1: {} - semver@7.5.4: - dependencies: - lru-cache: 6.0.0 + semver@7.6.3: {} set-blocking@2.0.0: {} - set-function-length@1.2.0: + set-function-length@1.2.2: dependencies: - define-data-property: 1.1.1 + define-data-property: 1.1.4 + es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.2 + get-intrinsic: 1.2.4 gopd: 1.0.1 - has-property-descriptors: 1.0.1 + has-property-descriptors: 1.0.2 - set-function-name@2.0.1: + set-function-name@2.0.2: dependencies: - define-data-property: 1.1.1 + define-data-property: 1.1.4 + es-errors: 1.3.0 functions-have-names: 1.2.3 - has-property-descriptors: 1.0.1 + has-property-descriptors: 1.0.2 setprototypeof@1.2.0: {} @@ -10428,17 +10483,16 @@ snapshots: shiki@0.14.7: dependencies: ansi-sequence-parser: 1.1.1 - jsonc-parser: 3.2.1 + jsonc-parser: 3.3.1 vscode-oniguruma: 1.7.0 vscode-textmate: 8.0.0 - side-channel@1.0.4: + side-channel@1.0.6: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - object-inspect: 1.13.1 - - signal-exit@3.0.7: {} + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 signal-exit@4.1.0: {} @@ -10455,9 +10509,9 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.6.2 + tslib: 2.8.0 - source-map-js@1.0.2: {} + source-map-js@1.2.1: {} source-map-support@0.5.21: dependencies: @@ -10472,21 +10526,19 @@ snapshots: space-separated-tokens@2.0.2: {} - spawn-command@0.0.2: {} - spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.16 + spdx-license-ids: 3.0.20 - spdx-exceptions@2.4.0: {} + spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: - spdx-exceptions: 2.4.0 - spdx-license-ids: 3.0.16 + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.20 - spdx-license-ids@3.0.16: {} + spdx-license-ids@3.0.20: {} split-on-first@3.0.0: {} @@ -10511,7 +10563,7 @@ snapshots: figures: 3.2.0 find-up: 5.0.0 git-semver-tags: 4.1.1 - semver: 7.5.4 + semver: 7.6.3 stringify-package: 1.0.1 yargs: 16.2.0 @@ -10533,35 +10585,50 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - string.prototype.matchall@4.0.10: + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + + string.prototype.matchall@4.0.11: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 has-symbols: 1.0.3 - internal-slot: 1.0.6 - regexp.prototype.flags: 1.5.1 - set-function-name: 2.0.1 - side-channel: 1.0.4 + internal-slot: 1.0.7 + regexp.prototype.flags: 1.5.3 + set-function-name: 2.0.2 + side-channel: 1.0.6 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 - string.prototype.trim@1.2.8: + string.prototype.trim@1.2.9: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 - string.prototype.trimend@1.0.7: + string.prototype.trimend@1.0.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.0.0 - string.prototype.trimstart@1.0.7: + string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.0.0 string_decoder@1.1.1: dependencies: @@ -10571,7 +10638,7 @@ snapshots: dependencies: safe-buffer: 5.2.1 - stringify-entities@4.0.3: + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 @@ -10584,83 +10651,82 @@ snapshots: strip-ansi@7.1.0: dependencies: - ansi-regex: 6.0.1 + ansi-regex: 6.1.0 strip-bom@3.0.0: {} - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - strip-indent@3.0.0: dependencies: min-indent: 1.0.1 strip-json-comments@3.1.1: {} - style-to-js@1.1.10: + style-to-js@1.1.16: dependencies: - style-to-object: 1.0.5 + style-to-object: 1.0.8 style-to-object@0.4.4: dependencies: inline-style-parser: 0.1.1 - style-to-object@1.0.5: + style-to-object@1.0.8: dependencies: - inline-style-parser: 0.2.2 + inline-style-parser: 0.2.4 stylelint-config-prettier-scss@1.0.0(stylelint@16.2.0(typescript@5.3.3)): dependencies: stylelint: 16.2.0(typescript@5.3.3) - stylelint-config-recommended-scss@14.0.0(postcss@8.4.33)(stylelint@16.2.0(typescript@5.3.3)): + stylelint-config-recommended-scss@14.1.0(postcss@8.4.47)(stylelint@16.2.0(typescript@5.3.3)): dependencies: - postcss-scss: 4.0.9(postcss@8.4.33) + postcss-scss: 4.0.9(postcss@8.4.47) stylelint: 16.2.0(typescript@5.3.3) - stylelint-config-recommended: 14.0.0(stylelint@16.2.0(typescript@5.3.3)) - stylelint-scss: 6.1.0(stylelint@16.2.0(typescript@5.3.3)) + stylelint-config-recommended: 14.0.1(stylelint@16.2.0(typescript@5.3.3)) + stylelint-scss: 6.8.1(stylelint@16.2.0(typescript@5.3.3)) optionalDependencies: - postcss: 8.4.33 + postcss: 8.4.47 - stylelint-config-recommended@14.0.0(stylelint@16.2.0(typescript@5.3.3)): + stylelint-config-recommended@14.0.1(stylelint@16.2.0(typescript@5.3.3)): dependencies: stylelint: 16.2.0(typescript@5.3.3) - stylelint-config-standard-scss@13.0.0(postcss@8.4.33)(stylelint@16.2.0(typescript@5.3.3)): + stylelint-config-standard-scss@13.1.0(postcss@8.4.47)(stylelint@16.2.0(typescript@5.3.3)): dependencies: stylelint: 16.2.0(typescript@5.3.3) - stylelint-config-recommended-scss: 14.0.0(postcss@8.4.33)(stylelint@16.2.0(typescript@5.3.3)) - stylelint-config-standard: 36.0.0(stylelint@16.2.0(typescript@5.3.3)) + stylelint-config-recommended-scss: 14.1.0(postcss@8.4.47)(stylelint@16.2.0(typescript@5.3.3)) + stylelint-config-standard: 36.0.1(stylelint@16.2.0(typescript@5.3.3)) optionalDependencies: - postcss: 8.4.33 + postcss: 8.4.47 - stylelint-config-standard@36.0.0(stylelint@16.2.0(typescript@5.3.3)): + stylelint-config-standard@36.0.1(stylelint@16.2.0(typescript@5.3.3)): dependencies: stylelint: 16.2.0(typescript@5.3.3) - stylelint-config-recommended: 14.0.0(stylelint@16.2.0(typescript@5.3.3)) + stylelint-config-recommended: 14.0.1(stylelint@16.2.0(typescript@5.3.3)) - stylelint-scss@6.1.0(stylelint@16.2.0(typescript@5.3.3)): + stylelint-scss@6.8.1(stylelint@16.2.0(typescript@5.3.3)): dependencies: - known-css-properties: 0.29.0 + css-tree: 3.0.0 + is-plain-object: 5.0.0 + known-css-properties: 0.34.0 + mdn-data: 2.12.1 postcss-media-query-parser: 0.2.3 - postcss-resolve-nested-selector: 0.1.1 - postcss-selector-parser: 6.0.15 + postcss-resolve-nested-selector: 0.1.6 + postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 stylelint: 16.2.0(typescript@5.3.3) stylelint@16.2.0(typescript@5.3.3): dependencies: - '@csstools/css-parser-algorithms': 2.5.0(@csstools/css-tokenizer@2.2.3) - '@csstools/css-tokenizer': 2.2.3 - '@csstools/media-query-list-parser': 2.1.7(@csstools/css-parser-algorithms@2.5.0(@csstools/css-tokenizer@2.2.3))(@csstools/css-tokenizer@2.2.3) - '@csstools/selector-specificity': 3.0.1(postcss-selector-parser@6.0.15) + '@csstools/css-parser-algorithms': 2.7.1(@csstools/css-tokenizer@2.4.1) + '@csstools/css-tokenizer': 2.4.1 + '@csstools/media-query-list-parser': 2.1.13(@csstools/css-parser-algorithms@2.7.1(@csstools/css-tokenizer@2.4.1))(@csstools/css-tokenizer@2.4.1) + '@csstools/selector-specificity': 3.1.1(postcss-selector-parser@6.1.2) balanced-match: 2.0.0 colord: 2.9.3 cosmiconfig: 9.0.0(typescript@5.3.3) - css-functions-list: 3.2.1 + css-functions-list: 3.2.3 css-tree: 2.3.1 - debug: 4.3.4 + debug: 4.3.7 fast-glob: 3.3.2 fastest-levenshtein: 1.0.16 file-entry-cache: 8.0.0 @@ -10668,26 +10734,26 @@ snapshots: globby: 11.1.0 globjoin: 0.1.4 html-tags: 3.3.1 - ignore: 5.3.0 + ignore: 5.3.2 imurmurhash: 0.1.4 is-plain-object: 5.0.0 known-css-properties: 0.29.0 mathml-tag-names: 2.1.3 - meow: 13.1.0 - micromatch: 4.0.5 + meow: 13.2.0 + micromatch: 4.0.8 normalize-path: 3.0.0 - picocolors: 1.0.0 - postcss: 8.4.33 - postcss-resolve-nested-selector: 0.1.1 - postcss-safe-parser: 7.0.0(postcss@8.4.33) - postcss-selector-parser: 6.0.15 + picocolors: 1.1.1 + postcss: 8.4.47 + postcss-resolve-nested-selector: 0.1.6 + postcss-safe-parser: 7.0.1(postcss@8.4.47) + postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 string-width: 4.2.3 strip-ansi: 7.1.0 - supports-hyperlinks: 3.0.0 + supports-hyperlinks: 3.1.0 svg-tags: 1.0.0 - table: 6.8.1 + table: 6.8.2 write-file-atomic: 5.0.1 transitivePeerDependencies: - supports-color @@ -10711,7 +10777,7 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-hyperlinks@3.0.0: + supports-hyperlinks@3.1.0: dependencies: has-flag: 4.0.0 supports-color: 7.2.0 @@ -10722,7 +10788,7 @@ snapshots: svg-tags@1.0.0: {} - svgo@3.2.0: + svgo@3.3.2: dependencies: '@trysound/sax': 0.2.0 commander: 7.2.0 @@ -10730,29 +10796,29 @@ snapshots: css-tree: 2.3.1 css-what: 6.1.0 csso: 5.0.5 - picocolors: 1.0.0 + picocolors: 1.1.1 - synckit@0.8.8: + synckit@0.9.2: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.2 + tslib: 2.8.0 - systemjs@6.14.3: {} + systemjs@6.15.1: {} tabbable@6.2.0: {} - table@6.8.1: + table@6.8.2: dependencies: - ajv: 8.12.0 + ajv: 8.17.1 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 strip-ansi: 6.0.1 - terser@5.27.0: + terser@5.36.0: dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.11.3 + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -10771,15 +10837,7 @@ snapshots: through@2.3.8: {} - tiny-invariant@1.3.1: {} - - titleize@3.0.0: {} - - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - - to-fast-properties@2.0.0: {} + tiny-invariant@1.3.3: {} to-regex-range@5.0.1: dependencies: @@ -10787,19 +10845,26 @@ snapshots: toidentifier@1.0.1: {} + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tree-kill@1.2.2: {} trim-lines@3.0.1: {} trim-newlines@3.0.1: {} - trough@2.1.0: {} + trough@2.2.0: {} - ts-api-utils@1.0.3(typescript@5.3.3): + ts-api-utils@1.3.0(typescript@5.3.3): dependencies: typescript: 5.3.3 - tsconfck@3.0.1(typescript@5.3.3): + tsconfck@3.1.4(typescript@5.3.3): optionalDependencies: typescript: 5.3.3 @@ -10810,9 +10875,9 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tslib@2.4.0: {} + tslib@2.7.0: {} - tslib@2.6.2: {} + tslib@2.8.0: {} tsscmp@1.0.6: {} @@ -10832,47 +10897,52 @@ snapshots: type-fest@2.19.0: {} - type-fest@4.10.1: {} + type-fest@4.26.1: {} type-is@1.6.18: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - typed-array-buffer@1.0.0: + typed-array-buffer@1.0.2: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 - typed-array-byte-length@1.0.0: + typed-array-byte-length@1.0.1: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 - typed-array-byte-offset@1.0.0: + typed-array-byte-offset@1.0.2: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 - typed-array-length@1.0.4: + typed-array-length@1.0.6: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 for-each: 0.3.3 - is-typed-array: 1.1.12 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 typedarray@0.0.6: {} - typedoc@0.25.7(typescript@5.3.3): + typedoc@0.25.13(typescript@5.3.3): dependencies: lunr: 2.3.9 marked: 4.3.0 - minimatch: 9.0.3 + minimatch: 9.0.5 shiki: 0.14.7 typescript: 5.3.3 @@ -10880,121 +10950,107 @@ snapshots: dependencies: typescript: 5.3.3 - typescript-eslint-language-service@5.0.5(@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3): + typescript-eslint-language-service@5.0.5(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.3.3))(eslint@8.57.1)(typescript@5.3.3): dependencies: - '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) - eslint: 8.56.0 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.3.3) + eslint: 8.57.1 typescript: 5.3.3 typescript@5.3.3: {} - uglify-js@3.17.4: + uglify-js@3.19.3: optional: true unbox-primitive@1.0.2: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.7 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - undici-types@5.26.5: {} + undici-types@6.19.8: {} - unicode-canonical-property-names-ecmascript@2.0.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-canonical-property-names-ecmascript: 2.0.1 unicode-property-aliases-ecmascript: 2.1.0 - unicode-match-property-value-ecmascript@2.1.0: {} + unicode-match-property-value-ecmascript@2.2.0: {} unicode-property-aliases-ecmascript@2.1.0: {} unicorn-magic@0.1.0: {} - unified@10.1.2: - dependencies: - '@types/unist': 2.0.10 - bail: 2.0.2 - extend: 3.0.2 - is-buffer: 2.0.5 - is-plain-obj: 4.1.0 - trough: 2.1.0 - vfile: 5.3.7 - - unified@11.0.4: + unified@11.0.5: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 bail: 2.0.2 devlop: 1.1.0 extend: 3.0.2 is-plain-obj: 4.1.0 - trough: 2.1.0 - vfile: 6.0.1 + trough: 2.2.0 + vfile: 6.0.3 unist-util-is@6.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-position-from-estree@2.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-position@5.0.0: dependencies: - '@types/unist': 3.0.2 - - unist-util-remove-position@5.0.0: - dependencies: - '@types/unist': 3.0.2 - unist-util-visit: 5.0.0 - - unist-util-stringify-position@3.0.3: - dependencies: - '@types/unist': 2.0.10 + '@types/unist': 3.0.3 unist-util-stringify-position@4.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-visit-parents@6.0.1: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit@5.0.0: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - untildify@4.0.0: {} + universalify@0.2.0: {} - update-browserslist-db@1.0.13(browserslist@4.22.2): + update-browserslist-db@1.1.1(browserslist@4.24.2): dependencies: - browserslist: 4.22.2 - escalade: 3.1.1 - picocolors: 1.0.0 + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 uri-js@4.4.1: dependencies: punycode: 2.3.1 - use-breakpoint@4.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + use-breakpoint@4.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - use-deep-compare-effect@1.8.1(react@18.2.0): + use-deep-compare-effect@1.8.1(react@18.3.1): dependencies: - '@babel/runtime': 7.23.8 + '@babel/runtime': 7.26.0 dequal: 2.0.3 - react: 18.2.0 + react: 18.3.1 - use-sync-external-store@1.2.0(react@18.2.0): + use-sync-external-store@1.2.2(react@18.3.1): dependencies: - react: 18.2.0 + react: 18.3.1 util-deprecate@1.0.2: {} @@ -11007,35 +11063,22 @@ snapshots: vary@1.1.2: {} - vfile-location@5.0.2: - dependencies: - '@types/unist': 3.0.2 - vfile: 6.0.1 - - vfile-message@3.1.4: + vfile-location@5.0.3: dependencies: - '@types/unist': 2.0.10 - unist-util-stringify-position: 3.0.3 + '@types/unist': 3.0.3 + vfile: 6.0.3 vfile-message@4.0.2: dependencies: - '@types/unist': 3.0.2 + '@types/unist': 3.0.3 unist-util-stringify-position: 4.0.0 - vfile@5.3.7: - dependencies: - '@types/unist': 2.0.10 - is-buffer: 2.0.5 - unist-util-stringify-position: 3.0.3 - vfile-message: 3.1.4 - - vfile@6.0.1: + vfile@6.0.3: dependencies: - '@types/unist': 3.0.2 - unist-util-stringify-position: 4.0.0 + '@types/unist': 3.0.3 vfile-message: 4.0.2 - victory-vendor@36.8.2: + victory-vendor@36.9.2: dependencies: '@types/d3-array': 3.2.1 '@types/d3-ease': 3.0.2 @@ -11052,48 +11095,44 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-eslint@1.8.1(eslint@8.56.0)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)): + vite-plugin-eslint@1.8.1(eslint@8.57.1)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)): dependencies: '@rollup/pluginutils': 4.2.1 - '@types/eslint': 8.56.2 - eslint: 8.56.0 - rollup: '@rollup/wasm-node@4.24.0' - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + '@types/eslint': 8.56.12 + eslint: 8.57.1 + rollup: '@rollup/wasm-node@4.24.2' + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) - vite-plugin-package-version@1.1.0(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)): + vite-plugin-package-version@1.1.0(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)): dependencies: - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) - vite-tsconfig-paths@4.3.1(typescript@5.3.3)(vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0)): + vite-tsconfig-paths@4.3.2(typescript@5.3.3)(vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0)): dependencies: - debug: 4.3.4 + debug: 4.3.7 globrex: 0.1.2 - tsconfck: 3.0.1(typescript@5.3.3) + tsconfck: 3.1.4(typescript@5.3.3) optionalDependencies: - vite: 5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0) + vite: 5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0) transitivePeerDependencies: - supports-color - typescript - vite@5.0.12(@types/node@20.11.7)(sass@1.70.0)(terser@5.27.0): + vite@5.4.10(@types/node@20.17.2)(sass@1.80.4)(terser@5.36.0): dependencies: - esbuild: 0.19.12 - postcss: 8.4.33 - rollup: '@rollup/wasm-node@4.24.0' + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: '@rollup/wasm-node@4.24.2' optionalDependencies: - '@types/node': 20.11.7 + '@types/node': 20.17.2 fsevents: 2.3.3 - sass: 1.70.0 - terser: 5.27.0 + sass: 1.80.4 + terser: 5.36.0 vscode-oniguruma@1.7.0: {} vscode-textmate@8.0.0: {} - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - web-namespaces@2.0.1: {} which-boxed-primitive@1.0.2: @@ -11104,10 +11143,10 @@ snapshots: is-string: 1.0.7 is-symbol: 1.0.4 - which-builtin-type@1.1.3: + which-builtin-type@1.1.4: dependencies: function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-async-function: 2.0.0 is-date-object: 1.0.5 is-finalizationregistry: 1.0.2 @@ -11116,25 +11155,25 @@ snapshots: is-weakref: 1.0.2 isarray: 2.0.5 which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.13 + which-collection: 1.0.2 + which-typed-array: 1.1.15 - which-collection@1.0.1: + which-collection@1.0.2: dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 which-module@2.0.1: {} - which-typed-array@1.1.13: + which-typed-array@1.1.15: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 which@1.3.1: dependencies: @@ -11148,6 +11187,8 @@ snapshots: dependencies: string-width: 5.1.2 + word-wrap@1.2.5: {} + wordwrap@1.0.0: {} wrap-ansi@6.2.0: @@ -11175,7 +11216,7 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 4.1.0 - ws@8.5.0: {} + ws@8.17.1: {} xtend@4.0.2: {} @@ -11215,7 +11256,7 @@ snapshots: yargs@16.2.0: dependencies: cliui: 7.0.4 - escalade: 3.1.1 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 @@ -11225,24 +11266,26 @@ snapshots: yargs@17.7.2: dependencies: cliui: 8.0.1 - escalade: 3.1.1 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - ylru@1.3.2: {} + ylru@1.4.0: {} yocto-queue@0.1.0: {} - zod@3.22.4: {} + yoctocolors-cjs@2.1.2: {} + + zod@3.23.8: {} - zustand@4.5.0(@types/react@18.2.48)(react@18.2.0): + zustand@4.5.5(@types/react@18.3.12)(react@18.3.1): dependencies: - use-sync-external-store: 1.2.0(react@18.2.0) + use-sync-external-store: 1.2.2(react@18.3.1) optionalDependencies: - '@types/react': 18.2.48 - react: 18.2.0 + '@types/react': 18.3.12 + react: 18.3.1 zwitch@2.0.4: {} diff --git a/web/src/pages/network/NetworkGateway/NetworkGateway.tsx b/web/src/pages/network/NetworkGateway/NetworkGateway.tsx index 9dc55208d..c053d431c 100644 --- a/web/src/pages/network/NetworkGateway/NetworkGateway.tsx +++ b/web/src/pages/network/NetworkGateway/NetworkGateway.tsx @@ -5,7 +5,6 @@ import { useCallback, useMemo } from 'react'; import ReactMarkdown from 'react-markdown'; import { useI18nContext } from '../../../i18n/i18n-react'; -import { GatewaysStatus } from '../../../shared/components/network/GatewaysStatus/GatewaysStatus'; import { ActionButton } from '../../../shared/defguard-ui/components/Layout/ActionButton/ActionButton'; import { ActionButtonVariant } from '../../../shared/defguard-ui/components/Layout/ActionButton/types'; import { Button } from '../../../shared/defguard-ui/components/Layout/Button/Button'; @@ -19,14 +18,22 @@ import useApi from '../../../shared/hooks/useApi'; import { useClipboard } from '../../../shared/hooks/useClipboard'; import { externalLink } from '../../../shared/links'; import { QueryKeys } from '../../../shared/queries'; +import { AddComponentBox } from '../../users/shared/components/AddComponentBox/AddComponentBox'; import { useNetworkPageStore } from '../hooks/useNetworkPageStore'; +import { GatewayCard } from './components/GatewayCard'; +import { AddGatewayModal } from './modals/AddGatewayModal'; +import { EditGatewayModal } from './modals/EditGatewayModal'; +import { useAddGatewayModal } from './modals/hooks/useAddGatewayModal'; export const NetworkGatewaySetup = () => { const { writeToClipboard } = useClipboard(); const selectedNetworkId = useNetworkPageStore((state) => state.selectedNetworkId); const { LL } = useI18nContext(); const { - network: { getNetworkToken }, + network: { + getNetworkToken, + gateway: { getAllGateways }, + }, } = useApi(); const { data: networkToken } = useQuery( @@ -38,9 +45,18 @@ export const NetworkGatewaySetup = () => { }, ); + const { data: gateways } = useQuery( + [QueryKeys.FETCH_ALL_GATEWAYS, selectedNetworkId], + () => getAllGateways(selectedNetworkId), + { + refetchOnMount: true, + refetchOnWindowFocus: false, + }, + ); + const command = useCallback(() => { // eslint-disable-next-line max-len - return `docker run -e DEFGUARD_TOKEN=${networkToken?.token} -e DEFGUARD_GRPC_URL=${networkToken?.grpc_url} --restart unless-stopped --network host --cap-add NET_ADMIN ghcr.io/defguard/gateway:latest`; + return `docker run -e DEFGUARD_TOKEN=${networkToken?.token} --restart unless-stopped --network host --cap-add NET_ADMIN ghcr.io/defguard/gateway:latest`; }, [networkToken]); const returnNetworkToken = useCallback(() => { @@ -78,15 +94,25 @@ export const NetworkGatewaySetup = () => { window.location.href = 'https://github.com/DefGuard/gateway/releases'; }; + const openAddGatewayModal = useAddGatewayModal((state) => state.open); + return (
+ + +
+

Gateways

+
+
+ {gateways?.map((gateway) => )} + +

{LL.gatewaySetup.header.main()}

- {/* {parse( - LL.gatewaySetup.messages.runCommand({ - setupGatewayDocs: externalLink.gitbook.setup.gateway, - }), - )} */} {LL.gatewaySetup.messages.runCommand({ setupGatewayDocs: externalLink.gitbook.setup.gateway, @@ -154,7 +180,8 @@ export const NetworkGatewaySetup = () => { {LL.gatewaySetup.messages.oneLineInstall()} - + {/* TODO: Reflect gateway status in the gateway list above */} + {/* */}
); }; diff --git a/web/src/pages/network/NetworkGateway/components/GatewayCard.tsx b/web/src/pages/network/NetworkGateway/components/GatewayCard.tsx new file mode 100644 index 000000000..d0569f9bf --- /dev/null +++ b/web/src/pages/network/NetworkGateway/components/GatewayCard.tsx @@ -0,0 +1,80 @@ +import './style.scss'; + +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { useI18nContext } from '../../../../i18n/i18n-react'; +import { EditButton } from '../../../../shared/defguard-ui/components/Layout/EditButton/EditButton'; +import { EditButtonOption } from '../../../../shared/defguard-ui/components/Layout/EditButton/EditButtonOption'; +import { EditButtonOptionStyleVariant } from '../../../../shared/defguard-ui/components/Layout/EditButton/types'; +import useApi from '../../../../shared/hooks/useApi'; +import { useToaster } from '../../../../shared/hooks/useToaster'; +import { MutationKeys } from '../../../../shared/mutations'; +import { QueryKeys } from '../../../../shared/queries'; +import { Gateway } from '../../../../shared/types'; +import { useEditGatewayModal } from '../modals/hooks/useEditGatewayModal'; + +interface Props { + gateway: Gateway; +} + +export const GatewayCard = ({ gateway }: Props) => { + const { + network: { + gateway: { deleteGateway }, + }, + } = useApi(); + const queryClient = useQueryClient(); + const toaster = useToaster(); + const { LL } = useI18nContext(); + + const { mutate } = useMutation([MutationKeys.DELETE_GATEWAY], deleteGateway, { + onSuccess: (_data, _variables) => { + queryClient.invalidateQueries([QueryKeys.FETCH_ALL_GATEWAYS]); + toaster.success('Gateway removed successfully'); + close(); + }, + onError: (err) => { + toaster.error(LL.messages.error()); + console.error(err); + }, + }); + + const setEditGatewayModal = useEditGatewayModal((state) => state.setState); + + return ( +
+
+
+

+ ID: {gateway.id} +

+
+
+

{gateway.url}

+
+
+
+ + { + setEditGatewayModal({ + gateway, + visible: true, + }); + }} + /> + { + mutate({ + gatewayId: gateway.id, + }); + }} + /> + +
+
+ ); +}; diff --git a/web/src/pages/network/NetworkGateway/components/style.scss b/web/src/pages/network/NetworkGateway/components/style.scss new file mode 100644 index 000000000..2eb42110d --- /dev/null +++ b/web/src/pages/network/NetworkGateway/components/style.scss @@ -0,0 +1,10 @@ +.gateway-card { + border-radius: 15px; + border: 1px solid var(--border-primary); + background-color: var(--surface-default-modal); + box-sizing: border-box; + padding: 15px; + display: flex; + align-items: center; + justify-content: space-between; +} diff --git a/web/src/pages/network/NetworkGateway/modals/AddGatewayModal.tsx b/web/src/pages/network/NetworkGateway/modals/AddGatewayModal.tsx new file mode 100644 index 000000000..ac66ef251 --- /dev/null +++ b/web/src/pages/network/NetworkGateway/modals/AddGatewayModal.tsx @@ -0,0 +1,144 @@ +import './style.scss'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useMemo } from 'react'; +import { SubmitErrorHandler, SubmitHandler, useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { shallow } from 'zustand/shallow'; + +import { useI18nContext } from '../../../../i18n/i18n-react'; +import { FormInput } from '../../../../shared/defguard-ui/components/Form/FormInput/FormInput'; +import { Button } from '../../../../shared/defguard-ui/components/Layout/Button/Button'; +import { + ButtonSize, + ButtonStyleVariant, +} from '../../../../shared/defguard-ui/components/Layout/Button/types'; +import { ModalWithTitle } from '../../../../shared/defguard-ui/components/Layout/modals/ModalWithTitle/ModalWithTitle'; +import useApi from '../../../../shared/hooks/useApi'; +import { useToaster } from '../../../../shared/hooks/useToaster'; +import { MutationKeys } from '../../../../shared/mutations'; +import { QueryKeys } from '../../../../shared/queries'; +import { trimObjectStrings } from '../../../../shared/utils/trimObjectStrings'; +import { useNetworkPageStore } from '../../hooks/useNetworkPageStore'; +import { useAddGatewayModal } from './hooks/useAddGatewayModal'; + +interface Inputs { + url: string; +} + +export const AddGatewayModal = () => { + const { LL } = useI18nContext(); + const { + network: { + gateway: { addGateway }, + }, + } = useApi(); + const [visible] = useAddGatewayModal((state) => [state.visible], shallow); + const [reset, close] = useAddGatewayModal( + (state) => [state.reset, state.close], + shallow, + ); + const selectedNetworkId = useNetworkPageStore((state) => state.selectedNetworkId); + + const zodSchema = useMemo( + () => + z.object({ + url: z.string().url(), + }), + [], + ); + + const { + control, + handleSubmit, + setValue, + getValues, + formState: { isValid }, + } = useForm({ + resolver: zodResolver(zodSchema), + mode: 'all', + defaultValues: { + url: '', + }, + }); + + const onInvalidSubmit: SubmitErrorHandler = (values) => { + const invalidFields = Object.keys(values) as (keyof Partial)[]; + const invalidFieldsValues = getValues(invalidFields); + invalidFields.forEach((key, index) => { + setValue(key, invalidFieldsValues[index], { + shouldTouch: true, + shouldValidate: true, + }); + }); + }; + + const queryClient = useQueryClient(); + const toaster = useToaster(); + + const { mutate, isLoading: addGatewayLoading } = useMutation( + [MutationKeys.ADD_GATEWAY], + addGateway, + { + onSuccess: (_data, _variables) => { + queryClient.invalidateQueries([QueryKeys.FETCH_ALL_GATEWAYS]); + toaster.success('Gateway added successfully'); + close(); + }, + onError: (err) => { + toaster.error(LL.messages.error()); + console.error(err); + }, + }, + ); + + const onValidSubmit: SubmitHandler = (values) => { + values = trimObjectStrings(values); + mutate({ + url: values.url, + networkId: selectedNetworkId, + }); + }; + + return ( + +
+ +
+
+ +
+ ); +}; diff --git a/web/src/pages/network/NetworkGateway/modals/EditGatewayModal.tsx b/web/src/pages/network/NetworkGateway/modals/EditGatewayModal.tsx new file mode 100644 index 000000000..f444c75b2 --- /dev/null +++ b/web/src/pages/network/NetworkGateway/modals/EditGatewayModal.tsx @@ -0,0 +1,151 @@ +import './style.scss'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useEffect, useMemo } from 'react'; +import { SubmitErrorHandler, SubmitHandler, useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { shallow } from 'zustand/shallow'; + +import { useI18nContext } from '../../../../i18n/i18n-react'; +import { FormInput } from '../../../../shared/defguard-ui/components/Form/FormInput/FormInput'; +import { Button } from '../../../../shared/defguard-ui/components/Layout/Button/Button'; +import { + ButtonSize, + ButtonStyleVariant, +} from '../../../../shared/defguard-ui/components/Layout/Button/types'; +import { ModalWithTitle } from '../../../../shared/defguard-ui/components/Layout/modals/ModalWithTitle/ModalWithTitle'; +import useApi from '../../../../shared/hooks/useApi'; +import { useToaster } from '../../../../shared/hooks/useToaster'; +import { MutationKeys } from '../../../../shared/mutations'; +import { QueryKeys } from '../../../../shared/queries'; +import { trimObjectStrings } from '../../../../shared/utils/trimObjectStrings'; +import { useEditGatewayModal } from './hooks/useEditGatewayModal'; + +interface Inputs { + url: string; +} + +export const EditGatewayModal = () => { + const { LL } = useI18nContext(); + const { + network: { + gateway: { editGateway }, + }, + } = useApi(); + const [gateway, visible] = useEditGatewayModal( + (state) => [state.gateway, state.visible], + shallow, + ); + + const [close] = useEditGatewayModal((state) => [state.close], shallow); + + const zodSchema = useMemo( + () => + z.object({ + url: z.string().url(), + }), + [], + ); + + const defaultValues = useMemo(() => { + return { + url: gateway?.url, + }; + }, [gateway]); + + const { + control, + handleSubmit, + setValue, + getValues, + reset, + formState: { isValid }, + } = useForm({ + resolver: zodResolver(zodSchema), + mode: 'all', + defaultValues: defaultValues, + }); + + useEffect(() => { + reset(defaultValues); + }, [reset, defaultValues]); + + const onInvalidSubmit: SubmitErrorHandler = (values) => { + const invalidFields = Object.keys(values) as (keyof Partial)[]; + const invalidFieldsValues = getValues(invalidFields); + invalidFields.forEach((key, index) => { + setValue(key, invalidFieldsValues[index], { + shouldTouch: true, + shouldValidate: true, + }); + }); + }; + + const queryClient = useQueryClient(); + const toaster = useToaster(); + + const { mutate, isLoading: addGatewayLoading } = useMutation( + [MutationKeys.ADD_GATEWAY], + editGateway, + { + onSuccess: (_data, _variables) => { + queryClient.invalidateQueries([QueryKeys.FETCH_ALL_GATEWAYS]); + toaster.success('Gateway changed successfully'); + close(); + }, + onError: (err) => { + toaster.error(LL.messages.error()); + console.error(err); + }, + }, + ); + + const onValidSubmit: SubmitHandler = (values) => { + if (!gateway) return; + values = trimObjectStrings(values); + mutate({ + url: values.url, + gatewayId: gateway.id, + }); + }; + + return ( + +
+ +
+
+ +
+ ); +}; diff --git a/web/src/pages/network/NetworkGateway/modals/hooks/useAddGatewayModal.tsx b/web/src/pages/network/NetworkGateway/modals/hooks/useAddGatewayModal.tsx new file mode 100644 index 000000000..62fa772bf --- /dev/null +++ b/web/src/pages/network/NetworkGateway/modals/hooks/useAddGatewayModal.tsx @@ -0,0 +1,31 @@ +import { createWithEqualityFn } from 'zustand/traditional'; + +const defaultValues: StoreValues = { + visible: false, + url: '', +}; + +export const useAddGatewayModal = createWithEqualityFn( + (set, _get) => ({ + ...defaultValues, + open: () => set({ ...defaultValues, visible: true }), + close: () => set({ visible: false }), + setState: (values) => set((old) => ({ ...old, ...values })), + reset: () => set(defaultValues), + }), + Object.is, +); + +type Store = StoreValues & StoreMethods; + +type StoreValues = { + visible: boolean; + url: string; +}; + +type StoreMethods = { + open: () => void; + close: () => void; + reset: () => void; + setState: (values: Partial) => void; +}; diff --git a/web/src/pages/network/NetworkGateway/modals/hooks/useEditGatewayModal.tsx b/web/src/pages/network/NetworkGateway/modals/hooks/useEditGatewayModal.tsx new file mode 100644 index 000000000..dc5033099 --- /dev/null +++ b/web/src/pages/network/NetworkGateway/modals/hooks/useEditGatewayModal.tsx @@ -0,0 +1,31 @@ +import { createWithEqualityFn } from 'zustand/traditional'; + +import { Gateway } from '../../../../../shared/types'; + +const defaultValues: StoreValues = { + visible: false, + gateway: undefined, +}; + +export const useEditGatewayModal = createWithEqualityFn( + (set) => ({ + ...defaultValues, + setState: (values) => set((old) => ({ ...old, ...values })), + open: (values) => set({ ...defaultValues, ...values }), + close: () => set({ visible: false }), + }), + Object.is, +); + +type StoreValues = { + visible: boolean; + gateway?: Gateway; +}; + +type StoreMethods = { + setState: (values: Partial) => void; + open: (values: Partial) => void; + close: () => void; +}; + +type Store = StoreValues & StoreMethods; diff --git a/web/src/pages/network/NetworkGateway/modals/style.scss b/web/src/pages/network/NetworkGateway/modals/style.scss new file mode 100644 index 000000000..3b9919800 --- /dev/null +++ b/web/src/pages/network/NetworkGateway/modals/style.scss @@ -0,0 +1,15 @@ +@use '@scssutils' as *; + +#add-user-modal { + overflow-x: hidden; + + &.step-0 { + @media (max-width: 635px) { + width: 100%; + } + + @media (min-width: 635px) { + width: auto; + } + } +} diff --git a/web/src/pages/network/NetworkGateway/style.scss b/web/src/pages/network/NetworkGateway/style.scss index 340a535c8..30131e462 100644 --- a/web/src/pages/network/NetworkGateway/style.scss +++ b/web/src/pages/network/NetworkGateway/style.scss @@ -4,6 +4,16 @@ flex-direction: column; row-gap: 20px; + & > section.gateway-list { + display: flex; + flex-direction: column; + row-gap: 20px; + + .add-component { + height: 80px; + } + } + & > section.header-section { h2, p { diff --git a/web/src/pages/settings/components/GlobalSettings/components/BrandingSettings/BrandingSettings.tsx b/web/src/pages/settings/components/GlobalSettings/components/BrandingSettings/BrandingSettings.tsx index 81e90852b..359732b1f 100644 --- a/web/src/pages/settings/components/GlobalSettings/components/BrandingSettings/BrandingSettings.tsx +++ b/web/src/pages/settings/components/GlobalSettings/components/BrandingSettings/BrandingSettings.tsx @@ -109,11 +109,11 @@ export const BrandingSettings = () => { main_logo_url: settings?.main_logo_url === defaultSettings.main_logo_url ? '' - : settings?.main_logo_url ?? '', + : (settings?.main_logo_url ?? ''), nav_logo_url: settings?.nav_logo_url === defaultSettings.nav_logo_url ? '' - : settings?.nav_logo_url ?? '', + : (settings?.nav_logo_url ?? ''), }; }, [settings?.instance_name, settings?.main_logo_url, settings?.nav_logo_url]); diff --git a/web/src/pwa/playstore.png b/web/src/pwa/playstore.png index 33b042ed1..570b08fb9 100644 Binary files a/web/src/pwa/playstore.png and b/web/src/pwa/playstore.png differ diff --git a/web/src/shared/components/network/GatewaysStatus/GatewaysStatus.tsx b/web/src/shared/components/network/GatewaysStatus/GatewaysStatus.tsx index a2a51e7fa..d11b93188 100644 --- a/web/src/shared/components/network/GatewaysStatus/GatewaysStatus.tsx +++ b/web/src/shared/components/network/GatewaysStatus/GatewaysStatus.tsx @@ -1,7 +1,7 @@ import './style.scss'; import { autoUpdate, offset, useFloating } from '@floating-ui/react'; -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import classNames from 'classnames'; import { AnimatePresence, motion, TargetAndTransition } from 'framer-motion'; import { isUndefined } from 'lodash-es'; @@ -32,10 +32,9 @@ const REFETCH_INTERVAL = 5 * 1000; export const GatewaysStatus = ({ networkId }: Props) => { const toaster = useToaster(); const { - network: { getGatewaysStatus, deleteGateway }, + network: { getGatewaysStatus }, } = useApi(); const { LL } = useI18nContext(); - const queryClient = useQueryClient(); const [floatingOpen, setFloatingOpen] = useState(false); const { x, y, strategy, refs } = useFloating({ placement: 'bottom', @@ -63,17 +62,6 @@ export const GatewaysStatus = ({ networkId }: Props) => { }, ); - const { mutate: deleteGatewayMutation } = useMutation({ - mutationFn: deleteGateway, - onSuccess: () => { - queryClient.invalidateQueries([QueryKeys.FETCH_NETWORK_GATEWAYS_STATUS]); - }, - onError: (err) => { - toaster.error(LL.components.gatewaysStatus.messages.deleteError()); - console.error(err); - }, - }); - const isLoading = (queryLoading && !data) || !data; const getStatus = useMemo(() => { @@ -188,18 +176,7 @@ export const GatewaysStatus = ({ networkId }: Props) => { duration: 0.2, }} > - {data?.map((g) => ( - - deleteGatewayMutation({ - networkId, - gatewayId: g.uid, - }) - } - /> - ))} + {data?.map((g) => )} )} @@ -210,10 +187,9 @@ export const GatewaysStatus = ({ networkId }: Props) => { type GatewayStatusRowProps = { status: GatewayStatus; - onDismiss: () => void; }; -const GatewayStatusRow = ({ status, onDismiss }: GatewayStatusRowProps) => { +const GatewayStatusRow = ({ status }: GatewayStatusRowProps) => { const [loading, setLoading] = useState(false); const cn = () => classNames('gateway-status-row', { @@ -234,7 +210,6 @@ const GatewayStatusRow = ({ status, onDismiss }: GatewayStatusRowProps) => { className="gateway-dismiss" onClick={() => { setLoading(true); - onDismiss(); }} disabled={loading} > diff --git a/web/src/shared/hooks/useApi.tsx b/web/src/shared/hooks/useApi.tsx index 84a961c41..f5c7ab5c8 100644 --- a/web/src/shared/hooks/useApi.tsx +++ b/web/src/shared/hooks/useApi.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo } from 'react'; import { useI18nContext } from '../../i18n/i18n-react'; import { + AddGatewayRequest, AddOpenidClientRequest, AddUserRequest, AddWalletRequest, @@ -381,9 +382,6 @@ const useApi = (props?: HookProps): ApiHook => { const getGatewaysStatus: ApiHook['network']['getGatewaysStatus'] = (networkId) => client.get(`/network/${networkId}/gateways`).then(unpackRequest); - const deleteGateway: ApiHook['network']['deleteGateway'] = (data) => - client.delete(`/network/${data.networkId}/gateways/${data.gatewayId}`); - const changePasswordSelf: ApiHook['changePasswordSelf'] = (data) => client.put('/user/change_password', data).then(unpackRequest); @@ -474,6 +472,22 @@ const useApi = (props?: HookProps): ApiHook => { return {}; }); + const getAllGateways: ApiHook['network']['gateway']['getAllGateways'] = (networkId) => + client + .get(`/network/${networkId}/all_gateways`) + .then(unpackRequest) + .then((data) => data?.gateways || []); + + const addGateway: ApiHook['network']['gateway']['addGateway'] = ( + data: AddGatewayRequest, + ) => client.post(`/network/${data.networkId}/gateway`, data).then(unpackRequest); + + const deleteGateway: ApiHook['network']['gateway']['deleteGateway'] = (data) => + client.delete(`/gateway/${data.gatewayId}`).then(unpackRequest); + + const editGateway: ApiHook['network']['gateway']['editGateway'] = (data) => + client.put(`/gateway/${data.gatewayId}`, data).then(unpackRequest); + useEffect(() => { client.interceptors.response.use( (res) => { @@ -560,7 +574,12 @@ const useApi = (props?: HookProps): ApiHook => { getNetworkToken, getNetworkStats, getGatewaysStatus, - deleteGateway, + gateway: { + getAllGateways, + addGateway, + deleteGateway, + editGateway, + }, }, auth: { login, diff --git a/web/src/shared/images/png/manual-config-1.png b/web/src/shared/images/png/manual-config-1.png index 634bf205d..edbfb492e 100644 Binary files a/web/src/shared/images/png/manual-config-1.png and b/web/src/shared/images/png/manual-config-1.png differ diff --git a/web/src/shared/mutations.ts b/web/src/shared/mutations.ts index da00e7d9c..2166d3cec 100644 --- a/web/src/shared/mutations.ts +++ b/web/src/shared/mutations.ts @@ -48,4 +48,6 @@ export const MutationKeys = { CHANGE_NETWORK: 'CHANGE_NETWORK', IMPORT_NETWORK: 'IMPORT_NETWORK', CREATE_USER_DEVICES: 'CREATE_USER_DEVICES', + ADD_GATEWAY: 'ADD_GATEWAY', + DELETE_GATEWAY: 'DELETE_GATEWAY', }; diff --git a/web/src/shared/queries.ts b/web/src/shared/queries.ts index 0d539d21a..41f5259e6 100644 --- a/web/src/shared/queries.ts +++ b/web/src/shared/queries.ts @@ -30,4 +30,5 @@ export const QueryKeys = { FETCH_OPENID_INFO: 'FETCH_OPENID_INFO', FETCH_ENTERPRISE_STATUS: 'FETCH_ENTERPRISE_STATUS', FETCH_ENTERPRISE_SETTINGS: 'FETCH_ENTERPRISE_SETTINGS', + FETCH_ALL_GATEWAYS: 'FETCH_ALL_GATEWAYS', }; diff --git a/web/src/shared/types.ts b/web/src/shared/types.ts index fd02238e0..0c8794902 100644 --- a/web/src/shared/types.ts +++ b/web/src/shared/types.ts @@ -117,6 +117,12 @@ export type GatewayStatus = { uid: string; }; +export type Gateway = { + id: number; + network_id: number; + url: string; +}; + export interface Network { id: number; name: string; @@ -377,6 +383,16 @@ export type DeleteGatewayRequest = { gatewayId: string; }; +export type AddGatewayRequest = { + networkId: number; + url: string; +}; + +export type EditGatewayRequest = { + gatewayId: number; + url: string; +}; + export type ChangePasswordSelfRequest = { old_password: string; new_password: string; @@ -505,7 +521,12 @@ export interface ApiHook { getNetworkToken: (networkId: Network['id']) => Promise; getNetworkStats: (data: GetNetworkStatsRequest) => Promise; getGatewaysStatus: (networkId: number) => Promise; - deleteGateway: (data: DeleteGatewayRequest) => Promise; + gateway: { + deleteGateway: (data: { gatewayId: number }) => Promise; + getAllGateways: (networkId: number) => Promise; + addGateway: (data: AddGatewayRequest) => Promise; + editGateway: (data: EditGatewayRequest) => Promise; + }; }; auth: { login: (data: LoginData) => Promise;