From 1b41849115aacd3b1adfbf5717432c9e5040ff4b Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Thu, 5 Oct 2023 09:07:53 -0400 Subject: [PATCH 1/4] Added ui --- .gitignore | 4 +- bot/.env.TEMPLATE | 1 - bot/docker-compose.yml | 1 + service/.env.TEMPLATE | 1 - service/.version | 2 +- service/Cargo.toml | 3 +- service/data/spells/cantrips.json | 216 +- service/docker-compose.yml | 3 +- service/src/db/spells/model.rs | 8 +- service/src/db/spells/routes.rs | 22 +- service/src/db/spells/types.rs | 8 +- service/src/main.rs | 7 + ui/.env.TEMPLATE | 5 + ui/.eslintrc.json | 17 + ui/.nvmrc | 1 + ui/.prettierrc.json | 8 + ui/Dockerfile | 39 + ui/Makefile | 26 + ui/docker-compose.yml | 26 + ui/next-env.d.ts | 5 + ui/next.config.js | 22 + ui/package-lock.json | 5425 +++++++++++++++++++++++++++ ui/package.json | 42 + ui/postcss.config.js | 7 + ui/public/favicon.ico | Bin 0 -> 25931 bytes ui/public/layers-2x.png | Bin 0 -> 1259 bytes ui/public/layers.png | Bin 0 -> 696 bytes ui/public/marker-icon-2x.png | Bin 0 -> 2586 bytes ui/public/marker-icon.png | Bin 0 -> 1466 bytes ui/public/marker-shadow.png | Bin 0 -> 618 bytes ui/public/vercel.svg | 4 + ui/src/api/index.ts | 25 + ui/src/api/spells.ts | 37 + ui/src/api/spells.types.ts | 82 + ui/src/app/backgrounds/page.tsx | 5 + ui/src/app/bot/page.tsx | 0 ui/src/app/classes/page.tsx | 5 + ui/src/app/feats/page.tsx | 5 + ui/src/app/items/page.tsx | 5 + ui/src/app/layout.tsx | 40 + ui/src/app/options/page.tsx | 5 + ui/src/app/page.tsx | 5 + ui/src/app/races/page.tsx | 5 + ui/src/app/recoil-root-wrapper.tsx | 8 + ui/src/app/spells/page.tsx | 91 + ui/src/app/spells/spells.css | 7 + ui/src/components/SpellModal.tsx | 153 + ui/src/components/Topbar/index.tsx | 57 + ui/src/components/Topbar/topbar.css | 47 + ui/src/js/spells.ts | 23 + ui/src/js/theme.ts | 5 + ui/src/js/utils.ts | 6 + ui/styles/globals.css | 38 + ui/tsconfig.json | 45 + 54 files changed, 6473 insertions(+), 129 deletions(-) create mode 100644 ui/.env.TEMPLATE create mode 100755 ui/.eslintrc.json create mode 100644 ui/.nvmrc create mode 100644 ui/.prettierrc.json create mode 100644 ui/Dockerfile create mode 100644 ui/Makefile create mode 100644 ui/docker-compose.yml create mode 100755 ui/next-env.d.ts create mode 100755 ui/next.config.js create mode 100644 ui/package-lock.json create mode 100644 ui/package.json create mode 100644 ui/postcss.config.js create mode 100755 ui/public/favicon.ico create mode 100644 ui/public/layers-2x.png create mode 100644 ui/public/layers.png create mode 100644 ui/public/marker-icon-2x.png create mode 100644 ui/public/marker-icon.png create mode 100644 ui/public/marker-shadow.png create mode 100755 ui/public/vercel.svg create mode 100644 ui/src/api/index.ts create mode 100644 ui/src/api/spells.ts create mode 100644 ui/src/api/spells.types.ts create mode 100644 ui/src/app/backgrounds/page.tsx create mode 100644 ui/src/app/bot/page.tsx create mode 100644 ui/src/app/classes/page.tsx create mode 100644 ui/src/app/feats/page.tsx create mode 100644 ui/src/app/items/page.tsx create mode 100644 ui/src/app/layout.tsx create mode 100644 ui/src/app/options/page.tsx create mode 100644 ui/src/app/page.tsx create mode 100644 ui/src/app/races/page.tsx create mode 100644 ui/src/app/recoil-root-wrapper.tsx create mode 100644 ui/src/app/spells/page.tsx create mode 100644 ui/src/app/spells/spells.css create mode 100644 ui/src/components/SpellModal.tsx create mode 100644 ui/src/components/Topbar/index.tsx create mode 100644 ui/src/components/Topbar/topbar.css create mode 100644 ui/src/js/spells.ts create mode 100644 ui/src/js/theme.ts create mode 100644 ui/src/js/utils.ts create mode 100755 ui/styles/globals.css create mode 100755 ui/tsconfig.json diff --git a/.gitignore b/.gitignore index 2a8cf44..cfab8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,5 @@ target/ .idea/ **/Cargo.lock -logs/ -app/ +.next/ +node_modules/ diff --git a/bot/.env.TEMPLATE b/bot/.env.TEMPLATE index dd583f4..07f5e95 100644 --- a/bot/.env.TEMPLATE +++ b/bot/.env.TEMPLATE @@ -1,5 +1,4 @@ RUST_LOG=warn,bot=info -COMPOSE_PROJECT_NAME=siren SERVICE_HOST=localhost SERVICE_PORT=5000 diff --git a/bot/docker-compose.yml b/bot/docker-compose.yml index 67cde8b..e35d8fb 100644 --- a/bot/docker-compose.yml +++ b/bot/docker-compose.yml @@ -1,5 +1,6 @@ version: '3.8' +name: siren services: bot: image: siren-bot:${BOT_VERSION:-latest} diff --git a/service/.env.TEMPLATE b/service/.env.TEMPLATE index 95ba80b..8799caa 100644 --- a/service/.env.TEMPLATE +++ b/service/.env.TEMPLATE @@ -1,5 +1,4 @@ RUST_LOG=warn,service=info -COMPOSE_PROJECT_NAME=siren DATABASE_USER=siren DATABASE_PASSWORD= diff --git a/service/.version b/service/.version index e9f3799..686ee6f 100644 --- a/service/.version +++ b/service/.version @@ -1 +1 @@ -SIREN_VERSION=0.2.4 \ No newline at end of file +SIREN_VERSION=0.2.5 \ No newline at end of file diff --git a/service/Cargo.toml b/service/Cargo.toml index 067c94b..a76b62d 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "service" -version = "0.2.4" +version = "0.2.5" edition = "2021" authors = ["Ben Sherriff "] repository = "https://github.com/bensherriff/siren" @@ -14,6 +14,7 @@ path = "src/lib.rs" [dependencies] actix-web = "4.4.0" actix-rt = "2.9.0" +actix-cors = "0.6.4" actix-web-httpauth = "0.8.1" chrono = { version = "0.4.31", features = ["serde"] } dotenv = "0.15.0" diff --git a/service/data/spells/cantrips.json b/service/data/spells/cantrips.json index b81c6e7..39325e6 100644 --- a/service/data/spells/cantrips.json +++ b/service/data/spells/cantrips.json @@ -5,12 +5,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "saving_throw": [ @@ -48,7 +48,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -67,7 +67,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -87,7 +87,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -95,7 +95,7 @@ }, "area": { "type": "sphere", - "amount": 5, + "value": 5, "unit": "feet" }, "damage_inflict": [ @@ -111,7 +111,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -133,12 +133,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 120, + "value": 120, "unit": "feet" }, "damage_inflict": [ @@ -153,7 +153,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -176,17 +176,17 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "area": { "type": "cube", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -200,7 +200,7 @@ }, { "type": "timed", - "amount": 1, + "value": 1, "unit": "hour" } ], @@ -231,17 +231,17 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "area": { "type": "cube", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -252,7 +252,7 @@ "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -275,12 +275,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 120, + "value": 120, "unit": "feet" }, "components": { @@ -292,7 +292,7 @@ "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -303,7 +303,7 @@ ], "description": { "entries": [ - "You create up to four torch-amountd lights within range, making them appear as torches, lanterns, or glowing orbs that hover in the air for the duration. You can also combine the four lights into one glowing vaguely humanoid form of Medium amount. Whichever form you choose, each light sheds dim light in a 10-foot radius.", + "You create up to four torch-valued lights within range, making them appear as torches, lanterns, or glowing orbs that hover in the air for the duration. You can also combine the four lights into one glowing vaguely humanoid form of Medium value. Whichever form you choose, each light sheds dim light in a 10-foot radius.", "As a bonus action on your turn, you can move the lights up to 60 feet to a new spot within range. A light must be within 20 feet of another light created by this spell, and a light winks out if it exceeds the spell's range." ] } @@ -314,12 +314,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -358,12 +358,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 120, + "value": 120, "unit": "feet" }, "damage_inflict": [ @@ -398,7 +398,7 @@ "level": 0, "ritual": true, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -412,7 +412,7 @@ "durations": [ { "type": "timed", - "amount": 8, + "value": 8, "unit": "hours" } ], @@ -434,12 +434,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 120, + "value": 120, "unit": "feet" }, "damage_inflict": [ @@ -474,7 +474,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -484,12 +484,12 @@ "verbal": false, "somatic": true, "material": true, - "materials_needed": "a small amount of makeup applied to the face as this spell is cast" + "materials_needed": "a small value of makeup applied to the face as this spell is cast" }, "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -510,12 +510,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "saving_throw": [ @@ -552,7 +552,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -560,7 +560,7 @@ }, "area": { "type": "sphere", - "amount": 5, + "value": 5, "unit": "feet" }, "damage_inflict": [ @@ -596,7 +596,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -610,7 +610,7 @@ "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -631,12 +631,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -674,12 +674,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "saving_throw": [ @@ -716,7 +716,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -724,7 +724,7 @@ }, "area": { "type": "sphere", - "amount": 20, + "value": 20, "unit": "feet" }, "saving_throw": [ @@ -739,7 +739,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "hour" } ], @@ -761,12 +761,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "self", - "amount": 15, + "value": 15, "unit": "feet" }, "saving_throw": [ @@ -803,12 +803,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -819,7 +819,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -842,7 +842,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "bonus" }, "range": { @@ -860,7 +860,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -881,7 +881,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "minutes" }, "range": { @@ -916,12 +916,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 120, + "value": 120, "unit": "feet" }, "components": { @@ -933,7 +933,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -955,12 +955,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "saving_throw": [ @@ -996,12 +996,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -1013,7 +1013,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -1037,17 +1037,17 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "area": { "type": "cube", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -1061,7 +1061,7 @@ }, { "type": "timed", - "amount": 1, + "value": 1, "unit": "hour" } ], @@ -1090,12 +1090,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 10, + "value": 10, "unit": "feet" }, "saving_throw": [ @@ -1134,11 +1134,11 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "range": { "type": "point", - "amount": 10, + "value": 10, "unit": "feet" }, "components": { @@ -1149,7 +1149,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "hour" } ], @@ -1183,7 +1183,7 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "range": { "type": "self" @@ -1220,7 +1220,7 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "range": { "type": "self" @@ -1237,7 +1237,7 @@ "durations": [ { "type": "timed", - "amount": 10, + "value": 10, "unit": "minutes" } ], @@ -1261,11 +1261,11 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "damage_inflict": [ @@ -1301,7 +1301,7 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "range": { "type": "touch" @@ -1315,7 +1315,7 @@ "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -1336,12 +1336,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "saving_throw": [ @@ -1378,7 +1378,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1389,7 +1389,7 @@ ], "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -1419,17 +1419,17 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "area": { "type": "cube", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -1443,7 +1443,7 @@ }, { "type": "timed", - "amount": 1, + "value": 1, "unit": "hour" } ], @@ -1473,7 +1473,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "bonus" }, "range": { @@ -1492,7 +1492,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -1513,7 +1513,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1551,7 +1551,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { @@ -1584,7 +1584,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1595,7 +1595,7 @@ ], "range": { "type": "self", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -1625,12 +1625,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -1641,7 +1641,7 @@ "durations": [ { "type": "timed", - "amount": 1, + "value": 1, "unit": "minutes" } ], @@ -1674,7 +1674,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1683,7 +1683,7 @@ "attack_type": "melee", "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -1715,7 +1715,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1726,7 +1726,7 @@ ], "range": { "type": "point", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { @@ -1756,7 +1756,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1767,7 +1767,7 @@ ], "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "components": { @@ -1797,12 +1797,12 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "range": { "type": "point", - "amount": 30, + "value": 30, "unit": "feet" }, "components": { @@ -1813,7 +1813,7 @@ "durations": [ { "type": "concentration", - "amount": 1, + "value": 1, "unit": "round" } ], @@ -1834,7 +1834,7 @@ "level": 0, "ritual": false, "casting_time": { - "amount": 1, + "value": 1, "unit": "action" }, "damage_inflict": [ @@ -1845,7 +1845,7 @@ ], "range": { "type": "point", - "amount": 60, + "value": 60, "unit": "feet" }, "components": { @@ -1877,7 +1877,7 @@ "ritual": false, "casting_time": { "unit": "action", - "amount": 1 + "value": 1 }, "damage_inflict": [ "radiant" @@ -1887,7 +1887,7 @@ ], "range": { "type": "point", - "amount": 5, + "value": 5, "unit": "feet" }, "components": { diff --git a/service/docker-compose.yml b/service/docker-compose.yml index 6dde2aa..984c3c5 100644 --- a/service/docker-compose.yml +++ b/service/docker-compose.yml @@ -1,5 +1,6 @@ version: '3.8' +name: siren services: service: image: siren-service:${SIREN_VERSION:-latest} @@ -14,7 +15,7 @@ services: environment: DATABASE_HOST: db DATABASE_PORT: 5432 - SERVICE_HOST: siren + SERVICE_HOST: service SERVICE_PORT: 5000 ports: - ${SERVICE_PORT:-5000}:5000 diff --git a/service/src/db/spells/model.rs b/service/src/db/spells/model.rs index 1616134..f1317ff 100644 --- a/service/src/db/spells/model.rs +++ b/service/src/db/spells/model.rs @@ -6,7 +6,7 @@ use crate::db::{schema::spells::{self}, classes::AbilityType, conditions::Condit use super::{SchoolType, CastingTime, CastingType, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description, DurationType}; -#[derive(Queryable, QueryableByName)] +#[derive(Queryable, QueryableByName, Serialize, Deserialize)] #[diesel(table_name = spells)] pub struct QuerySpell { pub id: i32, @@ -191,6 +191,7 @@ impl InsertSpell { #[derive(Debug, Serialize, Deserialize)] pub struct Spell { + pub id: Option, pub name: String, pub school: SchoolType, pub level: i32, @@ -226,17 +227,18 @@ impl From for Spell { Err(err) => { log::error!("Failed to parse spell: {}", err); Self { + id: None, name: "".to_string(), school: SchoolType::Abjuration, level: 0, ritual: false, - casting_time: CastingTime { amount: 0, casting_type: CastingType::Action }, + casting_time: CastingTime { value: 0, casting_type: CastingType::Action }, saving_throw: None, attack_type: None, damage_inflict: None, damage_resist: None, conditions: None, - range: Range { range_type: "".to_string(), amount: None, unit: None }, + range: Range { range_type: "".to_string(), value: None, unit: None }, area: None, components: Components { verbal: false, somatic: false, material: false, materials_needed: None, materials_cost: None, materials_consumed: None }, durations: vec![], diff --git a/service/src/db/spells/routes.rs b/service/src/db/spells/routes.rs index 25ebf11..5d985f8 100644 --- a/service/src/db/spells/routes.rs +++ b/service/src/db/spells/routes.rs @@ -73,7 +73,7 @@ async fn get_all(req: HttpRequest) -> HttpResponse { None => None }; // Limit must be between 1 and 100 - let limit = std::cmp::min(std::cmp::max(params.limit.unwrap_or(20), 1), 100); + let limit = std::cmp::min(std::cmp::max(params.limit.unwrap_or(100), 1), 100); let total_count = QuerySpell::get_count(&filters).unwrap(); let max_page = std::cmp::max((total_count as f64 / limit as f64).ceil() as i32, 1); // Page must be between 1 and max_page @@ -82,8 +82,11 @@ async fn get_all(req: HttpRequest) -> HttpResponse { match web::block(move || QuerySpell::get_all(&filters, limit, page)).await.unwrap() { Ok(spells) => { let mut response: Vec = Vec::new(); - for spell in spells { - response.push(Spell::from(spell)); + for query_spell in spells { + let id = query_spell.id; + let mut spell = Spell::from(query_spell); + spell.id = Some(id); + response.push(spell); } HttpResponse::Ok().json(GetResponse { data: response, @@ -112,10 +115,15 @@ async fn get_by_id(id: web::Path) -> HttpResponse { }) }; match web::block(move || QuerySpell::get_by_id(id)).await.unwrap() { - Ok(spell) => HttpResponse::Ok().json(GetResponse { - data: Spell::from(spell), - metadata: None - }), + Ok(query_spell) => { + let id = query_spell.id; + let mut spell = Spell::from(query_spell); + spell.id = Some(id); + HttpResponse::Ok().json(GetResponse { + data: spell, + metadata: None + }) + }, Err(err) => { error!("{:?}", err.message); ResponseError::error_response(&err) diff --git a/service/src/db/spells/types.rs b/service/src/db/spells/types.rs index 6e8f943..f82c4c3 100644 --- a/service/src/db/spells/types.rs +++ b/service/src/db/spells/types.rs @@ -56,7 +56,7 @@ impl FromStr for SchoolType { #[derive(Debug, Serialize, Deserialize)] pub struct CastingTime { - pub amount: i32, + pub value: i32, #[serde(rename = "unit")] pub casting_type: CastingType } @@ -209,7 +209,7 @@ pub struct Range { #[serde(rename = "type")] pub range_type: String, #[serde(skip_serializing_if = "Option::is_none")] - pub amount: Option, + pub value: Option, #[serde(skip_serializing_if = "Option::is_none")] pub unit: Option } @@ -219,7 +219,7 @@ pub struct Area { #[serde(rename = "type")] pub area_type: AreaType, #[serde(skip_serializing_if = "Option::is_none")] - pub amount: Option, + pub value: Option, #[serde(skip_serializing_if = "Option::is_none")] pub unit: Option } @@ -270,7 +270,7 @@ pub struct Duration { #[serde(rename = "type")] pub duration_type: DurationType, #[serde(skip_serializing_if = "Option::is_none")] - pub amount: Option, + pub value: Option, #[serde(skip_serializing_if = "Option::is_none")] pub unit: Option } diff --git a/service/src/main.rs b/service/src/main.rs index 2077335..bae3589 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -4,6 +4,7 @@ extern crate diesel_migrations; use std::env; +use actix_cors::Cors; use actix_web::{HttpServer, App}; use dotenv::dotenv; @@ -22,9 +23,15 @@ async fn main() -> std::io::Result<()> { let port = env::var("SERVICE_PORT").unwrap_or("5000".to_string()); match HttpServer::new(|| { + let cors = Cors::default() + .allow_any_origin() + .allow_any_method() + .allow_any_header() + .max_age(3600); App::new() .configure(db::messages::init_routes) .configure(db::spells::init_routes) + .wrap(cors) }) .bind(format!("{}:{}", host, port)) { Ok(b) => { diff --git a/ui/.env.TEMPLATE b/ui/.env.TEMPLATE new file mode 100644 index 0000000..b339118 --- /dev/null +++ b/ui/.env.TEMPLATE @@ -0,0 +1,5 @@ +SERVICE_HOST=service +SERVICE_PORT=5000 + +UI_PORT=8080 +NODE_ENV=development \ No newline at end of file diff --git a/ui/.eslintrc.json b/ui/.eslintrc.json new file mode 100755 index 0000000..88dd4f0 --- /dev/null +++ b/ui/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint/eslint-plugin" + ], + "extends": [ + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "rules": { + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-explicit-any": "off" + } +} \ No newline at end of file diff --git a/ui/.nvmrc b/ui/.nvmrc new file mode 100644 index 0000000..7ec5619 --- /dev/null +++ b/ui/.nvmrc @@ -0,0 +1 @@ +18.17.1 \ No newline at end of file diff --git a/ui/.prettierrc.json b/ui/.prettierrc.json new file mode 100644 index 0000000..2396656 --- /dev/null +++ b/ui/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "trailingComma": "none", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "jsxSingleQuote": true, + "printWidth": 120 +} \ No newline at end of file diff --git a/ui/Dockerfile b/ui/Dockerfile new file mode 100644 index 0000000..cd71033 --- /dev/null +++ b/ui/Dockerfile @@ -0,0 +1,39 @@ +# Base +FROM node:18-alpine AS base + +# Dependencies +FROM base as deps +RUN apk add --no-cache libc6-compat +WORKDIR /app +COPY package.json package-lock.json ./ +RUN npm ci + +# Dev +FROM base AS dev +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Builder +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +# Runner +FROM base AS runner +WORKDIR /app +RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs +COPY --from=builder /app/next.config.js ./ +COPY --from=builder /app/public ./public +COPY --from=builder /app/package.json ./package.json +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs +EXPOSE 3000 +ENV PORT 3000 +ENV NEXT_TELEMETRY_DISABLED 1 + +CMD ["node", "server.js"] diff --git a/ui/Makefile b/ui/Makefile new file mode 100644 index 0000000..b1844a7 --- /dev/null +++ b/ui/Makefile @@ -0,0 +1,26 @@ +#!make + +SHELL := /bin/bash + +.PHONY: help build start stop lint + +help: ## This info + @echo + @cat Makefile | grep -E '^[a-zA-Z\/_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + @echo + +build: ## Install the dependencies and build + docker compose build + +up: ## Start the dev instance + docker compose up -d + +down: ## Stop the dev instance + docker compose down + +lint: ## Run the linter + npm run lint + +clean: ## Remove node modules + docker compose down && \ + docker image rm siren-ui \ No newline at end of file diff --git a/ui/docker-compose.yml b/ui/docker-compose.yml new file mode 100644 index 0000000..7e5f30e --- /dev/null +++ b/ui/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3' + +name: siren +services: + ui: + container_name: siren-ui + env_file: + - .env + environment: + - NODE_ENV=${NODE_ENV:-development} + ports: + - ${UI_PORT:-8080}:3000 + build: + context: ./ + target: dev + command: "npm run dev" + volumes: + - ./src:/app/src + - ./public:/app/public + - ./styles:/app/styles + networks: + - siren-frontend + restart: unless-stopped + +networks: + siren-frontend: {} diff --git a/ui/next-env.d.ts b/ui/next-env.d.ts new file mode 100755 index 0000000..4f11a03 --- /dev/null +++ b/ui/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/ui/next.config.js b/ui/next.config.js new file mode 100755 index 0000000..42643a9 --- /dev/null +++ b/ui/next.config.js @@ -0,0 +1,22 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + swcMinify: true, + eslint: { + ignoreDuringBuilds: true + }, + webpackDevMiddleware: (config) => { + config.watchOptions = { + poll: 1000, + aggregateTimeout: 300 + }; + return config; + }, + publicRuntimeConfig: { + // remove private variables from processEnv + processEnv: Object.fromEntries(Object.entries(process.env).filter(([key]) => key.includes('NEXT_PUBLIC_'))) + }, + output: 'standalone' +}; + +module.exports = nextConfig; diff --git a/ui/package-lock.json b/ui/package-lock.json new file mode 100644 index 0000000..2d20efe --- /dev/null +++ b/ui/package-lock.json @@ -0,0 +1,5425 @@ +{ + "name": "siren-ui", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "siren-ui", + "version": "0.1.0", + "dependencies": { + "@mantine/core": "^7.1.2", + "@mantine/hooks": "^7.1.2", + "@mantine/modals": "^7.1.2", + "@mantine/notifications": "^7.1.2", + "axios": "^1.5.1", + "next": "^13.5.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^4.11.0", + "react-leaflet": "^4.2.1", + "recharts": "^2.8.0", + "recoil": "^0.7.7" + }, + "devDependencies": { + "@types/node": "20.8.2", + "@types/react": "18.2.24", + "@types/react-dom": "18.2.8", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "autoprefixer": "^10.4.16", + "eslint": "8.50.0", + "eslint-config-next": "13.5.4", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "postcss": "^8.4.31", + "postcss-import": "^15.1.0", + "postcss-preset-mantine": "^1.8.0", + "prettier": "^3.0.3", + "typescript": "5.2.2" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", + "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", + "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz", + "integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==", + "dependencies": { + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz", + "integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==", + "dependencies": { + "@floating-ui/core": "^1.4.2", + "@floating-ui/utils": "^0.1.3" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.24.8.tgz", + "integrity": "sha512-AuYeDoaR8jtUlUXtZ1IJ/6jtBkGnSpJXbGNzokBL87VDJ8opMq1Bgrc0szhK482ReQY6KZsMoZCVSb4xwalkBA==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.1", + "aria-hidden": "^1.2.3", + "tabbable": "^6.0.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.2.tgz", + "integrity": "sha512-5qhlDvjaLmAst/rKb3VdlCinwTF4EYMiVxuuc/HVUjs46W0zgtbMmAZ1UTsDrRTxRmUEzl92mOtWbeeXL26lSQ==", + "dependencies": { + "@floating-ui/dom": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.4.tgz", + "integrity": "sha512-qprfWkn82Iw821mcKofJ5Pk9wgioHicxcQMxx+5zt5GSKoqdWvgG5AxVmpmUUjzTLPVSH5auBrhI93Deayn/DA==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@mantine/core": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-7.1.2.tgz", + "integrity": "sha512-EZg82V/+uA2bM981mEUOUGfqKIRsMfvxLdAPQpurhtqsnq4yBj1xjC3KzX/Eas9QhhHuR+4DJJyGTuO9aOK6nQ==", + "dependencies": { + "@floating-ui/react": "^0.24.8", + "clsx": "2.0.0", + "react-number-format": "^5.2.2", + "react-remove-scroll": "^2.5.6", + "react-textarea-autosize": "8.5.3", + "type-fest": "^3.13.1" + }, + "peerDependencies": { + "@mantine/hooks": "7.1.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@mantine/core/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mantine/hooks": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-7.1.2.tgz", + "integrity": "sha512-2sqfBKse/aJq93zEpIn4OY+jRACmDIWBixfBgobRfltDyeL8G+3223LSAaeT6ZD8+h2YBJVmbCD5QY7bx2l11Q==", + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@mantine/modals": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@mantine/modals/-/modals-7.1.2.tgz", + "integrity": "sha512-5OOSUzWpnYwnmLILfA8TAmnXogWpzu4Z8v0V+NiiQb2lFADZTl7qnBmw4BbAoT9mwWo3sXlCvepj5bGjsl7pMg==", + "peerDependencies": { + "@mantine/core": "7.1.2", + "@mantine/hooks": "7.1.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@mantine/notifications": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-7.1.2.tgz", + "integrity": "sha512-aakf3KRGOnfh+qxGGH/B0ifS5myFi3xO2S0AKD6t//sbQrrUW+SUKh0qyuatnKIx7dxf+DA/sMobyqLUgyzAmg==", + "dependencies": { + "@mantine/store": "7.1.2", + "react-transition-group": "4.4.5" + }, + "peerDependencies": { + "@mantine/core": "7.1.2", + "@mantine/hooks": "7.1.2", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/@mantine/notifications/node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/@mantine/notifications/node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/@mantine/store": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@mantine/store/-/store-7.1.2.tgz", + "integrity": "sha512-Lf3FLymM0q92BuRC4tZxTxrb9EjVa+J8fqEV147u/Q3aUSNmkhJCqN2MXPbTHIBJ2PsbLtDhy/2edNyIK1KhKQ==", + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/@next/env": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.4.tgz", + "integrity": "sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.4.tgz", + "integrity": "sha512-vI94U+D7RNgX6XypSyjeFrOzxGlZyxOplU0dVE5norIfZGn/LDjJYPHdvdsR5vN1eRtl6PDAsOHmycFEOljK5A==", + "dev": true, + "dependencies": { + "glob": "7.1.7" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.4.tgz", + "integrity": "sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.4.tgz", + "integrity": "sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.4.tgz", + "integrity": "sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.4.tgz", + "integrity": "sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.4.tgz", + "integrity": "sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.4.tgz", + "integrity": "sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.4.tgz", + "integrity": "sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.4.tgz", + "integrity": "sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.4.tgz", + "integrity": "sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.3.tgz", + "integrity": "sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==", + "dev": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz", + "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/d3-array": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.8.tgz", + "integrity": "sha512-2xAVyAUgaXHX9fubjcCbGAUOqYfRJN1em1EKR2HfzWBpObZhwfnZKvofTN4TplMqJdFQao61I+NVSai/vnBvDQ==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.1.tgz", + "integrity": "sha512-CSAVrHAtM9wfuLJ2tpvvwCU/F22sm7rMHNN+yh9D6O6hyAms3+O0cgMpC1pm6UEUMOntuZC8bMt74PteiDUdCg==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", + "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.2.tgz", + "integrity": "sha512-zAbCj9lTqW9J9PlF4FwnvEjXZUy75NQqPm7DMHZXuxCFTpuTrdK2NMYGQekf4hlasL78fCYOLu4EE3/tXElwow==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", + "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.5.tgz", + "integrity": "sha512-w/C++3W394MHzcLKO2kdsIn5KKNTOqeQVzyPSGPLzQbkPw/jpeaGtSRlakcKevGgGsjJxGsbqS0fPrVFDbHrDA==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.3.tgz", + "integrity": "sha512-cHMdIq+rhF5IVwAV7t61pcEXfEHsEsrbBUPkFGBwTXuxtTAkBBrnrNA8++6OWm3jwVsXoZYQM8NEekg6CPJ3zw==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.1.tgz", + "integrity": "sha512-5j/AnefKAhCw4HpITmLDTPlf4vhi8o/dES+zbegfPb7LaGfNyqkLxBR6E+4yvTAgnJLmhe80EXFMzUs38fw4oA==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", + "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz", + "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.2.24", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.24.tgz", + "integrity": "sha512-Ee0Jt4sbJxMu1iDcetZEIKQr99J1Zfb6D4F3qfUWoR1JpInkY1Wdg4WwCyBjL257D0+jGqSl1twBjV8iCaC0Aw==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.8", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.8.tgz", + "integrity": "sha512-bAIvO5lN/U8sPGvs1Xm61rlRHHaq5rp5N3kp9C+NJ/Q41P8iqjkXSu0+/qu8POsjH9pNWb0OYabFez7taP7omw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "devOptional": true + }, + "node_modules/@types/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.4.tgz", + "integrity": "sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.4", + "@typescript-eslint/type-utils": "6.7.4", + "@typescript-eslint/utils": "6.7.4", + "@typescript-eslint/visitor-keys": "6.7.4", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.4.tgz", + "integrity": "sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.4", + "@typescript-eslint/types": "6.7.4", + "@typescript-eslint/typescript-estree": "6.7.4", + "@typescript-eslint/visitor-keys": "6.7.4", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.4.tgz", + "integrity": "sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.4", + "@typescript-eslint/visitor-keys": "6.7.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.4.tgz", + "integrity": "sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.7.4", + "@typescript-eslint/utils": "6.7.4", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.4.tgz", + "integrity": "sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.4.tgz", + "integrity": "sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.4", + "@typescript-eslint/visitor-keys": "6.7.4", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.4.tgz", + "integrity": "sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.4", + "@typescript-eslint/types": "6.7.4", + "@typescript-eslint/typescript-estree": "6.7.4", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.4.tgz", + "integrity": "sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.4", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { + "version": "10.4.16", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.16.tgz", + "integrity": "sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.21.10", + "caniuse-lite": "^1.0.30001538", + "fraction.js": "^4.3.6", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.0.tgz", + "integrity": "sha512-ZtlVZobOeDQhb/y2lMK6mznDw7TJHDNcKx5/bbBkFvArIQ5CVFhSI6hWWQnMx9I8cNmNmZ30wpDyOC2E2nvgbQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.1.tgz", + "integrity": "sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001543", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz", + "integrity": "sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.512", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.512.tgz", + "integrity": "sha512-1W8wRbYlQE4ph7eoj3TJ+uqwO6+xvAE/L+KGU7WTQQvX3tnSIGZAb90MTsMoJqzntamiwJhBAj4WZmygXhsOUg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "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", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz", + "integrity": "sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", + "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.50.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.5.4.tgz", + "integrity": "sha512-FzQGIj4UEszRX7fcRSJK6L1LrDiVZvDFW320VVntVKh3BSU8Fb9kpaoxQx0cdFgf3MQXdeSbrCXJ/5Z/NndDkQ==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "13.5.4", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.0.tgz", + "integrity": "sha512-QTHR9ddNnn35RTxlaEnx2gCxqFlF2SEN0SE2d17SqwyM7YOSI2GHWRYp5BiRkObTUNYPupC/3Fq2a0PpT+EKpg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", + "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "dependencies": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", + "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.0.tgz", + "integrity": "sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/hamt_plus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", + "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.1.tgz", + "integrity": "sha512-9E+nePc8C9cnQldmNl6bgpTY6zI4OPRZd97fhJ/iVZ1GifIUDVV5F6x1nEDqpe8KaMEZGT4xgrwKQDxXnjOIZQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.3" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dev": true, + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "peer": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "13.5.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.5.4.tgz", + "integrity": "sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==", + "dependencies": { + "@next/env": "13.5.4", + "@swc/helpers": "0.5.2", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001406", + "postcss": "8.4.31", + "styled-jsx": "5.1.1", + "watchpack": "2.4.0" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=16.14.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "13.5.4", + "@next/swc-darwin-x64": "13.5.4", + "@next/swc-linux-arm64-gnu": "13.5.4", + "@next/swc-linux-arm64-musl": "13.5.4", + "@next/swc-linux-x64-gnu": "13.5.4", + "@next/swc-linux-x64-musl": "13.5.4", + "@next/swc-win32-arm64-msvc": "13.5.4", + "@next/swc-win32-ia32-msvc": "13.5.4", + "@next/swc-win32-x64-msvc": "13.5.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/object.hasown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-mixins": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-9.0.4.tgz", + "integrity": "sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "postcss-js": "^4.0.0", + "postcss-simple-vars": "^7.0.0", + "sugarss": "^4.0.1" + }, + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-preset-mantine": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/postcss-preset-mantine/-/postcss-preset-mantine-1.8.0.tgz", + "integrity": "sha512-aLc+EoDXsvnXM2lWWF1MI+lgGqbd5xatVJ3KyTmsheNoXBYN0OFAkRFqyy3tfdveH64Fno2SLNEr4w/njPSInw==", + "dev": true, + "dependencies": { + "postcss-mixins": "^9.0.4", + "postcss-nested": "^6.0.1" + }, + "peerDependencies": { + "postcss": ">=8.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-simple-vars": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", + "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", + "dev": true, + "engines": { + "node": ">=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.1" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-icons": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.11.0.tgz", + "integrity": "sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "dependencies": { + "@react-leaflet/core": "^2.1.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-number-format": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.3.1.tgz", + "integrity": "sha512-qpYcQLauIeEhCZUZY9jXZnnroOtdy3jYaS1zQ3M1Sr6r/KMOBEIGNIb7eKT19g2N1wbYgFgvDzs19hw5TrB8XQ==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.6.tgz", + "integrity": "sha512-bO856ad1uDYLefgArk559IzUNeQ6SWH4QnrevIUjH+GczV56giDfl3h0Idptf2oIKxQmd1p9BN25jleKodTALg==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.4", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", + "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-resize-detector": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-8.1.0.tgz", + "integrity": "sha512-S7szxlaIuiy5UqLhLL1KY3aoyGHbZzsTpYal9eYMwCyKqoqoVLCmIgAgNyIM1FhnP2KyBygASJxdhejrzjMb+w==", + "dependencies": { + "lodash": "^4.17.21" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-smooth": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-2.0.4.tgz", + "integrity": "sha512-OkFsrrMBTvQUwEJthE1KXSOj79z57yvEWeFefeXPib+RmQEI9B1Ub1PgzlzzUyBOvl/TjXt5nF2hmD4NsgAh8A==", + "dependencies": { + "fast-equals": "^5.0.0", + "react-transition-group": "2.9.0" + }, + "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" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz", + "integrity": "sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ==", + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "dependencies": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0", + "react-dom": ">=15.0.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/recharts": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.8.0.tgz", + "integrity": "sha512-nciXqQDh3aW8abhwUlA4EBOBusRHLNiKHfpRZiG/yjups1x+auHb2zWPuEcTn/IMiN47vVMMuF8Sr+vcQJtsmw==", + "dependencies": { + "classnames": "^2.2.5", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.19", + "react-is": "^16.10.2", + "react-resize-detector": "^8.0.4", + "react-smooth": "^2.0.2", + "recharts-scale": "^0.4.4", + "reduce-css-calc": "^2.1.8", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=12" + }, + "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" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recoil": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.7.7.tgz", + "integrity": "sha512-8Og5KPQW9LwC577Vc7Ug2P0vQshkv1y3zG3tSSkWMqkWSwHmE+by06L8JtnGocjW6gcCvfwB3YtrJG6/tWivNQ==", + "dependencies": { + "hamt_plus": "1.0.2" + }, + "peerDependencies": { + "react": ">=16.13.1" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/reduce-css-calc": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz", + "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==", + "dependencies": { + "css-unit-converter": "^1.1.1", + "postcss-value-parser": "^3.3.0" + } + }, + "node_modules/reduce-css-calc/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/run-applescript/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-applescript/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.9.tgz", + "integrity": "sha512-6i5hL3MqG/K2G43mWXWgP+qizFW/QH/7kCNN13JrJS5q48FN5IKksLDscexKP3dnmB6cdm9jlNgAsWNLpSykmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sugarss": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", + "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", + "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/victory-vendor": { + "version": "36.6.11", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.6.11.tgz", + "integrity": "sha512-nT8kCiJp8dQh8g991J/R5w5eE2KnO8EAIP0xocWlh9l2okngMWglOPoMZzJvek8Q1KUc4XE/mJxTZnvOB1sTYg==", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "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.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/ui/package.json b/ui/package.json new file mode 100644 index 0000000..7be067a --- /dev/null +++ b/ui/package.json @@ -0,0 +1,42 @@ +{ + "name": "siren-ui", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@mantine/core": "^7.1.2", + "@mantine/hooks": "^7.1.2", + "@mantine/modals": "^7.1.2", + "@mantine/notifications": "^7.1.2", + "axios": "^1.5.1", + "next": "^13.5.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^4.11.0", + "react-leaflet": "^4.2.1", + "recharts": "^2.8.0", + "recoil": "^0.7.7" + }, + "devDependencies": { + "@types/node": "20.8.2", + "@types/react": "18.2.24", + "@types/react-dom": "18.2.8", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "autoprefixer": "^10.4.16", + "eslint": "8.50.0", + "eslint-config-next": "13.5.4", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "postcss": "^8.4.31", + "postcss-import": "^15.1.0", + "postcss-preset-mantine": "^1.8.0", + "prettier": "^3.0.3", + "typescript": "5.2.2" + } +} diff --git a/ui/postcss.config.js b/ui/postcss.config.js new file mode 100644 index 0000000..7a4f139 --- /dev/null +++ b/ui/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + 'postcss-preset-mantine': {}, + 'postcss-import': {}, + autoprefixer: {} + } +}; diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/ui/public/layers-2x.png b/ui/public/layers-2x.png new file mode 100644 index 0000000000000000000000000000000000000000..200c333dca9652ac4cba004d609e5af4eee168c1 GIT binary patch literal 1259 zcmVFhCYNy;#0irRPomHqW|G1C*;4?@4#E?jH>?v@U%cy?3dQAc-DchXVErpOh~ z-jbon+tNbnl6hoEb;)TVk+%hTDDi_G%i3*RZ&15!$Fjr^f;Ke&A@|?=`2&+{zr+3a z{D*=t(`AXyS%X7N z%a#RZw6vD^t_rnM`L4E>m=U&R!A-&}nZIi$BOPvkhrCuUe@BN~-lRD)f44;J%TwgE zcze8u!PQ_NR7?o(NylLXVTfDO zxs5=@|GsYEsNo4M#nT%N!UE(?dnS)t2+{ELYAFp*3=iF=|EQnTp`#vlSXuGVraYo? z+RCzXo6h3qA8{KG?S4nE(lM+;Eb4nT3XV;7gcAxUi5m)`k5tv}cPy()8ZR3TLW3I- zAS^}cq-IJvL7a4RgR!yk@~RT%$lA7{L5ES*hyx)M4(yxI$Ub(4f)K|^v1>zvwQY!_ zIrWw8q9GS^!Dp~}+?mbnB6jDF8mVlbQ!jFKDY;w=7;XO{9bq7>LXGK24WA`;rL)_Z z)&j}pbV(;6gY;VMhbxgvn`X;6x}VUEE-7 z%)7j-%t8S=ZL3yc)HbXDAqJZvBTPoiW_A-+a8m3_Z?v{DN7Tnr#O_VUMT0UBt$;p` zDh6JbGHN8JJ*JN%y2%msb97@_S>9!%Egwk;?PEkU9ntz&3uR}%Fj5d$JHQbQb3}a{ zSzFT^#n=VInPpcAS}CNxj?_ zVscANk5Cfz(51EI1pz};AWWb|kgbYNb4wCEGUn3+eMUMV?1-{=I4TlmLJMot@rd07 zZuo2hk1ccu{YmGkcYdWAVdk{Z4Nm?^cTD&}jGm+Q1SYIXMwmG*oO*83&#>l%nbR`G zhh=lZ%xIb7kU3#;TBbfECrnC9P=-XpL|TG2BoZdj61*XiFbW8?1Z_wp%#;>${SUIy V$8qr;L*)Pf002ovPDHLkV1hYLS~36t literal 0 HcmV?d00001 diff --git a/ui/public/layers.png b/ui/public/layers.png new file mode 100644 index 0000000000000000000000000000000000000000..1a72e5784b2b456eac5d7670738db80697af3377 GIT binary patch literal 696 zcmV;p0!RIcP)*@&l2<6p=!C&s@#ZL+%BQvF&b?w6S%wp=I>1QHj7AP5C)IWy#b znXXB;g;j=$a-tW89K%FbDceHVq&unY*Wx3L#=EGWH=rjqnp|4c_Ulec!ql3#G-5ZF zVlbBA@XP=)C8U&+Lrc)S4O5%1$&{(;7R^K(CSnvSr$v;+B$8q&7Bf|h$#PARo1^%M zf1H^nG-EiXVXr07OH(*8R)xa|FD;lXUlg_-%)~ZGsL2cX0NXaAzN2q%jqLRR6ruVk8`Jb7n#{`T;o@`F= z#3YcynIR^s83UNF3D!f5m#Mg)NJ24&Qfrqb&_z=yF;=B)#9Iq7u-@^O!(mW{D;qvr zPc)gVb%aowtS8m@ElL4A9G>w#ffQ~q{i&_i)*6f^)Sz|C?C>zb4Uo?H<-&Hz@a?J; z$ml@zGygWofb9$ZBj6aLjpLhsT2AzjOu=-*u_gSCULuqp7Vds@BKcX=lOk~^Pb;%&wG9p3o}FL;Zuhp5D3)R z2yY2yCGfH2=LJmOkQw^9n>daF6?Fz>oOD64$CM+_T`j0x%{zb|G zWolt{H|diO#S`|$6RM$ zYQuE4RW{2yZ`>fAt>jzyYyOB?)~HrQBlbbLT5yF%Xq8FEuzo80dd{%Q!{_)^mTE`^ z2$xe>TH$qiDJ+}(ajTp$Y*4vgGRrt^_?JwUO3+hm&{Mb<8aRtf7%F@*!JJv* zmcB*cag=-t4U&g79u1krRAKHHm?ZXHP8z-#KdAM9?vU7sxldD%A5;r0Rk~kblro}5 z9YhoJP18m~=v^kMBWPltYTV$TD;r4n^eZVWmDs^6;ZN_RG+a#^(N18a+%xd;JvScL zu54_hiMdFR4767cmcp!KOryQBQG{$|3e)h(z_sY-NRM>A$84n-CdxAt6V242bQmV| z86*uGCJtVTXCvLyz=eM@jE-Vz#IeA4DY~VhqL`R_>D;YIh9amQX~+l$Sfbohb*X)d zKiDG!?8t|64T_+_Jzbv6K)P|KG-6qDVGPYUwpPqb#c;-juz~ZW0bFF4JlB>cOB#?3 z9XJ~@0J1u{T_(66oVpmpLOkqOk6}qY=vN7820OS|_L-o5(4!i~Ivv=j{IKzS2m>C_ zhm9Npo09&0s*wy#K%InNpSW)yCZOhAFheUQtcXnn!x)WSjonNUm7@fguKPg0C3ESs~`Bd3Pyd$@XU8m z0JZWv0l=fZ{{jH?{!9Nt!mEGL|9_Oug?i>9H?4E!|Krk+(hy9WRiM;!>w8@J9&fq& z${#rK1z4j2$*KVGO=b{ivL6FFEPprv0No7|9RPB_H>dzW{;{(>P`XWmKn^Y#<8`e9 zc*;k@X>z(^khkvlh3UB1ICnF@RRHbZaQhkI;sl{txVGnBEzaFKZpw96Fm8qu^5@!a z+db!omc48o>}VvJr!j9Mpo^ZMPs2FKikZu-3edWhZ~5&Mp15G60gsVYic)|~eH4Q6 zF8d5^efqo~DD}CwRpRO|j91O-zygw(bv;<>V5MDzeC#nk zosJI@GCU;ylx)tp87H~!5Gl8^4UxdZ-ZLrRy7g=zwjIe|v>O(6W-QBuv-7h4HTLcz&ce9H!^9o^4XLD_t08@f%uD+tdxMAHzHi z6>y1>XBw|wNRu9u6j`13s*X9iz%Z1zep^?+<}$-U*uzd9$?LD0QWc+GSyhyvx<?!6YcvM{vC6CN2-dD>XyCsuOMe zdjA0H)tFMHvR%5Uqd_swkzDP0t5)bhy5xwusp(WsD}~`13N0NuN78MHcc03G_@3v- zZOvStb!W8+G+$o+mNh5)?USue0<9~5nql|l&C!mcb^cmUZGk2gF&p9IOMcs@2-WZX z+M_WESiwx34!IyuOY(`!=Sit;If5uuYqSJm`D>ogL1P7x5=v2W{zicaAxUs>WGzTn zQv?x3HR!VK$IB{-D-)cU&hLE;M2}umynSZBHRVLCW#WkaY>!>~#*V;;^Ck!H4Swwp zDHCGo7gMu}4-?)ga$s&da$6}|l&eSgpl~CnG5lbg z7&|&nHy^@(l0;d(4qw!>Pc+03BPqwvhV@DjJr)KAb74dUY>mzPErgW+cGhAfAE(Hx zg7S551PZuugrt1qVHk*xE*1`NeDO|ZnOO1ye(Ps{N=r+Q=S*|(%4dYb+TIr5*H@Ka z&IFce5q4snQ7O4sQm?Pxu??B#U>#Bu+HC!Ti{Sl150Y#4pk06Ac+lU@`2YRqk-uHH zZoIWi#kr-H+gi|P?w*2JMQ7U)c>*fCAPTksemc#0N4+Zgz+o*bN1@=(#&Q(RLz+r2 zQx|up>q>^w^^^t*`_3bp*JBDwCvP3iT>oMu+dLrW{Yd*GhC1Kx;_L$zF%*j;?iDxZ zrao$m-Bw;}qtlD8Ts>}{*(A|it9iEx_ZRY$yVv3y#q}J<;l}p;3_y0NqKJBW%sac- z#s<-=rSr4%CNFQcuf<8$A3ba|hx+!=-B0jwr*}bFG1p0OLTqz#DYd z16dVY=E5n{UkaA*7{FAF7c$=SE0gV@(AxW_6rfOFvBFyfQpO=ChwyqQo?nZOT`6__ zP3(sCcoy|xktOO{hUoSFKDM)^*yWXvlS$9yTyC~k^q#t~$$O;oU_E7XGiY~S^b+mS zVh=RZHn+0(T-ooM5xx%AW=ZUqv zgKQURIr-z7x5ejdVPYlT>F)dyou|#!MM#5qXK_BVQyz*bJ!*A&^rr((=SaeGlUNwV z01+e{DcnsPPIth+gTfMc34NrqGRM-T5f0=)<0vZ6?K`I0Z1Y3GdqxI|$iyh%qoeNX UQO-*oc+)|Q_08}VdXD6O0C*xx%>V!Z literal 0 HcmV?d00001 diff --git a/ui/public/marker-icon.png b/ui/public/marker-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..950edf24677ded147df13b26f91baa2b0fa70513 GIT binary patch literal 1466 zcmV;r1x5OaP)P001cn1^@s6z>|W`000GnNklGNuHDcIX17Zdjl&3`L?0sTjIws<{((Dh&g-s0<@jYQyl?D*X^?%13;ml^gy> ziMrY_^1WI=(g@LMizu=zCoA>C`6|QEq1eV92k*7m>G65*&@&6)aC&e}G zI)pf-Za|N`DT&Cn1J|o`19mumxW~hiKiKyc-P`S@q)rdTo84@QI@;0yXrG%9uhI>A zG5QHb6s4=<6xy{1 z@NMxEkryp{LS44%z$3lP^cX!9+2-;CTt3wM4(k*#C{aiIiLuB>jJj;KPhPzIC00bL zU3a#;aJld94lCW=`4&aAy8M7PY=HQ>O%$YEP4c4UY#CRxfgbE~(|uiI=YS8q;O9y6 zmIkXzR`}p7ti|PrM3a}WMnR=3NVnWdAAR>b9X@)DKL6=YsvmH%?I24wdq?Gh54_;# z$?_LvgjEdspdQlft#4CQ z`2Zyvy?*)N1Ftw|{_hakhG9WjS?Az@I@+IZ8JbWewR!XUK4&6346+d#~gsE0SY(LX8&JfY>Aj)RxGy96nwhs2rv zzW6pTnMpFkDSkT*a*6Dx|u@ds6ISVn0@^RmIsKZ5Y;bazbc;tTSq(kg(=481ODrPyNB6n z-$+U}(w$m6U6H$w17Bw+wDaFIe~GvNMYvnw31MpY0eQKT9l>SU``8k7w4)z!GZKMI z#_cEKq7k~i%nlK@6c-K?+R;B#5$?T#YpKD`t_4bAs^#E+@5QW$@OX3*`;(#{U^d-vY)&xEE>n5lYl&T?Amke9$Lam@{1K@O ze*LXqlKQHiv=gx+V^Cbb2?z@ISBQ*3amF;9UJ3SBg(N|710TLamQmYZ&Qjn2LuO<* zCZlB4n%@pc&7NNnY1}x+NWpHlq`OJEo|`aYN9<`RBUB+79g;>dgb6YlfN#kGL?lO_ z!6~M^7sOnbsUkKk<@Ysie&`G>ruxH&Mgy&8;i=A zB9OO!xR{AyODw>DS-q5YM{0ExFEAzt zm>RdS+ssW(-8|?xr0(?$vBVB*%(xDLtq3Hf0I5yFm<_g=W2`QWAax{1rWVH=I!VrP zs(rTFX@W#t$hXNvbgX`gK&^w_YD;CQ!B@e0QbLIWaKAXQe2-kkloo;{iF#6}z!4=W zi$giRj1{ zt;2w`VSCF#WE&*ev7jpsC=6175@(~nTE2;7M-L((0bH@yG}-TB$R~WXd?tA$s3|%y zA`9$sA(>F%J3ioz<-LJl*^o1|w84l>HBR`>3l9c8$5Xr@xCiIQ7{x$fMCzOk_-M=% z+{a_Q#;42`#KfUte@$NT77uaTz?b-fBe)1s5XE$yA79fm?KqM^VgLXD07*qoM6N<$ Ef<_J(9smFU literal 0 HcmV?d00001 diff --git a/ui/public/vercel.svg b/ui/public/vercel.svg new file mode 100755 index 0000000..fbf0e25 --- /dev/null +++ b/ui/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/ui/src/api/index.ts b/ui/src/api/index.ts new file mode 100644 index 0000000..e0baecc --- /dev/null +++ b/ui/src/api/index.ts @@ -0,0 +1,25 @@ +import axios, { AxiosResponse } from 'axios'; + +const serviceHost = process.env.SERVICE_HOST || 'http://localhost'; +const servicePort = process.env.SERVICE_PORT || 5000; + +export async function getRequest(endpoint: string, params: any): Promise | undefined> { + const response = await axios + .get(`${serviceHost}:${servicePort}/${endpoint}`, { params }) + .catch((error) => console.error(error)); + return response || undefined; +} + +export async function postRequest(endpoint: string, body: any): Promise | undefined> { + const response = await axios + .post(`${serviceHost}:${servicePort}/${endpoint}`, { body }) + .catch((error) => console.error(error)); + return response || undefined; +} + +export interface Metadata { + limit: number; + page: number; + pages: number; + total: number; +} diff --git a/ui/src/api/spells.ts b/ui/src/api/spells.ts new file mode 100644 index 0000000..c5b13f3 --- /dev/null +++ b/ui/src/api/spells.ts @@ -0,0 +1,37 @@ +import { getRequest } from '.'; +import { GetSpellsResponse } from './spells.types'; + +interface GetSpellsParams { + name?: string; + schools?: string[]; + levels?: number[]; + ritual?: boolean; + concentration?: boolean; + classes?: string[]; + damage_inflict?: string[]; + damage_resist?: string[]; + conditions?: string[]; + saving_throw?: string[]; + attack_type?: string[]; + limit?: number; + page?: number; +} + +export async function getSpells(params?: GetSpellsParams): Promise { + const response = await getRequest('spells', { + name: params?.name, + schools: params?.schools?.join(','), + levels: params?.levels?.join(','), + ritual: params?.ritual, + concentration: params?.concentration, + classes: params?.classes?.join(','), + damage_inflict: params?.damage_inflict?.join(','), + damage_resist: params?.damage_resist?.join(','), + conditions: params?.conditions?.join(','), + saving_throw: params?.saving_throw?.join(','), + attack_type: params?.attack_type?.join(','), + limit: params?.limit, + page: params?.page + }); + return response?.data || { data: [] }; +} diff --git a/ui/src/api/spells.types.ts b/ui/src/api/spells.types.ts new file mode 100644 index 0000000..81677f4 --- /dev/null +++ b/ui/src/api/spells.types.ts @@ -0,0 +1,82 @@ +import { Metadata } from '.'; + +export interface Spell { + id: string; + name: string; + school: string; + level: number; + ritual: boolean; + casting_time: CastingTime; + saving_throw?: string[]; + attack_type?: string; + damage_inflict?: string[]; + damage_resist?: string[]; + conditions?: string[]; + range: Range; + area?: Area; + components: Components; + durations: Duration[]; + classes: string[]; + sources: Source[]; + tags?: string[]; + description?: Description; +} + +export interface CastingTime { + value: number; + unit: string; +} + +export interface Range { + type: string; + value?: number; + unit?: string; +} + +export interface Area { + type: string; + value?: number; + unit?: string; +} + +export interface Components { + verbal: boolean; + somatic: boolean; + material: boolean; + materials_needed?: string; + materials_cost?: number; + materials_consumed?: boolean; +} + +export interface Duration { + type: string; + value?: number; + unit?: string; + // concentration: boolean; +} + +export interface Source { + source: string; + page?: number; +} + +export interface Description { + entries: EntryType[]; +} + +type EntryType = string | Entry; + +export interface Entry { + type: string; + items: string[]; +} + +export interface GetSpellResponse { + data: Spell; + metadata: Metadata; +} + +export interface GetSpellsResponse { + data: Spell[]; + metadata: Metadata; +} diff --git a/ui/src/app/backgrounds/page.tsx b/ui/src/app/backgrounds/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/backgrounds/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/bot/page.tsx b/ui/src/app/bot/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/ui/src/app/classes/page.tsx b/ui/src/app/classes/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/classes/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/feats/page.tsx b/ui/src/app/feats/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/feats/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/items/page.tsx b/ui/src/app/items/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/items/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/layout.tsx b/ui/src/app/layout.tsx new file mode 100644 index 0000000..3ead78f --- /dev/null +++ b/ui/src/app/layout.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import RecoilRootWrapper from '@app/recoil-root-wrapper'; +import Topbar from '@/components/Topbar'; +import { Inter } from 'next/font/google'; +import { Box, MantineProvider } from '@mantine/core'; +import { ModalsProvider } from '@mantine/modals'; +import { Notifications } from '@mantine/notifications'; +import 'styles/globals.css'; +import '@mantine/core/styles.css'; +import '@mantine/notifications/styles.css'; + +export const metadata = { + title: 'Siren', + description: '' +}; + +const inter = Inter({ subsets: ['latin'] }); + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + Siren + + + + + + + + + {children} + + + + + + + ); +} diff --git a/ui/src/app/options/page.tsx b/ui/src/app/options/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/options/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/races/page.tsx b/ui/src/app/races/page.tsx new file mode 100644 index 0000000..e892a07 --- /dev/null +++ b/ui/src/app/races/page.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Page() { + return <>; +} diff --git a/ui/src/app/recoil-root-wrapper.tsx b/ui/src/app/recoil-root-wrapper.tsx new file mode 100644 index 0000000..363f3f6 --- /dev/null +++ b/ui/src/app/recoil-root-wrapper.tsx @@ -0,0 +1,8 @@ +'use client'; + +import { RecoilRoot } from 'recoil'; +import React, { ReactNode } from 'react'; + +export default function RecoilRootWrapper({ children }: { children: ReactNode }) { + return {children}; +} diff --git a/ui/src/app/spells/page.tsx b/ui/src/app/spells/page.tsx new file mode 100644 index 0000000..ec80cea --- /dev/null +++ b/ui/src/app/spells/page.tsx @@ -0,0 +1,91 @@ +'use client'; + +import { getSpells } from '@/api/spells'; +import { Spell } from '@/api/spells.types'; +import SpellModal from '@/components/SpellModal'; +import React, { useEffect, useState } from 'react'; +import './spells.css'; +import { Box, TextInput } from '@mantine/core'; +import { AiOutlineVerticalAlignTop } from 'react-icons/ai'; + +export default function Page() { + const [cantrips, setCantrips] = useState([]); + const [level1, setLevel1] = useState([]); + const [level2, setLevel2] = useState([]); + const [level3, setLevel3] = useState([]); + const [level4, setLevel4] = useState([]); + const [level5, setLevel5] = useState([]); + const [level6, setLevel6] = useState([]); + const [level7, setLevel7] = useState([]); + const [level8, setLevel8] = useState([]); + const [level9, setLevel9] = useState([]); + const [activeSpell, setActiveSpell] = useState(undefined); + const [isOpen, setIsOpen] = useState(false); + const [searchName, setSearchName] = useState(''); + + useEffect(() => { + getSpells({ levels: [0] }).then((s) => setCantrips(s.data)); + getSpells({ levels: [1] }).then((s) => setLevel1(s.data)); + getSpells({ levels: [2] }).then((s) => setLevel2(s.data)); + getSpells({ levels: [3] }).then((s) => setLevel3(s.data)); + getSpells({ levels: [4] }).then((s) => setLevel4(s.data)); + getSpells({ levels: [5] }).then((s) => setLevel5(s.data)); + getSpells({ levels: [6] }).then((s) => setLevel6(s.data)); + getSpells({ levels: [7] }).then((s) => setLevel7(s.data)); + getSpells({ levels: [8] }).then((s) => setLevel8(s.data)); + getSpells({ levels: [9] }).then((s) => setLevel9(s.data)); + }, []); + + return ( + +

Spells

+ setSearchName(e.target.value)} + style={{ width: '25%' }} + /> + s.name.toLowerCase().includes(searchName.toLowerCase()))} + onClick={(spell) => { + setActiveSpell(spell); + setIsOpen(true); + }} + /> +
+ {activeSpell && setIsOpen(false)} />} +
+ ); +} + +function SpellSection({ title, spells, onClick }: { title: string; spells: Spell[]; onClick: (spell: Spell) => void }) { + const isBrowser = () => typeof window !== 'undefined'; //The approach recommended by Next.js + + function scrollToTop() { + if (!isBrowser()) return; + window.scrollTo({ top: 0, behavior: 'smooth' }); + } + + return ( + +

{title}

+
    + {spells.map((spell) => ( +
  • onClick(spell)} + > + {spell.name} +
  • + ))} +
+
+ Back to top + +
+
+ ); +} diff --git a/ui/src/app/spells/spells.css b/ui/src/app/spells/spells.css new file mode 100644 index 0000000..407132f --- /dev/null +++ b/ui/src/app/spells/spells.css @@ -0,0 +1,7 @@ +.spell-item { + padding: 0.2rem; +} + +.spell-item:hover { + text-decoration: underline; +} \ No newline at end of file diff --git a/ui/src/components/SpellModal.tsx b/ui/src/components/SpellModal.tsx new file mode 100644 index 0000000..623516a --- /dev/null +++ b/ui/src/components/SpellModal.tsx @@ -0,0 +1,153 @@ +'use client'; + +import { Spell } from '@/api/spells.types'; +import { levelText, rollDice } from '@/js/spells'; +import { capitalize } from '@/js/utils'; +import { Grid, Modal } from '@mantine/core'; +import { notifications } from '@mantine/notifications'; + +interface SpellModalProps { + spell: Spell; + isOpen: boolean; + onClose(): void; +} + +export default function SpellModal({ spell, isOpen, onClose }: SpellModalProps) { + return ( + +

{spell.name}

+ + + + {capitalize(spell.school)} {levelText(spell)} + + + +
+ + {spell.components.verbal && spell.components.somatic ? 'V, ' : 'V '} + {spell.components.somatic && spell.components.material ? 'S, ' : 'S '} + {spell.components.material && spell.components.materials_needed ? 'M*' : 'M'} + + {spell.components.materials_needed && ( + +
*{capitalize(spell.components.materials_needed)} +
+ )} +
+
+ + Sources: + {spell.sources.map((s) => ( + + {s.source} + {s.page ? `.${s.page}` : ''} + + ))} + + + Classes: + + {spell.classes.map((c) => ( + + {capitalize(c)} + + ))} + + + + Casting Time: + + {spell.casting_time.value} {capitalize(spell.casting_time.unit)} + + + + Range: + + {spell.range.type != 'point' && capitalize(spell.range.type)} {spell.range.value}{' '} + {capitalize(spell.range.unit)} + + + + Duration: + + {spell.durations.map((d) => ( + + {capitalize(d.type)} {d.value} {capitalize(d.unit)} + + ))} + + + + + +
+
+ ); +} + +function SpellDescription({ spell }: { spell: Spell }) { + function parseText(text: string) { + const regex = /{@(.*?) (.*?)}/g; + const matches = text.matchAll(regex); + const result = []; + let lastIndex = 0; + for (const match of matches) { + const [full, type, name] = match; + result.push(text.slice(lastIndex, match.index)); + if (match.index !== undefined) { + result.push( + handleLink(type, name)} className='link'> + {name} + + ); + lastIndex = match.index + full.length; + } + } + result.push(text.slice(lastIndex)); + return result; + } + + function handleLink(type: string, name: string) { + if (type == 'spell') { + console.log(`Link to spell: ${name}`); + } else if (type == 'dice' || type == 'damage') { + const rolls = rollDice(name); + notifications.show({ + title: `Rolling ${name}`, + message: `${rolls.join(' + ')} = ${rolls.reduce((a, b) => a + b, 0)}`, + color: 'blue', + autoClose: 5000, + withCloseButton: false + }); + } else { + console.error(`Unknown link type: ${type}`); + } + } + + return ( + <> + {spell.description && ( + <> + {spell.description.entries.map((e) => + typeof e === 'string' ? ( +

{parseText(e)}

+ ) : ( + <> + {e.type == 'list' ? ( +
    + {e.items.map((text) => ( +
  • {parseText(text)}
  • + ))} +
+ ) : ( + <> + )} + + ) + )} + + )} + + ); +} diff --git a/ui/src/components/Topbar/index.tsx b/ui/src/components/Topbar/index.tsx new file mode 100644 index 0000000..780e7a5 --- /dev/null +++ b/ui/src/components/Topbar/index.tsx @@ -0,0 +1,57 @@ +'use client'; + +import Link from 'next/link'; +import { usePathname } from 'next/navigation'; +import './topbar.css'; + +const headerItems = [ + { + name: 'Races', + link: '/races' + }, + { + name: 'Classes', + link: '/classes' + }, + { + name: 'Feats', + link: '/feats' + }, + { + name: 'Options & Features', + link: '/options' + }, + { + name: 'Backgrounds', + link: '/backgrounds' + }, + { + name: 'Items', + link: '/items' + }, + { + name: 'Spells', + link: '/spells' + } +]; + +export default function Topbar() { + const pathName = usePathname(); + + return ( + + ); +} diff --git a/ui/src/components/Topbar/topbar.css b/ui/src/components/Topbar/topbar.css new file mode 100644 index 0000000..6cc7cd2 --- /dev/null +++ b/ui/src/components/Topbar/topbar.css @@ -0,0 +1,47 @@ +.navbar { + display: flex; + justify-content: space-between; + color: black; + border-bottom: 1px solid #e6e6e6; +} + +.navbar .left { + display: flex; +} + +.navbar .title { + padding-left: 2em; + padding-right: 2em; + margin: auto; + font-size: x-large; +} + +.navbar .left .search { + margin: auto; +} + +.navbar .avatar { + padding-right: 2em; + margin-top: auto; + margin-bottom: auto; +} + +.header-items { + display: flex; + justify-content: space-between; +} + +.header-items .header-item { + padding-left: 2em; + padding-right: 2em; + margin: auto; + border-bottom: 2px solid transparent; +} + +.header-items .header-item:hover { + border-bottom: 2px solid #e6e6e6; +} + +.header-items .active { + border-bottom: 2px solid #5f5f5f; +} \ No newline at end of file diff --git a/ui/src/js/spells.ts b/ui/src/js/spells.ts new file mode 100644 index 0000000..ec525dd --- /dev/null +++ b/ui/src/js/spells.ts @@ -0,0 +1,23 @@ +import { Spell } from '@/api/spells.types'; + +export function levelText(spell: Spell) { + if (spell.level === 0) { + return 'Cantrip'; + } else { + return `Level ${spell.level}`; + } +} + +export function rollDice(dice: string): number[] { + // eslint-disable-next-line prefer-const + let [count, sides] = dice.split('d'); + const rolls = []; + if (isNaN(parseInt(count))) { + count = '1'; + } + for (let i = 0; i < parseInt(count); i++) { + rolls.push(Math.floor(Math.random() * parseInt(sides)) + 1); + } + console.log(rolls); + return rolls; +} diff --git a/ui/src/js/theme.ts b/ui/src/js/theme.ts new file mode 100644 index 0000000..cdc2cb2 --- /dev/null +++ b/ui/src/js/theme.ts @@ -0,0 +1,5 @@ +'use client'; + +import { createTheme } from '@mantine/core'; + +export const theme = createTheme({}); diff --git a/ui/src/js/utils.ts b/ui/src/js/utils.ts new file mode 100644 index 0000000..cd1ac5d --- /dev/null +++ b/ui/src/js/utils.ts @@ -0,0 +1,6 @@ +export function capitalize(str: string | undefined): string { + if (!str || str.length === 0) { + return ''; + } + return str.charAt(0).toUpperCase() + str.slice(1); +} diff --git a/ui/styles/globals.css b/ui/styles/globals.css new file mode 100755 index 0000000..19158c6 --- /dev/null +++ b/ui/styles/globals.css @@ -0,0 +1,38 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} + +.content { + display: flex; + flex-direction: row; + flex: 1; + overflow: hidden; +} + +.wrapper > nav { + flex: 0 0 56px; + overflow: hidden; +} + +.link { + list-style-type: none; + cursor: pointer; + color: #297bff; +} + +.link:hover { + color: #1c59bb; +} \ No newline at end of file diff --git a/ui/tsconfig.json b/ui/tsconfig.json new file mode 100755 index 0000000..5753bf1 --- /dev/null +++ b/ui/tsconfig.json @@ -0,0 +1,45 @@ +{ + "compilerOptions": { + "target": "ESNext", + "downlevelIteration": true, + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + "@api/*": ["src/api"], + "@app/*": ["./src/app/*"], + "@components/*": ["src/components/*"], + "@lib/*": ["src/components/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} From 49b3a3854375f93967aa2af7e07ebb950fd405a9 Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Thu, 5 Oct 2023 14:26:02 -0400 Subject: [PATCH 2/4] Refactored spells import, working on level_1 --- service/.env.TEMPLATE | 4 +- service/data/layout.json | 48 + service/data/spells/cantrips.json | 53 +- service/data/spells/level_1.json | 2823 +++++++++++++++++++++++++++++ service/src/db/mod.rs | 4 +- service/src/db/spells/mod.rs | 81 +- service/src/db/spells/model.rs | 7 +- service/src/db/spells/types.rs | 162 +- service/src/main.rs | 7 +- 9 files changed, 3044 insertions(+), 145 deletions(-) create mode 100644 service/data/layout.json diff --git a/service/.env.TEMPLATE b/service/.env.TEMPLATE index 8799caa..6527927 100644 --- a/service/.env.TEMPLATE +++ b/service/.env.TEMPLATE @@ -8,6 +8,4 @@ DATABASE_PORT=5432 SERVICE_HOST=localhost SERVICE_PORT=5000 - -DISCORD_TOKEN= -OPENAI_API_KEY= \ No newline at end of file +DATA_DIR_PATH= \ No newline at end of file diff --git a/service/data/layout.json b/service/data/layout.json new file mode 100644 index 0000000..801cdc8 --- /dev/null +++ b/service/data/layout.json @@ -0,0 +1,48 @@ +{ + "name": "", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "saving_throw": [], + "attack_type": [], + "damage_inflict": [], + "damage_resist": [], + "conditions": [], + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "area": { + "type": "cube", + "size": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false, + "materials_needed": "", + "materials_cost": 0, + "materials_consumed": false + }, + "durations": [ + { + "type": "instantaneous", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ { "source": "", "page": 0 } ], + "tags": [], + "description": { + "entries": [ + + ] + } +} \ No newline at end of file diff --git a/service/data/spells/cantrips.json b/service/data/spells/cantrips.json index 39325e6..fd2ee5a 100644 --- a/service/data/spells/cantrips.json +++ b/service/data/spells/cantrips.json @@ -213,8 +213,7 @@ "entries": [ "You choose nonmagical flame that you can see within range and that fits within a 5-foot cube. You affect it in one of the following ways:", { - "type": "list", - "items": [ + "list": [ "You instantaneously expand the flame 5 feet in one direction, provided that wood or other fuel is present in the new location.", "You instantaneously extinguish the flames within the cube.", "You double or halve the area of bright light and dim light cast by the flame, change its color, or both. The change lasts for 1 hour.", @@ -253,7 +252,7 @@ { "type": "concentration", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["artificer", "druid", "sorcerer", "warlock", "wizard"], @@ -293,7 +292,7 @@ { "type": "concentration", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["artificer", "bard", "sorcerer", "wizard"], @@ -341,8 +340,7 @@ "entries": [ "Whispering to the spirits of nature, you create one of the following effects within range:", { - "type": "list", - "items": [ + "list": [ "You create a tiny, harmless sensory effect that predicts what the weather will be at your location for the next 24 hours. The effect might manifest as a golden orb for clear skies, a cloud for rain, falling snowflakes for snow, and so on. This effect persists for 1 round.", "You instantly make a flower blossom, a seed pod open, or a leaf bud bloom.", "You create an instantaneous, harmless sensory effect, such as falling leaves, a puff of wind, the sound of a small animal, or the faint odor of skunk. The effect must fit in a 5-foot cube.", @@ -490,7 +488,7 @@ { "type": "concentration", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["bard", "sorcerer", "warlock", "wizard"], @@ -611,7 +609,7 @@ { "type": "concentration", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["artificer", "cleric", "druid"], @@ -658,8 +656,7 @@ "entries": [ "You seize the air and compel it to create one of the following effects at a point you can see within range:", { - "type": "list", - "items": [ + "list": [ "One Medium or smaller creature that you choose must succeed on a Strength saving throw or be pushed up to 5 feet away from you.", "You create a small blast of air capable of moving one object that is neither held nor carried and that weighs no more than 5 pounds. The object is pushed up to 10 feet away from you. It isn't pushed with enough force to cause damage.", "You create a harmless sensory effect using air, such as causing leaves to rustle, wind to slam shutters shut, or your clothing to ripple in a breeze." @@ -820,7 +817,7 @@ { "type": "timed", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["artificer", "bard", "sorcerer", "warlock", "wizard"], @@ -861,7 +858,7 @@ { "type": "timed", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["artificer", "druid", "warlock"], @@ -882,7 +879,7 @@ "ritual": false, "casting_time": { "value": 1, - "unit": "minutes" + "unit": "minute" }, "range": { "type": "touch" @@ -1014,7 +1011,7 @@ { "type": "timed", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["bard", "sorcerer", "warlock", "wizard"], @@ -1073,8 +1070,7 @@ "entries": [ "You choose a portion of dirt or stone that you can see within range and that fits within a 5-foot cube. You manipulate it in one of the following ways:", { - "type": "list", - "items": [ + "list": [ "If you target an area of loose earth, you can instantaneously excavate it, move it along the ground, and deposit it up to 5 feet away. This movement doesn't have enough force to cause damage.", "You cause shapes, colors, or both to appear on the dirt or stone, spelling out words, creating images, or shaping patterns. The changes last for 1 hour.", "If the dirt or stone you target is on the ground, you cause it to become difficult terrain. Alternatively, you can cause the ground to become normal terrain if it is already difficult terrain. This change lasts for 1 hour." @@ -1162,8 +1158,7 @@ "entries": [ "This spell is a minor magical trick that novice spellcasters use for practice. You create one of the following magical effects within range:", { - "type": "list", - "items": [ + "list": [ "You create an instantaneous, harmless sensory effect, such as a shower of sparks, a puff of wind, faint musical notes, or an odd odor.", "You instantaneously light or snuff out a candle, a torch, or a small campfire.", "You instantaneously clean or soil an object no larger than 1 cubic foot.", @@ -1402,7 +1397,7 @@ "type": "instantaneous" } ], - "classes": [], + "classes": ["wizard"], "sources": [ { "source": "EGW", "page": 189 } ], @@ -1455,8 +1450,7 @@ "entries": [ "You choose an area of water that you can see within range and that fits within a 5-foot cube. You manipulate it in one of the following ways:", { - "type": "list", - "items": [ + "list": [ "You instantaneously move or otherwise change the flow of the water as you direct, up to 5 feet in any direction. This movement doesn't have enough force to cause damage.", "You cause the water to form into simple shapes and animate at your direction. This change lasts for 1 hour.", "You change the water's color or opacity. The water must be changed in the same way throughout. This change lasts for 1 hour.", @@ -1493,7 +1487,7 @@ { "type": "timed", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["druid"], @@ -1642,7 +1636,7 @@ { "type": "timed", "value": 1, - "unit": "minutes" + "unit": "minute" } ], "classes": ["cleric"], @@ -1654,17 +1648,16 @@ "entries": [ "You manifest a minor wonder, a sign of supernatural power, within range. You create one of the following magical effects within range:", { - "type": "list", - "items": [ - "Your voice booms up to three times as loud as normal for 1 minutes.", - "You cause flames to flicker, brighten, dim, or change color for 1 minutes.", - "You cause harmless tremors in the ground for 1 minutes.", + "list": [ + "Your voice booms up to three times as loud as normal for 1 minute.", + "You cause flames to flicker, brighten, dim, or change color for 1 minute.", + "You cause harmless tremors in the ground for 1 minute.", "You create an instantaneous sound that originates from a point of your choice within range, such as a rumble of thunder, the cry of a raven, or ominous whispers.", "You instantaneously cause an unlocked door or window to fly open or slam shut.", - "You alter the appearance of your eyes for 1 minutes." + "You alter the appearance of your eyes for 1 minute." ] }, - "If you cast this spell multiple times, you can have up to three of its 1-minutes effects active at a time, and you can dismiss such an effect as an action." + "If you cast this spell multiple times, you can have up to three of its 1-minute effects active at a time, and you can dismiss such an effect as an action." ] } }, diff --git a/service/data/spells/level_1.json b/service/data/spells/level_1.json index e69de29..00fa213 100644 --- a/service/data/spells/level_1.json +++ b/service/data/spells/level_1.json @@ -0,0 +1,2823 @@ +[ + { + "name": "Absorb Elements", + "school": "abjuration", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "reaction", + "note": "which you take when you take acid, cold, fire, lightning, or thunder damage" + }, + "damage_inflict": ["acid"], + "range": { + "type": "self" + }, + "components": { + "verbal": false, + "somatic": true, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "round" + } + ], + "classes": ["artificer", "druid", "ranger", "sorcerer", "wizard"], + "sources": [ + { "source": "EEPC", "page": 150 } + ], + "description": { + "entries": [ + "The spell captures some of the incoming energy, lessening its effect on you and storing it for your next melee attack. You have resistance to the triggering damage type until the start of your next turn. Also, the first time you hit with a melee attack on your next turn, the target takes an extra {@damage 1d6} damage of the triggering type, and the spell ends.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the extra damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." + ] + } + }, + { + "name": "Alarm", + "school": "abjuration", + "level": 1, + "ritual": true, + "casting_time": { + "value": 1, + "unit": "minute" + }, + "range": { + "type": "point", + "value": 30, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a tiny bell and a piece of fine silver wire" + }, + "durations": [ + { + "type": "timed", + "value": 8, + "unit": "hours" + } + ], + "classes": ["artificer", "{@subclass paladin|Oath of the Watchers}", "ranger", "wizard"], + "sources": [ + { "source": "PHB", "page": 211 }, + { "source": "XGE", "page": 155 } + ], + "description": { + "entries": [ + "You set an alarm against unwanted intrusion. Choose a door, a window, or an area within range that is no larger than a {@filter 20-foot cube|spells|cube|phb|p. 204}. Until the spell ends, an alarm alerts you whenever a Tiny or larger creature touches or enters the warded area. When you cast the spell, you can designate creatures that won't set off the alarm. You also choose whether the alarm is mental or audible.", + "A mental alarm alerts you with a ping in your mind if you are within 1 mile of the warded area. This ping awakens you if you are {@condition sleeping}.", + "An audible alarm produces the sound of a hand bell for 10 seconds within 60 feet." + ] + } + }, + { + "name": "Animal Friendship", + "school": "enchantment", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "conditions": ["charmed"], + "range": { + "type": "point", + "value": 30, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a morsel of food" + }, + "durations": [ + { + "type": "timed", + "value": 24, + "unit": "hours" + } + ], + "classes": ["bard", "druid", "ranger", "{@subclass cleric|Nature Domain}"], + "sources": [ + { "source": "PHB", "page": 212 } + ], + "description": { + "entries": [ + "This spell lets you convince a beast that you mean it no harm. Choose a beast that you can see within range. It must see and hear you. If the beast's Intelligence is 4 or higher, the spell fails. Otherwise, the beast must succeed on a Wisdom saving throw or be {@condition charmed} by you for the spell's duration. If you or one of your companions harms the target, the spell ends.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can affect one additional beast for each slot level above 1st." + ] + } + }, + { + "name": "Armor of Agathys", + "school": "abjuration", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "damage_inflict": ["cold"], + "range": { + "type": "self" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a cup of water" + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "hour" + } + ], + "classes": ["warlock", "{@subclass paladin|Oath of Conquest}"], + "sources": [ + { "source": "PHB", "page": 215 } + ], + "description": { + "entries": [ + "A protective magical force surrounds you, manifesting as a spectral frost that covers you and your gear. You gain {@dice 5} temporary hit points for the duration. If a creature hits you with a melee attack while you have these hit points, the creature takes {@damage 5} cold damage.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, both the temporary hit points and the cold damage increase by {@scaledamage 5|1-9|5} for each slot level above 1st." + ] + } + }, + { + "name": "Arms of Hadar", + "school": "conjuration", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "saving_throw": ["strength"], + "damage_inflict": ["necrotic"], + "range": { + "type": "self" + }, + "area": { + "type": "sphere", + "size": 10, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": false + }, + "durations": [ + { + "type": "instantaneous" + } + ], + "classes": ["warlock"], + "sources": [ + { "source": "PHB", "page": 215 } + ], + "description": { + "entries": [ + "You invoke the power of Hadar, the Dark Hunger. Tendrils of dark energy erupt from you and batter all creatures within 10 feet of you. Each creature in that area must make a Strength saving throw. On a failed save, a target takes {@damage 2d6} necrotic damage and can't take reactions until its next turn. On a successful save, the creature takes half damage, but suffers no other effect.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." + ] + } + }, + { + "name": "Bane", + "school": "enchantment", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "saving_throw": ["charisma"], + "range": { + "type": "point", + "value": 30, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a drop of blood" + }, + "durations": [ + { + "type": "concentration", + "value": 1, + "unit": "minute" + } + ], + "classes": ["bard", "cleric", "{@subclass paladin|Oath of Vengeance}", "{@subclass warlock|The Undead}"], + "sources": [ + { "source": "PHB", "page": 216 } + ], + "description": { + "entries": [ + "Up to three creatures of your choice that you can see within range must make Charisma saving throws. Whenever a target that fails this saving throw makes an attack roll or a saving throw before the spell ends, the target must roll a {@dice d4} and subtract the number rolled from the attack roll or saving throw.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st." + ] + } + }, + { + "name": "Beast Bond", + "school": "divination", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "touch" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a bit of fur wrapped in a cloth" + }, + "durations": [ + { + "type": "concentration", + "value": 10, + "unit": "minutes" + } + ], + "classes": ["druid", "ranger"], + "sources": [ + { "source": "EEPC", "page": 150 } + ], + "description": { + "entries": [ + "You establish a telepathic link with one beast you touch that is friendly to you or {@condition charmed} by you. The spell fails if the beast's Intelligence is 4 or higher. Until the spell ends, the link is active while you and the beast are within line of sight of each other. Through the link, the beast can understand your telepathic messages to it, and it can telepathically communicate simple emotions and concepts back to you. While the link is active, the beast gains advantage on attack rolls against any creature within 5 feet of you that you can see." + ] + } + }, + { + "name": "Bless", + "school": "enchantment", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 30, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "a sprinkling of holy water" + }, + "durations": [ + { + "type": "concentration", + "value": 1, + "unit": "minute" + } + ], + "classes": ["cleric", "paladin"], + "sources": [ + { "source": "PHB", "page": 219 } + ], + "description": { + "entries": [ + "You bless up to three creatures of your choice within range. Whenever a target makes an attack roll or a saving throw before the spell ends, the target can roll a {@dice d4} and add the number rolled to the attack roll or saving throw.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st." + ] + } + }, + { + "name": "Burning Hands", + "school": "evocation", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "saving_throw": ["dexterity"], + "damage_inflict": ["fire"], + "range": { + "type": "self" + }, + "area": { + "type": "cone", + "size": 15, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": false + }, + "durations": [ + { + "type": "instantaneous" + } + ], + "classes": ["{@subclass cleric|Light Domain}", "{@subclass druid|Circle of Wildfire}", "sorcerer", "{@subclass warlock|The Fiend}", "{@subclass warlock|The Genie}", "wizard"], + "sources": [ + { "source": "PHB", "page": 220 } + ], + "description": { + "entries": [ + "As you hold your hands with thumbs touching and fingers spread, a thin sheet of flames shoots forth from your outstretched fingertips. Each creature in a {@filter 15-foot cone|spells|cone|phb|p. 204} must make a Dexterity saving throw. A creature takes {@damage 3d6} fire damage on a failed save, or half as much damage on a successful one.", + "The fire ignites any flammable objects in the area that aren't being worn or carried.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." + ] + } + }, + { + "name": "Catapult", + "school": "transmutation", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 60, + "unit": "feet" + }, + "saving_throw": ["dexterity"], + "damage_inflict": ["bludgeoning"], + "components": { + "verbal": false, + "somatic": true, + "material": false + }, + "durations": [ + { + "type": "instantaneous" + } + ], + "classes": ["artificer", "sorcerer", "wizard"], + "sources": [ + { "source": "EEPC", "page": 150 } + ], + "description": { + "entries": [ + "Choose one object weighing 1 to 5 pounds within range that isn't being worn or carried. The object flies in a straight line up to 90 feet in a direction you choose before falling to the ground, stopping early if it impacts against a solid surface. If the object would strike a creature, that creature must make a Dexterity saving throw. On a failed save, the object strikes the target and stops moving. When the object strikes something, the object and what it strikes each take {@damage 3d8} bludgeoning damage.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the maximum weight of objects that you can target with this spell increases by 5 pounds, and the damage increases by {@scaledamage 1d8|1-9|1d8}, for each slot level above 1st." + ] + } + }, + { + "name": "Cause Fear", + "school": "necromancy", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "saving_throw": ["wisdom"], + "conditions": ["frightened"], + "range": { + "type": "point", + "value": 60, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "concentration", + "value": 1, + "unit": "minute" + } + ], + "classes": ["warlock", "wizard"], + "sources": [ + { "source": "XGE", "page": 151 } + ], + "description": { + "entries": [ + "You awaken the sense of mortality in one creature you can see within range. A construct or an undead is immune to this effect. The target must succeed on a Wisdom saving throw or become {@condition frightened} of you until the spell ends. The {@condition frightened} target can repeat the saving throw at the end of each of its turns, ending the effect on itself on a success.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st. The creatures must be within 30 feet of each other when you target them." + ] + } + }, + { + "name": "Ceremony", + "school": "abjuration", + "level": 1, + "ritual": true, + "casting_time": { + "value": 1, + "unit": "hour" + }, + "range": { + "type": "touch" + }, + "components": { + "verbal": true, + "somatic": true, + "material": true, + "materials_needed": "25 gp worth of powdered silver, which the spell consumes", + "materials_consumed": true, + "materials_cost": 2500 + }, + "durations": [ + { + "type": "instantaneous" + } + ], + "classes": ["cleric", "paladin"], + "sources": [ + { "source": "XGE", "page": 151 } + ], + "description": { + "entries": [ + "You perform a special religious ceremony that is infused with magic. When you cast the spell, choose one of the following rites, the target of which must be within 10 feet of you throughout the casting.", + "{@bold Atonement.} You touch one willing creature whose alignment has changed, and you make a DC 20 Wisdom ({@skill Insight}) check. On a successful check, you restore the target to its original alignment.", + "{@bold Bless Water.} You touch one vial of water and cause it to become holy water.", + "{@bold Coming of Age.} You touch one humanoid who is a young adult. For the next 24 hours, whenever the target makes an ability check, it can roll a d4 and add the number rolled to the ability check. A creature can benefit from this rite only once.", + "{@bold Dedication.} You touch one humanoid who wishes to be dedicated to your god's service. For the next 24 hours, whenever the target makes a saving throw, it can roll a d4 and add the number rolled to the save. A creature can benefit from this rite only once.", + "{@bold Funeral Rite.} You touch one corpse, and for the next 7 days, the target can't become undead by any means short of a wish spell.", + "{@bold Wedding.} You touch adult humanoids willing to be bonded together in marriage. For the next 7 days, each target gains a +2 bonus to AC while they are within 30 feet of each other. A creature can benefit from this rite again only if widowed." + ] + } + }, + { + "name": "Chaos Bolt", + "school": "evocation", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "attack_type": "ranged", + "damage_inflict": ["acid", "cold", "fire", "force", "lightning", "poison", "psychic", "thunder"], + "range": { + "type": "point", + "value": 120, + "unit": "feet" + }, + "components": { + "verbal": true, + "somatic": true, + "material": false + }, + "durations": [ + { + "type": "instantaneous" + } + ], + "classes": ["sorcerer"], + "sources": [ + { "source": "XGE", "page": 151 } + ], + "description": { + "entries": [ + "You hurl an undulating, warbling mass of chaotic energy at one creature in range. Make a ranged spell attack against the target. On a hit, the target takes {@damage 2d8} + {@damage 1d6} damage. Choose one of the d8s. The number rolled on that die determines the attack's damage type, as shown below.", + { + "table": { + "headers": ["d8", "Damage Type"], + "rows": [ + ["1", "Acid"], + ["2", "Cold"], + ["3", "Fire"], + ["4", "Force"], + ["5", "Lightning"], + ["6", "Poison"], + ["7", "Psychic"], + ["8", "Thunder"] + ] + } + }, + "If you roll the same number on both d8s, the chaotic energy leaps from the target to a different creature of your choice within 30 feet of it. Make a new attack roll against the new target, and make a new damage roll, which could cause the chaotic energy to leap again.", + "A creature can be targeted only once by each casting of this spell.", + "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, each target takes {@scaledamage 1d6|1-9|1d6} extra damage of the type rolled for each slot level above 1st." + ] + } + }, + { + "name": "Charm Person", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Chromatic Orb", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Color Spray", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Command", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Compelled Duel", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Comprehend Languages", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Create or Destroy Water", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Cure Wounds", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Detect Evil and Good", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Detect Magic", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Detect Poison and Disease", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Disguise Self", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Dissonant Whispers", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Divine Favor", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Earth Tremor", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Ensnaring Strike", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Entangle", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Expeditious Retreat", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Faerie Fire", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "False Life", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Feather Fall", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Find Familiar", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Fog Cloud", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Frost Fingers", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Gift of Alacrity", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Goodberry", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Grease", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Guiding Bolt", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Hail of Thorns", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Healing Word", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Hellish Rebuke", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Heroism", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Hex", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Hunter’s Mark", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Ice Knife", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Identify", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Illusory Script", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Inflict Wounds", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Jump", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Longstrider", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Mage Armor", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Magic Missile", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Magnify Gravity", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Protection from Evil and Good", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Purify Food and Drink", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Ray of Sickness", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Sanctuary", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Searing Smite", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Shield", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Shield of Faith", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Silent Image", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Silvery Barbs", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Sleep", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Snare", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Speak with Animals", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Tasha’s Caustic Brew", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Tasha’s Hideous Laughter", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Tenser’s Floating Disk", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Thunderous Smite", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Thunderwave", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Unseen Servant", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Witch Bolt", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Wrathful Smite", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + }, + { + "name": "Zephyr Strike", + "school": "", + "level": 1, + "ritual": false, + "casting_time": { + "value": 1, + "unit": "action" + }, + "range": { + "type": "point", + "value": 1, + "unit": "feet" + }, + "components": { + "verbal": false, + "somatic": false, + "material": false + }, + "durations": [ + { + "type": "timed", + "value": 1, + "unit": "minute" + } + ], + "classes": [], + "sources": [ + { "source": "", "page": 0 } + ], + "description": { + "entries": [ + + ] + } + } +] \ No newline at end of file diff --git a/service/src/db/mod.rs b/service/src/db/mod.rs index 8325a8c..4b69032 100644 --- a/service/src/db/mod.rs +++ b/service/src/db/mod.rs @@ -51,6 +51,6 @@ pub fn connection() -> Result { .map_err(|e| ServiceError::new(500, format!("Failed getting db connection: {}", e))) } -pub fn load_data() { - spells::load_data(); +pub fn load_data(data_dir_path: &str) { + spells::load_data(data_dir_path); } diff --git a/service/src/db/spells/mod.rs b/service/src/db/spells/mod.rs index 27ba8cf..4ab082a 100644 --- a/service/src/db/spells/mod.rs +++ b/service/src/db/spells/mod.rs @@ -2,46 +2,57 @@ mod model; mod routes; mod types; +use std::{fs::{metadata, File, read_dir}, path::Path, io::BufReader}; + +use log::{warn, trace}; pub use model::*; pub use types::*; pub use routes::init_routes; -pub fn load_data() { - let root_path = std::env::current_dir().unwrap(); - let files = [ - "cantrips.json", "level_1.json", "level_2.json", "level_3.json", "level_4.json", "level_5.json", "level_6.json", "level_7.json", "level_8.json", "level_9.json" - ]; - let mut spells: Vec = vec![]; - for file in files { - let mut data_path = std::path::PathBuf::from(&root_path); - data_path.push(format!("data/spells/{}", file)); - let path = data_path.to_str().unwrap(); - match std::fs::read_to_string(path) { - Ok(data) => { - log::debug!("Loading spells from {}", path); - match serde_json::from_str::(&data) { - Ok(json) => { - match serde_json::from_value::>(json) { - Ok(mut new_spells) => spells.append(&mut new_spells), - Err(err) => log::error!("Failed to parse spells data: {}", err) +pub fn load_data(data_dir_path: &str) { + if Path::new(data_dir_path).exists() { + let meta = metadata(data_dir_path).unwrap(); + if meta.is_dir() { + let spells_dir_path = format!("{}/spells", data_dir_path); + if Path::new(&spells_dir_path).exists() { + let meta = metadata(&spells_dir_path).unwrap(); + if meta.is_dir() { + for entry in read_dir(&spells_dir_path).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + if path.is_file() { + let file = File::open(path).unwrap(); + let reader = BufReader::new(file); + let result: Result, serde_json::Error> = serde_json::from_reader(reader); + match result { + Ok(spells) => { + for spell in spells { + let mut filters = QueryFilters::default(); + filters.by_name = Some(spell.name.clone()); + match QuerySpell::get_all(&filters, 100, 1) { + Ok(spells) => { + if spells.len() > 0 { + trace!("Spell '{}' already exists", spell.name); + continue; + } + }, + Err(err) => { + warn!("Error checking if spell '{}' exists: {}", spell.name, err); + continue; + } + }; + let spell = InsertSpell::insert(spell.into()).unwrap(); + trace!("Inserted spell: {}", spell.name); + } + }, + Err(err) => warn!("Error reading spells from file: {}", err) + }; } - }, - Err(err) => log::error!("Failed to parse spells data to value: {}", err) - }; - }, - Err(err) => log::error!("Failed to read from {}: {}", file, err) - }; - } - let count = QuerySpell::get_count(&QueryFilters::default()).unwrap(); - if count >= spells.len() as i64 { - log::warn!("Spell data is already loaded"); - return; - } - for spell in spells { - let spell_name = spell.name.clone(); - match InsertSpell::insert(spell.into()) { - Ok(_) => {}, - Err(err) => log::error!("Failed to insert '{}' spell: {}", spell_name, err) + } + } + } } + } else { + warn!("Data path '{}' does not exist, no data imported", data_dir_path); } } diff --git a/service/src/db/spells/model.rs b/service/src/db/spells/model.rs index f1317ff..027aaf6 100644 --- a/service/src/db/spells/model.rs +++ b/service/src/db/spells/model.rs @@ -4,7 +4,7 @@ use siren::ServiceError; use crate::db::{schema::spells::{self}, classes::AbilityType, conditions::ConditionType}; -use super::{SchoolType, CastingTime, CastingType, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description, DurationType}; +use super::{SchoolType, CastingTime, SpellAttackType, SpellDamageType, Range, Area, Components, Duration, Source, Description, DurationType, Effect}; #[derive(Queryable, QueryableByName, Serialize, Deserialize)] #[diesel(table_name = spells)] @@ -198,6 +198,8 @@ pub struct Spell { pub ritual: bool, pub casting_time: CastingTime, #[serde(skip_serializing_if = "Option::is_none")] + pub effect: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub saving_throw: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub attack_type: Option, @@ -232,7 +234,8 @@ impl From for Spell { school: SchoolType::Abjuration, level: 0, ritual: false, - casting_time: CastingTime { value: 0, casting_type: CastingType::Action }, + casting_time: CastingTime { value: 0, casting_type: "".to_string(), note: None }, + effect: None, saving_throw: None, attack_type: None, damage_inflict: None, diff --git a/service/src/db/spells/types.rs b/service/src/db/spells/types.rs index f82c4c3..eaeb94e 100644 --- a/service/src/db/spells/types.rs +++ b/service/src/db/spells/types.rs @@ -58,50 +58,10 @@ impl FromStr for SchoolType { pub struct CastingTime { pub value: i32, #[serde(rename = "unit")] - pub casting_type: CastingType + pub casting_type: String, + pub note: Option } -#[derive(Debug, Serialize, Deserialize)] -pub enum CastingType { - #[serde(rename = "action")] - Action, - #[serde(rename = "bonus")] - BonusAction, - #[serde(rename = "reaction")] - Reaction, - #[serde(rename = "minutes")] - Minutes, - #[serde(rename = "hours")] - Hours -} - -// impl CastingType { -// pub fn to_string(&self) -> String { -// match self { -// CastingType::Action => "action".to_string(), -// CastingType::BonusAction => "bonus".to_string(), -// CastingType::Reaction => "reaction".to_string(), -// CastingType::Minutes => "minutes".to_string(), -// CastingType::Hours => "hours".to_string() -// } -// } -// } - -// impl FromStr for CastingType { -// type Err = (); - -// fn from_str(s: &str) -> Result { -// match s { -// "action" => Ok(CastingType::Action), -// "bonus" => Ok(CastingType::BonusAction), -// "reaction" => Ok(CastingType::Reaction), -// "minutes" => Ok(CastingType::Minutes), -// "hours" => Ok(CastingType::Hours), -// _ => Err(()) -// } -// } -// } - #[derive(Debug, Serialize, Deserialize)] pub enum SpellAttackType { #[serde(rename = "melee")] @@ -303,8 +263,15 @@ pub struct Description { #[derive(Debug)] pub struct Entry { - pub entry_type: String, - pub items: Vec + pub text: Option>, + pub list: Option>, + pub table: Option +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct EntryTable { + pub headers: Vec, + pub rows: Vec> } impl<'de> Deserialize<'de> for Entry { @@ -312,36 +279,82 @@ impl<'de> Deserialize<'de> for Entry { let value = serde_json::Value::deserialize(deserializer)?; match value { serde_json::Value::String(s) => Ok(Entry { - entry_type: "string".to_string(), - items: vec![s] + text: Some(vec![s]), + list: None, + table: None, }), serde_json::Value::Object(o) => { - let entry_type = match o.get("type") { - Some(t) => match t.as_str() { - Some(s) => s.to_string(), - None => return Err(serde::de::Error::custom("Invalid entry type")) - }, - None => return Err(serde::de::Error::custom("Missing entry type")) - }; - let items = match o.get("items") { + let list = match o.get("list") { Some(i) => match i.as_array() { Some(a) => { - let mut items = Vec::new(); + let mut list = Vec::new(); for item in a { match item.as_str() { - Some(s) => items.push(s.to_string()), - None => return Err(serde::de::Error::custom("Invalid entry item")) + Some(s) => list.push(s.to_string()), + None => return Err(serde::de::Error::custom("Invalid entry list item")) } } - items + Some(list) }, - None => return Err(serde::de::Error::custom("Invalid entry items")) + None => return Err(serde::de::Error::custom("Invalid entry list items")) }, - None => return Err(serde::de::Error::custom("Missing entry items")) + None => None + }; + let table = match o.get("table") { + Some(t) => match t.as_object() { + Some(o) => { + let mut headers = Vec::new(); + let mut rows = Vec::new(); + match o.get("headers") { + Some(c) => match c.as_array() { + Some(a) => { + for item in a { + match item.as_str() { + Some(s) => headers.push(s.to_string()), + None => return Err(serde::de::Error::custom("Invalid entry table header")) + } + } + }, + None => return Err(serde::de::Error::custom("Invalid entry table headers")) + }, + None => return Err(serde::de::Error::custom("Missing entry table headers")) + }; + match o.get("rows") { + Some(r) => match r.as_array() { + Some(a) => { + for row in a { + match row.as_array() { + Some(a) => { + let mut row = Vec::new(); + for item in a { + match item.as_str() { + Some(s) => row.push(s.to_string()), + None => return Err(serde::de::Error::custom("Invalid entry table row item")) + } + } + rows.push(row); + }, + None => return Err(serde::de::Error::custom("Invalid entry table row")) + } + } + }, + None => return Err(serde::de::Error::custom("Invalid entry table rows")) + }, + None => return Err(serde::de::Error::custom("Missing entry table rows")) + }; + Some(EntryTable { + headers, + rows + }) + }, + None => return Err(serde::de::Error::custom("Invalid entry table")) + }, + None => None }; Ok(Entry { - entry_type, - items + text: None, + list, + table }) }, _ => Err(serde::de::Error::custom("Invalid entry")) @@ -351,15 +364,17 @@ impl<'de> Deserialize<'de> for Entry { impl Serialize for Entry { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - match self.entry_type.as_str() { - "string" => serializer.serialize_str(&self.items[0]), - _ => { - let mut map = serializer.serialize_map(Some(2))?; - map.serialize_entry("type", &self.entry_type)?; - map.serialize_entry("items", &self.items)?; - map.end() - } + let mut map = serializer.serialize_map(Some(1))?; + if let Some(text) = &self.text { + map.serialize_entry("text", text)?; } + if let Some(list) = &self.list { + map.serialize_entry("list", list)?; + } + if let Some(table) = &self.table { + map.serialize_entry("table", table)?; + } + map.end() } } @@ -374,4 +389,9 @@ pub struct Components { pub materials_cost: Option, #[serde(skip_serializing_if = "Option::is_none")] pub materials_consumed: Option -} \ No newline at end of file +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Effect { + pub effect_type: Option +} diff --git a/service/src/main.rs b/service/src/main.rs index bae3589..53e0402 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -8,7 +8,7 @@ use actix_cors::Cors; use actix_web::{HttpServer, App}; use dotenv::dotenv; -use log::{error, info}; +use log::{error, info, warn}; mod db; @@ -17,7 +17,10 @@ async fn main() -> std::io::Result<()> { dotenv().ok(); env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", "warn,siren=info")); db::init(); - db::load_data(); + match env::var("DATA_DIR_PATH") { + Ok(data_dir_path) => db::load_data(&data_dir_path), + Err(err) => warn!("Unable to load initial database data: {}", err) + }; let host = env::var("SERVICE_HOST").unwrap_or("localhost".to_string()); let port = env::var("SERVICE_PORT").unwrap_or("5000".to_string()); From 5915a29dd5d16b113cbe04644cdc9e26a247d298 Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Thu, 5 Oct 2023 14:32:50 -0400 Subject: [PATCH 3/4] Removed data directory --- service/data/layout.json | 48 - service/data/spells/cantrips.json | 1908 ------------------- service/data/spells/level_1.json | 2823 ----------------------------- 3 files changed, 4779 deletions(-) delete mode 100644 service/data/layout.json delete mode 100644 service/data/spells/cantrips.json delete mode 100644 service/data/spells/level_1.json diff --git a/service/data/layout.json b/service/data/layout.json deleted file mode 100644 index 801cdc8..0000000 --- a/service/data/layout.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "saving_throw": [], - "attack_type": [], - "damage_inflict": [], - "damage_resist": [], - "conditions": [], - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "area": { - "type": "cube", - "size": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false, - "materials_needed": "", - "materials_cost": 0, - "materials_consumed": false - }, - "durations": [ - { - "type": "instantaneous", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ { "source": "", "page": 0 } ], - "tags": [], - "description": { - "entries": [ - - ] - } -} \ No newline at end of file diff --git a/service/data/spells/cantrips.json b/service/data/spells/cantrips.json deleted file mode 100644 index fd2ee5a..0000000 --- a/service/data/spells/cantrips.json +++ /dev/null @@ -1,1908 +0,0 @@ -[ - { - "name": "Acid Splash", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "saving_throw": [ - "dexterity" - ], - "damage_inflict": [ - "acid" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 211 }, - { "source": "SRD", "page": 114 } - ], - "description": { - "entries": [ - "You hurl a bubble of acid. Choose one creature within range, or choose two creatures within range that are within 5 feet of each other. A target must succeed on a Dexterity saving throw or take {@damage 1d6} acid damage.", - "This spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Blade Ward", - "school": "abjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "self" - }, - "damage_resistance": [ - "bludgeoning", - "piercing", - "slashing" - ], - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "round" - } - ], - "classes": ["bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 218 } - ], - "description": { - "entries": [ - "You extend your hand and trace a sigil of warding in the air. Until the end of your next turn, you have resistance against bludgeoning, piercing, and slashing damage dealt by weapon attacks." - ] - } - }, - { - "name": "Booming Blade", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "touch" - }, - "area": { - "type": "sphere", - "value": 5, - "unit": "feet" - }, - "damage_inflict": [ - "thunder" - ], - "attack_type": "melee", - "components": { - "verbal": false, - "somatic": true, - "material": false, - "materials_needed": "a melee weapon worth at least 1 sp" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "round" - } - ], - "classes": ["sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "SCAG", "page": 142 }, - { "source": "TCE", "page": 106 } - ], - "description": { - "entries": [ - "You brandish the weapon used in the spell's casting and make a melee attack with it against one creature within 5 feet of you. On a hit, the target suffers the weapon attack's normal effects and then becomes sheathed in booming energy until the start of your next turn. If the target willingly moves 5 feet or more before then, the target takes 1d8 thunder damage, and the spell ends.", - "This spell's damage increases when you reach certain levels. At 5th level, the melee attack deals an extra {@damage 1d8} thunder damage to the target on a hit, and the damage the target takes for moving increases to {@damage 2d8}. Both damage rolls increase by 1d8 at 11th level ({@damage 2d8} and {@damage 3d8}) and again at 17th level ({@damage 3d8} and {@damage 4d8})." - ] - } - }, - { - "name": "Chill Touch", - "school": "necromancy", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "damage_inflict": [ - "necrotic" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "round" - } - ], - "classes": ["sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 221 }, - { "source": "SRD", "page": 124 } - ], - "description": { - "entries": [ - "You create a ghostly, skeletal hand in the space of a creature within range. Make a ranged spell attack against the creature to assail it with the chill of the grave. On a hit, the target takes {@damage 1d8} necrotic damage, and it can't regain hit points until the start of your next turn. Until then, the hand clings to the target.", - "If you hit an undead target, it also has disadvantage on attack rolls against you until the end of your next turn.", - "This spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Control Flames", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "area": { - "type": "cube", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - }, - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["druid", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 16 }, - { "source": "XGE", "page": 152 } - ], - "description": { - "entries": [ - "You choose nonmagical flame that you can see within range and that fits within a 5-foot cube. You affect it in one of the following ways:", - { - "list": [ - "You instantaneously expand the flame 5 feet in one direction, provided that wood or other fuel is present in the new location.", - "You instantaneously extinguish the flames within the cube.", - "You double or halve the area of bright light and dim light cast by the flame, change its color, or both. The change lasts for 1 hour.", - "You cause simple shapes—such as the vague form of a creature, an inanimate object, or a location—to appear within the flames and animate as you like. The shapes last for 1 hour." - ] - }, - "If you cast this spell multiple times, you can have up to three non-instantaneous effects created by it active at a time, and you can dismiss such an effect as an action." - ] - } - }, - { - "name": "Create Bonfire", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "area": { - "type": "cube", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["artificer", "druid", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "EEPC", "page": 16 }, - { "source": "XGE", "page": 152 } - ], - "description": { - "entries": [ - "You create a bonfire on ground that you can see within range. Until the spell ends, the magic bonfire fills a 5-foot cube. Any creature in the bonfire's space when you cast the spell must succeed on a Dexterity saving throw or take {@damage 1d8} fire damage. A creature must also make the saving throw when it moves into the bonfire's space for the first time on a turn or ends its turn there.", - "The bonfire ignites flammable objects in its area that aren't being worn or carried.", - "The spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Dancing Lights", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a bit of phosphorus or wychwood, or a glowworm" - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["artificer", "bard", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 230 }, - { "source": "SRD", "page": 133 } - ], - "description": { - "entries": [ - "You create up to four torch-valued lights within range, making them appear as torches, lanterns, or glowing orbs that hover in the air for the duration. You can also combine the four lights into one glowing vaguely humanoid form of Medium value. Whichever form you choose, each light sheds dim light in a 10-foot radius.", - "As a bonus action on your turn, you can move the lights up to 60 feet to a new spot within range. A light must be within 20 feet of another light created by this spell, and a light winks out if it exceeds the spell's range." - ] - } - }, - { - "name": "Druidcraft", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["druid"], - "sources": [ - { "source": "PHB", "page": 236 }, - { "source": "SRD", "page": 138 } - ], - "description": { - "entries": [ - "Whispering to the spirits of nature, you create one of the following effects within range:", - { - "list": [ - "You create a tiny, harmless sensory effect that predicts what the weather will be at your location for the next 24 hours. The effect might manifest as a golden orb for clear skies, a cloud for rain, falling snowflakes for snow, and so on. This effect persists for 1 round.", - "You instantly make a flower blossom, a seed pod open, or a leaf bud bloom.", - "You create an instantaneous, harmless sensory effect, such as falling leaves, a puff of wind, the sound of a small animal, or the faint odor of skunk. The effect must fit in a 5-foot cube.", - "You instantly light or snuff out a candle, a torch, or a small campfire." - ] - } - ] - } - }, - { - "name": "Eldritch Blast", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "damage_inflict": [ - "force" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["warlock"], - "sources": [ - { "source": "PHB", "page": 237 }, - { "source": "SRD", "page": 139 } - ], - "description": { - "entries": [ - "A beam of crackling energy streaks toward a creature within range. Make a ranged spell attack against the target. On a hit, the target takes {@damage 1d10} force damage.", - "The spell creates more than one beam when you reach higher levels: two beams at 5th level, three beams at 11th level, and four beams at 17th level. You can direct the beams at the same target or at different ones. Make a separate attack roll for each beam." - ] - } - }, - { - "name": "Encode Thoughts", - "school": "enchantment", - "level": 0, - "ritual": true, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "self" - }, - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 8, - "unit": "hours" - } - ], - "classes": ["wizard"], - "sources": [ - { "source": "GGR", "page": 47 } - ], - "description": { - "entries": [ - "Putting a finger to your head, you pull a memory, an idea, or a message from your mind and transform it into a tangible string of glowing energy called a thought strand, which persists for the duration or until you cast this spell again. The thought strand appears in an unoccupied space within 5 feet of you as a Tiny, weightless, semisolid object that can be held and carried like a ribbon. It is otherwise stationary.", - "If you cast this spell while concentrating on a spell or an ability that allows you to read or manipulate the thoughts of others (such as {@spell detect thoughts} or {@spell modify memory}), you can transform the thoughts or memories you read, rather than your own, into a thought strand.", - "Casting this spell while holding a thought strand allows you to instantly receive whatever memory, idea, or message the thought strand contains. (Casting {@spell detect thoughts} on the strand has the same effect.)" - ] - } - }, - { - "name": "Fire Bolt", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "damage_inflict": [ - "fire" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 242 }, - { "source": "SRD", "page": 144 } - ], - "description": { - "entries": [ - "You hurl a mote of fire at a creature or object within range. Make a ranged spell attack against the target. On a hit, the target takes {@damage 1d10} fire damage. A flammable object hit by this spell ignites if it isn't being worn or carried.", - "This spell's damage increases by {@damage 1d10} when you reach 5th level ({@damage 2d10}), 11th level ({@damage 3d10}), and 17th level ({@damage 4d10})." - ] - } - }, - { - "name": "Friends", - "school": "enchantment", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "self" - }, - "components": { - "verbal": false, - "somatic": true, - "material": true, - "materials_needed": "a small value of makeup applied to the face as this spell is cast" - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 244 }, - { "source": "SRD", "page": 145 } - ], - "description": { - "entries": [ - "For the duration, you have advantage on all Charisma checks directed at one creature of your choice that isn't hostile toward you. When the spell ends, the creature realizes that you used magic to influence its mood and becomes hostile toward you. A creature prone to violence might attack you. Another creature might seek retribution in other ways (at the DM's discretion), depending on the nature of your interaction with it." - ] - } - }, - { - "name": "Frostbite", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "saving_throw": [ - "constitution" - ], - "damage_inflict": [ - "cold" - ], - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "druid", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "EEPC", "page": 18 }, - { "source": "XGE", "page": 155 } - ], - "description": { - "entries": [ - "You cause numbing frost to form on one creature that you can see within range. The target must make a Constitution saving throw. On a failed save, the target takes {@damage 1d6} cold damage, and it has disadvantage on the next weapon attack roll it makes before the end of its next turn.", - "The spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Green-Flame Blade", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "self" - }, - "area": { - "type": "sphere", - "value": 5, - "unit": "feet" - }, - "damage_inflict": [ - "fire" - ], - "attack_type": "melee", - "components": { - "verbal": false, - "somatic": true, - "material": true, - "materials_needed": "a melee weapon worth at least 1 sp" - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "SCAG", "page": 142 }, - { "source": "TCE", "page": 106 } - ], - "description": { - "entries": [ - "You brandish the weapon used in the spell's casting and make a melee attack with it against one creature within 5 feet of you. On a hit, the target suffers the weapon attack's normal effects, and you can cause green fire to leap from the target to a different creature of your choice that you can see within 5 feet of it. The second creature takes fire damage equal to your spellcasting ability modifier.", - "This spell's damage increases when you reach certain levels. At 5th level, the melee attack deals an extra {@damage 1d8} fire damage to the target on a hit, and the fire damage to the second creature increases to {@damage 1d8} + your spellcasting ability modifier. Both damage rolls increase by {@damage 1d8} at 11th level ({@damage 2d8} and {@damage 2d8}) and 17th level ({@damage 3d8} and {@damage 3d8})." - ] - } - }, - { - "name": "Guidance", - "school": "divination", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["artificer", "cleric", "druid"], - "sources": [ - { "source": "PHB", "page": 248 }, - { "source": "SRD", "page": 147 } - ], - "description": { - "entries": [ - "You touch one willing creature. Once before the spell ends, the target can roll a {@dice d4} and add the number rolled to one ability check of its choice. It can roll the die before or after making the ability check. The spell then ends." - ] - } - }, - { - "name": "Gust", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["druid", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 18 }, - { "source": "XGE", "page": 157 } - ], - "description": { - "entries": [ - "You seize the air and compel it to create one of the following effects at a point you can see within range:", - { - "list": [ - "One Medium or smaller creature that you choose must succeed on a Strength saving throw or be pushed up to 5 feet away from you.", - "You create a small blast of air capable of moving one object that is neither held nor carried and that weighs no more than 5 pounds. The object is pushed up to 10 feet away from you. It isn't pushed with enough force to cause damage.", - "You create a harmless sensory effect using air, such as causing leaves to rustle, wind to slam shutters shut, or your clothing to ripple in a breeze." - ] - } - ] - } - }, - { - "name": "Infestation", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "saving_throw": [ - "constitution" - ], - "damage_inflict": [ - "poison" - ], - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a living flea" - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["druid", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "XGE", "page": 158 } - ], - "description": { - "entries": [ - "You cause a cloud of mites, fleas, and other parasites to appear momentarily on one creature you can see within range. The target must succeed on a Constitution saving throw, or it takes {@damage 1d6} poison damage and moves 5 feet in a random direction if it can move and its speed is at least 5 feet. Roll a {@dice d4} for the direction: 1 north, 2 south, 3 east, or 4 west. This movement doesn't provoke opportunity attacks, and if the direction rolled is blocked, the target doesn't move.", - "The spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Light", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "touch" - }, - "area": { - "type": "sphere", - "value": 20, - "unit": "feet" - }, - "saving_throw": [ - "dexterity" - ], - "components": { - "verbal": true, - "somatic": false, - "material": true, - "materials_needed": "a firefly or phosphorescent moss" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["artificer", "bard", "cleric", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 255 }, - { "source": "SRD", "page": 150 } - ], - "description": { - "entries": [ - "You touch one object that is no larger than 10 feet in any dimension. Until the spell ends, the object sheds bright light in a 20-foot radius and dim light for an additional 20 feet. The light can be colored as you like. Completely covering the object with something opaque blocks the light. The spell ends if you cast it again or dismiss it as an action.", - "If you target an object held or worn by a hostile creature, that creature must succeed on a Dexterity saving throw to avoid the spell." - ] - } - }, - { - "name": "Lightning Lure", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "self", - "value": 15, - "unit": "feet" - }, - "saving_throw": [ - "strength" - ], - "damage_inflict": [ - "lightning" - ], - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "SCAG", "page": 143 }, - { "source": "TCE", "page": 107 } - ], - "description": { - "entries": [ - "You create a lash of lightning energy that strikes at one creature of your choice that you can see within range. The target must succeed on a Strength saving throw or be pulled up to 10 feet in a straight line toward you and then take {@damage 1d8} lightning damage if it is within 5 feet of you.", - "This spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Mage Hand", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": ["artificer", "bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 256 }, - { "source": "SRD", "page": 151 } - ], - "description": { - "entries": [ - "A spectral, floating hand appears at a point you choose within range. The hand lasts for the duration or until you dismiss it as an action. The hand vanishes if it is ever more than 30 feet away from you or if you cast this spell again.", - "You can use your action to control the hand. You can use the hand to manipulate an object, open an unlocked door or container, stow or retrieve an item from an open container, or pour the contents out of a vial. You can move the hand up to 30 feet each time you use it.", - "The hand can't attack, activate magic items, or carry more than 10 pounds." - ] - } - }, - { - "name": "Magic Stone", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "bonus" - }, - "range": { - "type": "touch" - }, - "damage_inflict": [ - "bludgeoning" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": ["artificer", "druid", "warlock"], - "sources": [ - { "source": "EEPC", "page": 160 } - ], - "description": { - "entries": [ - "You touch one to three pebbles and imbue them with magic. You or someone else can make a ranged spell attack with one of the pebbles by throwing it or hurling it with a sling. If thrown, it has a range of 60 feet. If someone else attacks with the pebble, that attacker adds your spellcasting ability modifier, not the attacker's, to the attack roll. On a hit, the target takes bludgeoning damage equal to {@damage 1d6} + your spellcasting ability modifier. Hit or miss, the spell then ends on the stone.", - "If you cast this spell again, the spell ends early on any pebbles still affected by it." - ] - } - }, - { - "name": "Mending", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "minute" - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "two lodestones" - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "bard", "cleric", "druid", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 259 }, - { "source": "SRD", "page": 152 } - ], - "description": { - "entries": [ - "This spell repairs a single break or tear in an object you touch, such as a broken chain link, two halves of a broken key, a torn cloak, or a leaking wineskin. As long as the break or tear is no larger than 1 foot in any dimension, you mend it, leaving no trace of the former damage.", - "This spell can physically repair a magic item or construct, but the spell can't restore magic to such an object." - ] - } - }, - { - "name": "Message", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a short piece of copper wire" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "round" - } - ], - "classes": ["artificer", "bard", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 259 }, - { "source": "SRD", "page": 152 } - ], - "description": { - "entries": [ - "You point your finger toward a creature within range and whisper a message. The target (and only the target) hears the message and can reply in a whisper that only you can hear.", - "You can cast this spell through solid objects if you are familiar with the target and know it is beyond the barrier. Magical silence, 1 foot of stone, 1 inch of common metal, a thin sheet of lead, or 3 feet of wood blocks the spell. The spell doesn't have to follow a straight line and can travel freely around corners or through openings." - ] - } - }, - { - "name": "Mind Sliver", - "school": "enchantment", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "saving_throw": [ - "intelligence" - ], - "damage_inflict": [ - "psychic" - ], - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "TCE", "page": 108 } - ], - "description": { - "entries": [ - "You drive a disorienting spike of psychic energy into the mind of one creature you can see within range. The target must succeed on an Intelligence saving throw or take {@damage 1d6} psychic damage and subtract {@damage 1d4} from the next saving throw it makes before the end of your next turn.", - "This spell's damage increases by {@damage 1d6} when you reach certain levels: 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Minor Illusion", - "school": "illusion", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": true, - "material": true, - "materials_needed": "a bit of fleece" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": ["bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 260 }, - { "source": "SRD", "page": 153 } - ], - "description": { - "entries": [ - "You create a sound or an image of an object within range that lasts for the duration. The illusion also ends if you dismiss it as an action or cast this spell again.", - "If you create a sound, its volume can range from a whisper to a scream. It can be your voice, someone else's voice, a lion's roar, a beating of drums, or any other sound you choose. The sound continues unabated throughout the duration, or you can make discrete sounds at different times before the spell ends.", - "If you create an image of an object--such as a chair, muddy footprints, or a small chest--it must be no larger than a 5-foot cube. The image can't create sound, light, smell, or any other sensory effect. Physical interaction with the image reveals it to be an illusion, because things can pass through it.", - "If a creature uses its action to examine the sound or image, the creature can determine that it is an illusion with a successful Intelligence ({@ability Investigation}) check against your spell save DC. If a creature discerns the illusion for what it is, the illusion becomes faint to the creature." - ] - } - }, - { - "name": "Mold Earth", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "area": { - "type": "cube", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - }, - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["druid", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 162 } - ], - "description": { - "entries": [ - "You choose a portion of dirt or stone that you can see within range and that fits within a 5-foot cube. You manipulate it in one of the following ways:", - { - "list": [ - "If you target an area of loose earth, you can instantaneously excavate it, move it along the ground, and deposit it up to 5 feet away. This movement doesn't have enough force to cause damage.", - "You cause shapes, colors, or both to appear on the dirt or stone, spelling out words, creating images, or shaping patterns. The changes last for 1 hour.", - "If the dirt or stone you target is on the ground, you cause it to become difficult terrain. Alternatively, you can cause the ground to become normal terrain if it is already difficult terrain. This change lasts for 1 hour." - ] - }, - "If you cast this spell multiple times, you can have no more than two of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action." - ] - } - }, - { - "name": "Poison Spray", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 10, - "unit": "feet" - }, - "saving_throw": [ - "constitution" - ], - "damage_inflict": [ - "poison" - ], - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "attack_type": "ranged", - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "druid", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 266 }, - { "source": "SRD", "page": 155 } - ], - "description": { - "entries": [ - "You extend your hand toward a creature you can see within range and project a puff of noxious gas from your palm. The creature must succeed on a Constitution saving throw or take {@damage 1d12} poison damage.", - "This spell's damage increases by {@damage 1d12} when you reach 5th level ({@damage 2d12}), 11th level ({@damage 3d12}), and 17th level ({@damage 4d12})." - ] - } - }, - { - "name": "Prestidigitation", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "range": { - "type": "point", - "value": 10, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["artificer", "bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 267 }, - { "source": "SRD", "page": 156 } - ], - "description": { - "entries": [ - "This spell is a minor magical trick that novice spellcasters use for practice. You create one of the following magical effects within range:", - { - "list": [ - "You create an instantaneous, harmless sensory effect, such as a shower of sparks, a puff of wind, faint musical notes, or an odd odor.", - "You instantaneously light or snuff out a candle, a torch, or a small campfire.", - "You instantaneously clean or soil an object no larger than 1 cubic foot.", - "You chill, warm, or flavor up to 1 cubic foot of nonliving material for 1 hour.", - "You make a color, a small mark, or a symbol appear on an object or a surface for 1 hour.", - "You create a nonmagical trinket or an illusory image that can fit in your hand and that lasts until the end of your next turn." - ] - }, - "If you cast this spell multiple times, you can have up to three of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action." - ] - } - }, - { - "name": "Primal Savagery", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "range": { - "type": "self" - }, - "damage_inflict": [ - "acid" - ], - "attack_type": "melee", - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["druid"], - "sources": [ - { "source": "XGE", "page": 163 } - ], - "description": { - "entries": [ - "You channel primal magic to cause your teeth or fingernails to sharpen, ready to deliver a corrosive attack. Make a melee spell attack against one creature within 5 feet of you. On a hit, the target takes {@damage 1d10} acid damage. After you make the attack, your teeth or fingernails return to normal.", - "The spell's damage increases by {@damage 1d10} when you reach 5th level ({@damage 2d10}), 11th level ({@damage 3d10}), and 17th level ({@damage 4d10})." - ] - } - }, - { - "name": "Produce Flame", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "range": { - "type": "self" - }, - "damage_inflict": [ - "fire" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 10, - "unit": "minutes" - } - ], - "classes": ["druid"], - "sources": [ - { "source": "PHB", "page": 269 }, - { "source": "SRD", "page": 157 } - ], - "description": { - "entries": [ - "A flickering flame appears in your hand. The flame remains there for the duration and harms neither you nor your equipment. The flame sheds bright light in a 10-foot radius and dim light for an additional 10 feet. The spell ends if you dismiss it as an action or if you cast it again.", - "You can also attack with the flame, although doing so ends the spell. When you cast this spell, or as an action on a later turn, you can hurl the flame at a creature within 30 feet of you. Make a ranged spell attack. On a hit, the target takes {@damage 1d8} fire damage.", - "This spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Ray of Frost", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "damage_inflict": [ - "cold" - ], - "attack_type": "ranged", - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 271 }, - { "source": "SRD", "page": 158 } - ], - "description": { - "entries": [ - "A frigid beam of blue-white light streaks toward a creature within range. Make a ranged spell attack against the target. On a hit, it takes {@damage 1d8} cold damage, and its speed is reduced by 10 feet until the start of your next turn.", - "The spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Resistance", - "school": "abjuration", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a miniature cloak" - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "round" - } - ], - "classes": ["artificer", "cleric", "druid"], - "sources": [ - { "source": "PHB", "page": 272 }, - { "source": "SRD", "page": 159 } - ], - "description": { - "entries": [ - "You touch one willing creature. Once before the spell ends, the target can roll a {@dice d4} and add the number rolled to one saving throw of its choice. It can roll the die before or after making the saving throw. The spell then ends." - ] - } - }, - { - "name": "Sacred Flame", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "saving_throw": [ - "dexterity" - ], - "damage_inflict": [ - "radiant" - ], - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["cleric"], - "sources": [ - { "source": "PHB", "page": 272 }, - { "source": "SRD", "page": 159 } - ], - "description": { - "entries": [ - "Flame-like radiance descends on a creature that you can see within range. The target must succeed on a Dexterity saving throw or take {@damage 1d8} radiant damage. The target gains no benefit from cover for this saving throw.", - "The spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Sapping Sting", - "school": "necromancy", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "necrotic" - ], - "saving_throw": [ - "constitution" - ], - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["wizard"], - "sources": [ - { "source": "EGW", "page": 189 } - ], - "description": { - "entries": [ - "You sap the vitality of one creature you can see in range. The target must succeed on a Constitution saving throw or take {@damage 1d4} necrotic damage and fall {@condition prone}.", - "This spell's damage increases by {@damage 1d4} when you reach 5th level ({@damage 2d4}), 11th level ({@damage 3d4}), and 17th level ({@damage 4d4})." - ] - } - }, - { - "name": "Shape Water", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "area": { - "type": "cube", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - }, - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["druid", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 164 } - ], - "description": { - "entries": [ - "You choose an area of water that you can see within range and that fits within a 5-foot cube. You manipulate it in one of the following ways:", - { - "list": [ - "You instantaneously move or otherwise change the flow of the water as you direct, up to 5 feet in any direction. This movement doesn't have enough force to cause damage.", - "You cause the water to form into simple shapes and animate at your direction. This change lasts for 1 hour.", - "You change the water's color or opacity. The water must be changed in the same way throughout. This change lasts for 1 hour.", - "You freeze the water, provided that there are no creatures in it. The water unfreezes in 1 hour." - ] - }, - "If you cast this spell multiple times, you can have no more than two of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action." - ] - } - }, - { - "name": "Shillelagh", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "bonus" - }, - "range": { - "type": "touch" - }, - "damage_inflict": [ - "bludgeoning" - ], - "attack_type": "melee", - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "mistletoe, a shamrock leaf, and a club or quarterstaff" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": ["druid"], - "sources": [ - { "source": "PHB", "page": 275 }, - { "source": "SRD", "page": 160 } - ], - "description": { - "entries": [ - "The wood of a club or quarterstaff you are holding is imbued with nature's power. For the duration, you can use your spellcasting ability instead of Strength for the attack and damage rolls of melee attacks using that weapon, and the weapon's damage die becomes a {@dice d8}. The weapon also becomes magical, if it isn't already. The spell ends if you cast it again or if you let go of the weapon." - ] - } - }, - { - "name": "Shocking Grasp", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "lightning" - ], - "attack_type": "melee", - "range": { - "type": "self" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "wizard"], - "sources": [ - { "source": "PHB", "page": 275 }, - { "source": "SRD", "page": 160 } - ], - "description": { - "entries": [ - "Lightning springs from your hand to deliver a shock to a creature you try to touch. Make a melee spell attack against the target. You have advantage on the attack roll if the target is wearing armor made of metal. On a hit, the target takes {@damage 1d8} lightning damage, and it can't take reactions until the start of its next turn.", - "The spell's damage increases by {@damage 1d8} when you reach 5th level ({@damage 2d8}), 11th level ({@damage 3d8}), and 17th level ({@damage 4d8})." - ] - } - }, - { - "name": "Spare the Dying", - "school": "necromancy", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "cleric"], - "sources": [ - { "source": "PHB", "page": 277 }, - { "source": "SRD", "page": 161 } - ], - "description": { - "entries": [ - "You touch a living creature that has 0 hit points. The creature becomes stable. This spell has no effect on undead or constructs." - ] - } - }, - { - "name": "Sword Burst", - "school": "conjuration", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "force" - ], - "saving_throw": [ - "dexterity" - ], - "range": { - "type": "self", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "SCAG", "page": 143 } - ], - "description": { - "entries": [ - "You create a momentary circle of spectral blades that sweep around you. Each creature within range, other than you, must succeed on a Dexterity saving throw or take {@damage 1d6} force damage.", - "This spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Thaumaturgy", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": ["cleric"], - "sources": [ - { "source": "PHB", "page": 282 }, - { "source": "SRD", "page": 162 } - ], - "description": { - "entries": [ - "You manifest a minor wonder, a sign of supernatural power, within range. You create one of the following magical effects within range:", - { - "list": [ - "Your voice booms up to three times as loud as normal for 1 minute.", - "You cause flames to flicker, brighten, dim, or change color for 1 minute.", - "You cause harmless tremors in the ground for 1 minute.", - "You create an instantaneous sound that originates from a point of your choice within range, such as a rumble of thunder, the cry of a raven, or ominous whispers.", - "You instantaneously cause an unlocked door or window to fly open or slam shut.", - "You alter the appearance of your eyes for 1 minute." - ] - }, - "If you cast this spell multiple times, you can have up to three of its 1-minute effects active at a time, and you can dismiss such an effect as an action." - ] - } - }, - { - "name": "Thorn Whip", - "school": "transmutation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "piercing" - ], - "attack_type": "melee", - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "the stem of a plant with thorns" - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "druid"], - "sources": [ - { "source": "PHB", "page": 282 }, - { "source": "SRD", "page": 162 } - ], - "description": { - "entries": [ - "You create a long, vine-like whip covered in thorns that lashes out at your command toward a creature in range. Make a melee spell attack against the target. If the attack hits, the creature takes {@damage 1d6} piercing damage, and if the creature is Large or smaller, you pull the creature up to 10 feet closer to you.", - "The spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Thunderclap", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "thunder" - ], - "saving_throw": [ - "constitution" - ], - "range": { - "type": "point", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "bard", "druid", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "EEPC", "page": 168 } - ], - "description": { - "entries": [ - "You create a burst of thunderous sound that can be heard up to 100 feet away. Each creature within range, other than you, must succeed on a Constitution saving throw or take {@damage 1d6} thunder damage.", - "The spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - }, - { - "name": "Toll the Dead", - "school": "necromancy", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "necrotic" - ], - "saving_throw": [ - "wisdom" - ], - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["cleric", "warlock", "wizard"], - "sources": [ - { "source": "XGE", "page": 169 } - ], - "description": { - "entries": [ - "You point at one creature you can see within range, and the sound of a dolorous bell fills the air around it for a moment. The target must succeed on a Wisdom saving throw or take {@damage 1d8} necrotic damage. If the target is missing any of its hit points, it instead takes {@damage 1d12} necrotic damage.", - "The spell's damage increases by one die when you reach 5th level ({@damage 2d8} or {@damage 2d12}), 11th level ({@damage 3d8} or {@damage 3d12}), and 17th level ({@damage 4d8} or {@damage 4d12})." - ] - } - }, - { - "name": "True Strike", - "school": "divination", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "round" - } - ], - "classes": ["bard", "sorcerer", "warlock", "wizard"], - "sources": [ - { "source": "PHB", "page": 284 }, - { "source": "SRD", "page": 163 } - ], - "description": { - "entries": [ - "You extend your hand and point a finger at a target in range. Your magic grants you a brief insight into the target's defenses. On your next turn, you gain advantage on your first attack roll against the target, provided that this spell hasn't ended." - ] - } - }, - { - "name": "Vicious Mockery", - "school": "enchantment", - "level": 0, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": [ - "psychic" - ], - "saving_throw": [ - "wisdom" - ], - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["bard"], - "sources": [ - { "source": "PHB", "page": 285 }, - { "source": "SRD", "page": 163 } - ], - "description": { - "entries": [ - "You unleash a string of insults laced with subtle enchantments at a creature you can see within range. If the target can hear you (though it need not understand you), it must succeed on a Wisdom saving throw or take {@damage 1d4} psychic damage and have disadvantage on the next attack roll it makes before the end of its next turn.", - "This spell's damage increases by {@damage 1d4} when you reach 5th level ({@damage 2d4}), 11th level ({@damage 3d4}), and 17th level ({@damage 4d4})." - ] - } - }, - { - "name": "Word of Radiance", - "school": "evocation", - "level": 0, - "ritual": false, - "casting_time": { - "unit": "action", - "value": 1 - }, - "damage_inflict": [ - "radiant" - ], - "saving_throw": [ - "constitution" - ], - "range": { - "type": "point", - "value": 5, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": true, - "materials_needed": "a holy symbol" - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["cleric"], - "sources": [ - { "source": "XGE", "page": 171 } - ], - "description": { - "entries": [ - "You utter a divine word, and burning radiance erupts from you. Each creature of your choice that you can see within range must succeed on a Constitution saving throw or take {@damage 1d6} radiant damage.", - "The spell's damage increases by {@damage 1d6} when you reach 5th level ({@damage 2d6}), 11th level ({@damage 3d6}), and 17th level ({@damage 4d6})." - ] - } - } -] \ No newline at end of file diff --git a/service/data/spells/level_1.json b/service/data/spells/level_1.json deleted file mode 100644 index 00fa213..0000000 --- a/service/data/spells/level_1.json +++ /dev/null @@ -1,2823 +0,0 @@ -[ - { - "name": "Absorb Elements", - "school": "abjuration", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "reaction", - "note": "which you take when you take acid, cold, fire, lightning, or thunder damage" - }, - "damage_inflict": ["acid"], - "range": { - "type": "self" - }, - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "round" - } - ], - "classes": ["artificer", "druid", "ranger", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 150 } - ], - "description": { - "entries": [ - "The spell captures some of the incoming energy, lessening its effect on you and storing it for your next melee attack. You have resistance to the triggering damage type until the start of your next turn. Also, the first time you hit with a melee attack on your next turn, the target takes an extra {@damage 1d6} damage of the triggering type, and the spell ends.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the extra damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." - ] - } - }, - { - "name": "Alarm", - "school": "abjuration", - "level": 1, - "ritual": true, - "casting_time": { - "value": 1, - "unit": "minute" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a tiny bell and a piece of fine silver wire" - }, - "durations": [ - { - "type": "timed", - "value": 8, - "unit": "hours" - } - ], - "classes": ["artificer", "{@subclass paladin|Oath of the Watchers}", "ranger", "wizard"], - "sources": [ - { "source": "PHB", "page": 211 }, - { "source": "XGE", "page": 155 } - ], - "description": { - "entries": [ - "You set an alarm against unwanted intrusion. Choose a door, a window, or an area within range that is no larger than a {@filter 20-foot cube|spells|cube|phb|p. 204}. Until the spell ends, an alarm alerts you whenever a Tiny or larger creature touches or enters the warded area. When you cast the spell, you can designate creatures that won't set off the alarm. You also choose whether the alarm is mental or audible.", - "A mental alarm alerts you with a ping in your mind if you are within 1 mile of the warded area. This ping awakens you if you are {@condition sleeping}.", - "An audible alarm produces the sound of a hand bell for 10 seconds within 60 feet." - ] - } - }, - { - "name": "Animal Friendship", - "school": "enchantment", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "conditions": ["charmed"], - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a morsel of food" - }, - "durations": [ - { - "type": "timed", - "value": 24, - "unit": "hours" - } - ], - "classes": ["bard", "druid", "ranger", "{@subclass cleric|Nature Domain}"], - "sources": [ - { "source": "PHB", "page": 212 } - ], - "description": { - "entries": [ - "This spell lets you convince a beast that you mean it no harm. Choose a beast that you can see within range. It must see and hear you. If the beast's Intelligence is 4 or higher, the spell fails. Otherwise, the beast must succeed on a Wisdom saving throw or be {@condition charmed} by you for the spell's duration. If you or one of your companions harms the target, the spell ends.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can affect one additional beast for each slot level above 1st." - ] - } - }, - { - "name": "Armor of Agathys", - "school": "abjuration", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "damage_inflict": ["cold"], - "range": { - "type": "self" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a cup of water" - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "hour" - } - ], - "classes": ["warlock", "{@subclass paladin|Oath of Conquest}"], - "sources": [ - { "source": "PHB", "page": 215 } - ], - "description": { - "entries": [ - "A protective magical force surrounds you, manifesting as a spectral frost that covers you and your gear. You gain {@dice 5} temporary hit points for the duration. If a creature hits you with a melee attack while you have these hit points, the creature takes {@damage 5} cold damage.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, both the temporary hit points and the cold damage increase by {@scaledamage 5|1-9|5} for each slot level above 1st." - ] - } - }, - { - "name": "Arms of Hadar", - "school": "conjuration", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "saving_throw": ["strength"], - "damage_inflict": ["necrotic"], - "range": { - "type": "self" - }, - "area": { - "type": "sphere", - "size": 10, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["warlock"], - "sources": [ - { "source": "PHB", "page": 215 } - ], - "description": { - "entries": [ - "You invoke the power of Hadar, the Dark Hunger. Tendrils of dark energy erupt from you and batter all creatures within 10 feet of you. Each creature in that area must make a Strength saving throw. On a failed save, a target takes {@damage 2d6} necrotic damage and can't take reactions until its next turn. On a successful save, the creature takes half damage, but suffers no other effect.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." - ] - } - }, - { - "name": "Bane", - "school": "enchantment", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "saving_throw": ["charisma"], - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a drop of blood" - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["bard", "cleric", "{@subclass paladin|Oath of Vengeance}", "{@subclass warlock|The Undead}"], - "sources": [ - { "source": "PHB", "page": 216 } - ], - "description": { - "entries": [ - "Up to three creatures of your choice that you can see within range must make Charisma saving throws. Whenever a target that fails this saving throw makes an attack roll or a saving throw before the spell ends, the target must roll a {@dice d4} and subtract the number rolled from the attack roll or saving throw.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st." - ] - } - }, - { - "name": "Beast Bond", - "school": "divination", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a bit of fur wrapped in a cloth" - }, - "durations": [ - { - "type": "concentration", - "value": 10, - "unit": "minutes" - } - ], - "classes": ["druid", "ranger"], - "sources": [ - { "source": "EEPC", "page": 150 } - ], - "description": { - "entries": [ - "You establish a telepathic link with one beast you touch that is friendly to you or {@condition charmed} by you. The spell fails if the beast's Intelligence is 4 or higher. Until the spell ends, the link is active while you and the beast are within line of sight of each other. Through the link, the beast can understand your telepathic messages to it, and it can telepathically communicate simple emotions and concepts back to you. While the link is active, the beast gains advantage on attack rolls against any creature within 5 feet of you that you can see." - ] - } - }, - { - "name": "Bless", - "school": "enchantment", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 30, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "a sprinkling of holy water" - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["cleric", "paladin"], - "sources": [ - { "source": "PHB", "page": 219 } - ], - "description": { - "entries": [ - "You bless up to three creatures of your choice within range. Whenever a target makes an attack roll or a saving throw before the spell ends, the target can roll a {@dice d4} and add the number rolled to the attack roll or saving throw.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st." - ] - } - }, - { - "name": "Burning Hands", - "school": "evocation", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "saving_throw": ["dexterity"], - "damage_inflict": ["fire"], - "range": { - "type": "self" - }, - "area": { - "type": "cone", - "size": 15, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["{@subclass cleric|Light Domain}", "{@subclass druid|Circle of Wildfire}", "sorcerer", "{@subclass warlock|The Fiend}", "{@subclass warlock|The Genie}", "wizard"], - "sources": [ - { "source": "PHB", "page": 220 } - ], - "description": { - "entries": [ - "As you hold your hands with thumbs touching and fingers spread, a thin sheet of flames shoots forth from your outstretched fingertips. Each creature in a {@filter 15-foot cone|spells|cone|phb|p. 204} must make a Dexterity saving throw. A creature takes {@damage 3d6} fire damage on a failed save, or half as much damage on a successful one.", - "The fire ignites any flammable objects in the area that aren't being worn or carried.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the damage increases by {@scaledamage 1d6|1-9|1d6} for each slot level above 1st." - ] - } - }, - { - "name": "Catapult", - "school": "transmutation", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "saving_throw": ["dexterity"], - "damage_inflict": ["bludgeoning"], - "components": { - "verbal": false, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["artificer", "sorcerer", "wizard"], - "sources": [ - { "source": "EEPC", "page": 150 } - ], - "description": { - "entries": [ - "Choose one object weighing 1 to 5 pounds within range that isn't being worn or carried. The object flies in a straight line up to 90 feet in a direction you choose before falling to the ground, stopping early if it impacts against a solid surface. If the object would strike a creature, that creature must make a Dexterity saving throw. On a failed save, the object strikes the target and stops moving. When the object strikes something, the object and what it strikes each take {@damage 3d8} bludgeoning damage.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, the maximum weight of objects that you can target with this spell increases by 5 pounds, and the damage increases by {@scaledamage 1d8|1-9|1d8}, for each slot level above 1st." - ] - } - }, - { - "name": "Cause Fear", - "school": "necromancy", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "saving_throw": ["wisdom"], - "conditions": ["frightened"], - "range": { - "type": "point", - "value": 60, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "concentration", - "value": 1, - "unit": "minute" - } - ], - "classes": ["warlock", "wizard"], - "sources": [ - { "source": "XGE", "page": 151 } - ], - "description": { - "entries": [ - "You awaken the sense of mortality in one creature you can see within range. A construct or an undead is immune to this effect. The target must succeed on a Wisdom saving throw or become {@condition frightened} of you until the spell ends. The {@condition frightened} target can repeat the saving throw at the end of each of its turns, ending the effect on itself on a success.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, you can target one additional creature for each slot level above 1st. The creatures must be within 30 feet of each other when you target them." - ] - } - }, - { - "name": "Ceremony", - "school": "abjuration", - "level": 1, - "ritual": true, - "casting_time": { - "value": 1, - "unit": "hour" - }, - "range": { - "type": "touch" - }, - "components": { - "verbal": true, - "somatic": true, - "material": true, - "materials_needed": "25 gp worth of powdered silver, which the spell consumes", - "materials_consumed": true, - "materials_cost": 2500 - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["cleric", "paladin"], - "sources": [ - { "source": "XGE", "page": 151 } - ], - "description": { - "entries": [ - "You perform a special religious ceremony that is infused with magic. When you cast the spell, choose one of the following rites, the target of which must be within 10 feet of you throughout the casting.", - "{@bold Atonement.} You touch one willing creature whose alignment has changed, and you make a DC 20 Wisdom ({@skill Insight}) check. On a successful check, you restore the target to its original alignment.", - "{@bold Bless Water.} You touch one vial of water and cause it to become holy water.", - "{@bold Coming of Age.} You touch one humanoid who is a young adult. For the next 24 hours, whenever the target makes an ability check, it can roll a d4 and add the number rolled to the ability check. A creature can benefit from this rite only once.", - "{@bold Dedication.} You touch one humanoid who wishes to be dedicated to your god's service. For the next 24 hours, whenever the target makes a saving throw, it can roll a d4 and add the number rolled to the save. A creature can benefit from this rite only once.", - "{@bold Funeral Rite.} You touch one corpse, and for the next 7 days, the target can't become undead by any means short of a wish spell.", - "{@bold Wedding.} You touch adult humanoids willing to be bonded together in marriage. For the next 7 days, each target gains a +2 bonus to AC while they are within 30 feet of each other. A creature can benefit from this rite again only if widowed." - ] - } - }, - { - "name": "Chaos Bolt", - "school": "evocation", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "attack_type": "ranged", - "damage_inflict": ["acid", "cold", "fire", "force", "lightning", "poison", "psychic", "thunder"], - "range": { - "type": "point", - "value": 120, - "unit": "feet" - }, - "components": { - "verbal": true, - "somatic": true, - "material": false - }, - "durations": [ - { - "type": "instantaneous" - } - ], - "classes": ["sorcerer"], - "sources": [ - { "source": "XGE", "page": 151 } - ], - "description": { - "entries": [ - "You hurl an undulating, warbling mass of chaotic energy at one creature in range. Make a ranged spell attack against the target. On a hit, the target takes {@damage 2d8} + {@damage 1d6} damage. Choose one of the d8s. The number rolled on that die determines the attack's damage type, as shown below.", - { - "table": { - "headers": ["d8", "Damage Type"], - "rows": [ - ["1", "Acid"], - ["2", "Cold"], - ["3", "Fire"], - ["4", "Force"], - ["5", "Lightning"], - ["6", "Poison"], - ["7", "Psychic"], - ["8", "Thunder"] - ] - } - }, - "If you roll the same number on both d8s, the chaotic energy leaps from the target to a different creature of your choice within 30 feet of it. Make a new attack roll against the new target, and make a new damage roll, which could cause the chaotic energy to leap again.", - "A creature can be targeted only once by each casting of this spell.", - "{@bold At Higher Levels.} When you cast this spell using a spell slot of 2nd level or higher, each target takes {@scaledamage 1d6|1-9|1d6} extra damage of the type rolled for each slot level above 1st." - ] - } - }, - { - "name": "Charm Person", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Chromatic Orb", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Color Spray", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Command", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Compelled Duel", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Comprehend Languages", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Create or Destroy Water", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Cure Wounds", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Detect Evil and Good", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Detect Magic", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Detect Poison and Disease", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Disguise Self", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Dissonant Whispers", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Divine Favor", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Earth Tremor", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Ensnaring Strike", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Entangle", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Expeditious Retreat", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Faerie Fire", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "False Life", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Feather Fall", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Find Familiar", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Fog Cloud", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Frost Fingers", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Gift of Alacrity", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Goodberry", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Grease", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Guiding Bolt", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Hail of Thorns", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Healing Word", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Hellish Rebuke", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Heroism", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Hex", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Hunter’s Mark", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Ice Knife", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Identify", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Illusory Script", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Inflict Wounds", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Jump", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Longstrider", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Mage Armor", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Magic Missile", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Magnify Gravity", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Protection from Evil and Good", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Purify Food and Drink", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Ray of Sickness", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Sanctuary", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Searing Smite", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Shield", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Shield of Faith", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Silent Image", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Silvery Barbs", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Sleep", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Snare", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Speak with Animals", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Tasha’s Caustic Brew", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Tasha’s Hideous Laughter", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Tenser’s Floating Disk", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Thunderous Smite", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Thunderwave", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Unseen Servant", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Witch Bolt", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Wrathful Smite", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - }, - { - "name": "Zephyr Strike", - "school": "", - "level": 1, - "ritual": false, - "casting_time": { - "value": 1, - "unit": "action" - }, - "range": { - "type": "point", - "value": 1, - "unit": "feet" - }, - "components": { - "verbal": false, - "somatic": false, - "material": false - }, - "durations": [ - { - "type": "timed", - "value": 1, - "unit": "minute" - } - ], - "classes": [], - "sources": [ - { "source": "", "page": 0 } - ], - "description": { - "entries": [ - - ] - } - } -] \ No newline at end of file From 5dcc2a6afc621d14f11f0ed1eb1f03ac63c16b77 Mon Sep 17 00:00:00 2001 From: Benjamin Sherriff Date: Thu, 5 Oct 2023 15:38:59 -0400 Subject: [PATCH 4/4] Recombined bot and service, fixed dockerfile --- .vscode/settings.json | 3 +- bot/.env.TEMPLATE | 7 ---- bot/Cargo.toml | 42 ------------------- bot/Dockerfile | 37 ---------------- bot/Makefile | 27 ------------ bot/docker-compose.yml | 21 ---------- service/.env.TEMPLATE | 5 ++- service/Cargo.toml | 9 ++++ service/Dockerfile | 36 +++++++++++++--- service/docker-compose.yml | 3 ++ .../src/bot}/commands/audio/mod.rs | 0 .../src/bot}/commands/audio/pause.rs | 0 .../src/bot}/commands/audio/play.rs | 2 +- .../src/bot}/commands/audio/resume.rs | 0 .../src/bot}/commands/audio/skip.rs | 0 .../src/bot}/commands/audio/stop.rs | 0 .../src/bot}/commands/audio/volume.rs | 0 {bot/src => service/src/bot}/commands/help.rs | 0 {bot/src => service/src/bot}/commands/mod.rs | 0 {bot/src => service/src/bot}/commands/oai.rs | 0 {bot/src => service/src/bot}/commands/ping.rs | 0 .../src/bot}/commands/schedule.rs | 0 bot/src/main.rs => service/src/bot/mod.rs | 13 ++---- service/src/db/spells/model.rs | 5 +++ service/src/db/spells/routes.rs | 2 + service/src/main.rs | 3 ++ ui/src/api/spells.ts | 2 + 27 files changed, 64 insertions(+), 153 deletions(-) delete mode 100644 bot/.env.TEMPLATE delete mode 100644 bot/Cargo.toml delete mode 100644 bot/Dockerfile delete mode 100644 bot/Makefile delete mode 100644 bot/docker-compose.yml rename {bot/src => service/src/bot}/commands/audio/mod.rs (100%) rename {bot/src => service/src/bot}/commands/audio/pause.rs (100%) rename {bot/src => service/src/bot}/commands/audio/play.rs (98%) rename {bot/src => service/src/bot}/commands/audio/resume.rs (100%) rename {bot/src => service/src/bot}/commands/audio/skip.rs (100%) rename {bot/src => service/src/bot}/commands/audio/stop.rs (100%) rename {bot/src => service/src/bot}/commands/audio/volume.rs (100%) rename {bot/src => service/src/bot}/commands/help.rs (100%) rename {bot/src => service/src/bot}/commands/mod.rs (100%) rename {bot/src => service/src/bot}/commands/oai.rs (100%) rename {bot/src => service/src/bot}/commands/ping.rs (100%) rename {bot/src => service/src/bot}/commands/schedule.rs (100%) rename bot/src/main.rs => service/src/bot/mod.rs (96%) diff --git a/.vscode/settings.json b/.vscode/settings.json index ffa8b01..92e36aa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,5 @@ { "rust-analyzer.linkedProjects": [ - "./service/Cargo.toml", - "./bot/Cargo.toml", + "./service/Cargo.toml" ] } \ No newline at end of file diff --git a/bot/.env.TEMPLATE b/bot/.env.TEMPLATE deleted file mode 100644 index 07f5e95..0000000 --- a/bot/.env.TEMPLATE +++ /dev/null @@ -1,7 +0,0 @@ -RUST_LOG=warn,bot=info - -SERVICE_HOST=localhost -SERVICE_PORT=5000 - -DISCORD_TOKEN= -OPENAI_API_KEY= \ No newline at end of file diff --git a/bot/Cargo.toml b/bot/Cargo.toml deleted file mode 100644 index d57de98..0000000 --- a/bot/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "bot" -version = "0.2.4" -edition = "2021" -authors = ["Ben Sherriff "] -repository = "https://github.com/bensherriff/siren" -readme = "README.md" -license = "GPL-3.0-or-later" - -[dependencies] -chrono = { version = "0.4.31", features = ["serde"] } -dotenv = "0.15.0" -serde_json = "1.0.107" -log = "0.4.20" -env_logger = "0.10.0" -service = { path = "../service" } - -[dependencies.serenity] -version = "0.11.6" -default-features = false -features = ["client", "gateway", "rustls_backend", "model", "voice", "cache", "framework", "standard_framework"] - -[dependencies.songbird] -version = "0.3.2" -features = ["builtin-queue", "yt-dlp"] - -[dependencies.tokio] -version = "1.32.0" -features = ["macros", "rt-multi-thread"] - -[dependencies.serde] -version = "1.0.188" -features = ["derive"] - -[dependencies.reqwest] -version = "0.11.22" -default-features = false -features = ["json", "rustls-tls"] - -[dependencies.pyo3] -version = "0.19.2" -features = ["auto-initialize"] diff --git a/bot/Dockerfile b/bot/Dockerfile deleted file mode 100644 index 5811412..0000000 --- a/bot/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -# Builder -FROM rust:1.72.1-bookworm as builder -WORKDIR /builder - -COPY src ./src -COPY Cargo.toml ./ -RUN cargo build --release - -# Packages -FROM debian:bullseye-slim as packages -WORKDIR /packages - -RUN apt-get update && apt-get install -y curl tar xz-utils && \ - curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux > yt-dlp && \ - chmod +x yt-dlp && \ - curl -L https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz > ffmpeg.tar.xz && \ - tar -xJf ffmpeg.tar.xz --wildcards */bin/ffmpeg --transform='s/^.*\///' && rm ffmpeg.tar.xz - -# FROM debian:bullseye-slim as libraries -# WORKDIR /libraries -# RUN apt-get update && apt-get install -y unzip && \ -# curl -L https://download.pytorch.org/libtorch/cu117/libtorch-cxx11-abi-shared-with-deps-2.0.1%2Bcu117.zip > libtorch.zip && \ -# unzip libtorch.zip && rm libtorch.zip - -# Runner -FROM debian:bullseye-slim as runtime -WORKDIR /bot -RUN apt-get update && apt-get install -y libopus-dev libpq5 libpq-dev && apt-get auto-remove -y -COPY --from=builder /builder/target/release/bot /usr/local/bin/bot -COPY --from=packages /packages /usr/bin -# COPY --from=libraries /libraries /usr/lib - -# ARG LIBTORCH=/usr/lib/libtorch -# ARG LD_LIBRARY_PATH=${LIBTORCH}/lib:${LD_LIBRARY_PATH} - -# ADD migrations ./ -CMD ["bot"] diff --git a/bot/Makefile b/bot/Makefile deleted file mode 100644 index 0845f7c..0000000 --- a/bot/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -#!make -SHELL := /bin/bash - -include .env - -.PHONY: help build test up down exec clean - -help: ## Help command - @echo - @cat Makefile | grep -E '^[a-zA-Z\/_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' - @echo - -build: ## Build the docker image - docker compose build - -db: ## Start the docker database - docker compose up -d db - -up: ## Start the app - docker compose up -d - -down: ## Stop the app - docker compose down - -clean: - docker compose down && \ - docker image rm siren-bot diff --git a/bot/docker-compose.yml b/bot/docker-compose.yml deleted file mode 100644 index e35d8fb..0000000 --- a/bot/docker-compose.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '3.8' - -name: siren -services: - bot: - image: siren-bot:${BOT_VERSION:-latest} - container_name: siren-bot - build: - context: . - dockerfile: ./Dockerfile - args: - - VERSION=${BOT_VERSION:-latest} - env_file: - - .env - networks: - - frontend - restart: unless-stopped - - -networks: - frontend: diff --git a/service/.env.TEMPLATE b/service/.env.TEMPLATE index 6527927..e8d5b3e 100644 --- a/service/.env.TEMPLATE +++ b/service/.env.TEMPLATE @@ -8,4 +8,7 @@ DATABASE_PORT=5432 SERVICE_HOST=localhost SERVICE_PORT=5000 -DATA_DIR_PATH= \ No newline at end of file +DATA_DIR_PATH= + +DISCORD_TOKEN= +OPENAI_API_KEY= \ No newline at end of file diff --git a/service/Cargo.toml b/service/Cargo.toml index a76b62d..5f615ae 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -43,3 +43,12 @@ features = ["json", "rustls-tls"] version = "2.1.2" default-features = false features = ["postgres", "32-column-tables", "serde_json", "r2d2", "with-deprecated"] + +[dependencies.serenity] +version = "0.11.6" +default-features = false +features = ["client", "gateway", "rustls_backend", "model", "voice", "cache", "framework", "standard_framework"] + +[dependencies.songbird] +version = "0.3.2" +features = ["builtin-queue", "yt-dlp"] diff --git a/service/Dockerfile b/service/Dockerfile index 11a9177..095ea6d 100644 --- a/service/Dockerfile +++ b/service/Dockerfile @@ -1,12 +1,36 @@ -FROM rust:1.72.1-bookworm as builder - -WORKDIR /service -USER root +# ========= +# Builder +# ========= +FROM rust:bookworm as builder +WORKDIR /builder COPY migrations ./migrations -COPY data ./data COPY src ./src COPY Cargo.toml ./ +RUN apt-get update && apt-get install -y cmake RUN cargo build --release -CMD ["./target/release/service"] \ No newline at end of file + +# ========== +# Packages +# ========== +FROM debian:bookworm-slim as packages +WORKDIR /packages + +RUN apt-get update && apt-get install -y curl tar xz-utils && \ + curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux > yt-dlp && \ + chmod +x yt-dlp && \ + curl -L https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz > ffmpeg.tar.xz && \ + tar -xJf ffmpeg.tar.xz --wildcards */bin/ffmpeg --transform='s/^.*\///' && rm ffmpeg.tar.xz + +# ========= +# Runtime +# ========= +FROM rust:bookworm as runtime +WORKDIR /service +USER root + +COPY --from=builder /builder/target/release/service /usr/local/bin/service +COPY --from=packages /packages /usr/bin + +CMD ["service"] diff --git a/service/docker-compose.yml b/service/docker-compose.yml index 984c3c5..b3b5d2c 100644 --- a/service/docker-compose.yml +++ b/service/docker-compose.yml @@ -17,6 +17,9 @@ services: DATABASE_PORT: 5432 SERVICE_HOST: service SERVICE_PORT: 5000 + DATA_DIR_PATH: /data + volumes: + - ${DATA_DIR_PATH}:/data ports: - ${SERVICE_PORT:-5000}:5000 depends_on: diff --git a/bot/src/commands/audio/mod.rs b/service/src/bot/commands/audio/mod.rs similarity index 100% rename from bot/src/commands/audio/mod.rs rename to service/src/bot/commands/audio/mod.rs diff --git a/bot/src/commands/audio/pause.rs b/service/src/bot/commands/audio/pause.rs similarity index 100% rename from bot/src/commands/audio/pause.rs rename to service/src/bot/commands/audio/pause.rs diff --git a/bot/src/commands/audio/play.rs b/service/src/bot/commands/audio/play.rs similarity index 98% rename from bot/src/commands/audio/play.rs rename to service/src/bot/commands/audio/play.rs index 386e6a2..cb0442b 100644 --- a/bot/src/commands/audio/play.rs +++ b/service/src/bot/commands/audio/play.rs @@ -5,7 +5,7 @@ use serenity::builder::CreateApplicationCommand; use serenity::model::application::interaction::application_command::ApplicationCommandInteraction; use songbird::EventHandler; -use crate::commands::audio::{join, leave, add_song, get_songbird, AudioConfigs}; +use crate::bot::commands::audio::{join, leave, add_song, get_songbird, AudioConfigs}; use super::{create_response, edit_response}; diff --git a/bot/src/commands/audio/resume.rs b/service/src/bot/commands/audio/resume.rs similarity index 100% rename from bot/src/commands/audio/resume.rs rename to service/src/bot/commands/audio/resume.rs diff --git a/bot/src/commands/audio/skip.rs b/service/src/bot/commands/audio/skip.rs similarity index 100% rename from bot/src/commands/audio/skip.rs rename to service/src/bot/commands/audio/skip.rs diff --git a/bot/src/commands/audio/stop.rs b/service/src/bot/commands/audio/stop.rs similarity index 100% rename from bot/src/commands/audio/stop.rs rename to service/src/bot/commands/audio/stop.rs diff --git a/bot/src/commands/audio/volume.rs b/service/src/bot/commands/audio/volume.rs similarity index 100% rename from bot/src/commands/audio/volume.rs rename to service/src/bot/commands/audio/volume.rs diff --git a/bot/src/commands/help.rs b/service/src/bot/commands/help.rs similarity index 100% rename from bot/src/commands/help.rs rename to service/src/bot/commands/help.rs diff --git a/bot/src/commands/mod.rs b/service/src/bot/commands/mod.rs similarity index 100% rename from bot/src/commands/mod.rs rename to service/src/bot/commands/mod.rs diff --git a/bot/src/commands/oai.rs b/service/src/bot/commands/oai.rs similarity index 100% rename from bot/src/commands/oai.rs rename to service/src/bot/commands/oai.rs diff --git a/bot/src/commands/ping.rs b/service/src/bot/commands/ping.rs similarity index 100% rename from bot/src/commands/ping.rs rename to service/src/bot/commands/ping.rs diff --git a/bot/src/commands/schedule.rs b/service/src/bot/commands/schedule.rs similarity index 100% rename from bot/src/commands/schedule.rs rename to service/src/bot/commands/schedule.rs diff --git a/bot/src/main.rs b/service/src/bot/mod.rs similarity index 96% rename from bot/src/main.rs rename to service/src/bot/mod.rs index c0857d2..43dcce0 100644 --- a/bot/src/main.rs +++ b/service/src/bot/mod.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use commands::audio::{create_response, AudioConfig, AudioConfigs}; -use dotenv::dotenv; use log::{error, warn, info}; use serenity::async_trait; use serenity::framework::StandardFramework; @@ -15,9 +14,9 @@ use serenity::http::Http; use serenity::prelude::*; use songbird::SerenityInit; -use crate::commands::oai::GPTModel; +use crate::bot::commands::oai::GPTModel; -mod commands; +pub mod commands; struct Handler { // Open AI Config @@ -108,11 +107,7 @@ impl EventHandler for Handler { } } -#[tokio::main] -async fn main() { - dotenv().ok(); - env_logger::init_from_env(env_logger::Env::default().filter_or("RUST_LOG", "warn,siren=info")); - +pub async fn run() { let token: String = env::var("DISCORD_TOKEN").expect("Expected a token in the environment"); let intents: GatewayIntents = GatewayIntents::all(); @@ -171,4 +166,4 @@ async fn main() { if let Err(why) = client.start_autosharded().await { error!("An error occurred while running the client: {:?}", why); } -} +} \ No newline at end of file diff --git a/service/src/db/spells/model.rs b/service/src/db/spells/model.rs index 027aaf6..d8f71f3 100644 --- a/service/src/db/spells/model.rs +++ b/service/src/db/spells/model.rs @@ -27,6 +27,7 @@ pub struct QuerySpell { #[derive(Debug)] pub struct QueryFilters { pub by_name: Option, + pub like_name: Option, pub by_schools: Option>, pub by_levels: Option>, pub by_ritual: Option, @@ -43,6 +44,7 @@ impl Default for QueryFilters { fn default() -> Self { Self { by_name: None, + like_name: None, by_schools: None, by_levels: None, by_ritual: None, @@ -65,6 +67,9 @@ impl QuerySpell { let offset = (page - 1) * limit; query = query.offset(offset as i64); if let Some(name) = &filters.by_name { + query = query.filter(spells::name.eq(name)); + } + if let Some(name) = &filters.like_name { query = query.filter(spells::name.ilike(format!("%{}%", name))); } if let Some(schools) = &filters.by_schools { diff --git a/service/src/db/spells/routes.rs b/service/src/db/spells/routes.rs index 5d985f8..cf61605 100644 --- a/service/src/db/spells/routes.rs +++ b/service/src/db/spells/routes.rs @@ -10,6 +10,7 @@ use super::{Spell, InsertSpell}; #[derive(Serialize, Deserialize)] struct GetAllParams { name: Option, + like_name: Option, schools: Option, levels: Option, ritual: Option, @@ -35,6 +36,7 @@ async fn get_all(req: HttpRequest) -> HttpResponse { }; let mut filters = QueryFilters::default(); filters.by_name = params.name.clone(); + filters.like_name = params.like_name.clone(); filters.by_schools = match ¶ms.schools { Some(schools) => Some(schools.split(",").map(|s| s.to_string()).collect()), None => None diff --git a/service/src/main.rs b/service/src/main.rs index 53e0402..bd2a483 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -10,6 +10,7 @@ use actix_web::{HttpServer, App}; use dotenv::dotenv; use log::{error, info, warn}; +mod bot; mod db; #[actix_web::main] @@ -25,6 +26,8 @@ async fn main() -> std::io::Result<()> { let host = env::var("SERVICE_HOST").unwrap_or("localhost".to_string()); let port = env::var("SERVICE_PORT").unwrap_or("5000".to_string()); + tokio::spawn(bot::run()); + match HttpServer::new(|| { let cors = Cors::default() .allow_any_origin() diff --git a/ui/src/api/spells.ts b/ui/src/api/spells.ts index c5b13f3..1c2e0eb 100644 --- a/ui/src/api/spells.ts +++ b/ui/src/api/spells.ts @@ -3,6 +3,7 @@ import { GetSpellsResponse } from './spells.types'; interface GetSpellsParams { name?: string; + like_name?: string; schools?: string[]; levels?: number[]; ritual?: boolean; @@ -20,6 +21,7 @@ interface GetSpellsParams { export async function getSpells(params?: GetSpellsParams): Promise { const response = await getRequest('spells', { name: params?.name, + like_name: params?.like_name, schools: params?.schools?.join(','), levels: params?.levels?.join(','), ritual: params?.ritual,