From c65d9edfa40f605fab8b67e92bbf389b7eaaf7ec Mon Sep 17 00:00:00 2001 From: Type-Style Date: Sun, 1 Sep 2024 21:03:56 +0200 Subject: [PATCH] 1st Release 2 (#121) * [Task] #6 provide fallback index.html * [Task] #6 production ready code (m) move httpdocs folder to dist have compile without sourcemaps for faster speed * [Task] #6 create github action for upload when main is updated (#21) * [change] #6 new ftp upload action * [Fix] #6 replace host with server in ftp action * [Task] #6 basic log (#26) * [CHANGE] #6 revert back to require output for production * [Task] #6 add ability to manually upload to prod * [Task] #9 enable manual start of codechecks * 10 webhook for writing (#36) * [Change] #3 clean up npm scripts, to have clean folder before build * [Task] #10 created data types in typescript * [Temp] #10 created subroute for writing, and folder structure * [Change] #3 include to use relative paths from src folder in ts and node https://stackoverflow.com/questions/43281741/how-can-i-use-paths-in-tsconfig-json See comment from Remo H. Hansen with at least 100 upvoted * [Change] Update VSCode to keep files open * [Task] #18 setup dotenv for secret variables * [Temp, Task] #10 Validate inputs using express-validator and custom functions * [Task] #18 prevent parameter pollution * [Task] #10 validating incoming parameter and logging errors * [Task] #7 add basic cache to express * [Changes] #7 Error Handling, to include basic custom Error Handling * [Task] #10 enhanced validation to only allow known parameters * [Change] #35 added Jest, tests for helper functions when writing * [Task] #10 better error Handling * [Task] #35 add tests for writing webhook validation * [TASK] #18 protect Webhook using KEY * [Fix] #35 test know import path structure now * [Task] #35 add test for protected webhook * [Task] #35 refactor build to run jest tests * [Task] #10 switched to crypto instead of bcrypt for dependency issue see synk inflight * [Fix] #36 PRQ Feedback * [Task] #3 improve error handling, logger and added chalk to colorize console output. Had to use chalk version 4 because of typescript converting to require, and chalk5 do want import syntax. * [Change] #3 nodemon to clear console when in dev mode * [!Task] #32 webhook creates folder and file based on date * [Change] #35 relocated tests and refactor write, also added file check * [Task] #18, installed helmet, configured self as CSP origin * [Fix] moved chalk out of dev dependency * [Task] #32 error logging and text output improvement, log string instead of "object" * [Task] #18 CSP Update to allow localhost for testing * [Fix] #3 debugging setup improvments * [FIX] #10 Error Handling * [Task] #10 writing basic non calculated data to file * [Fix] #10 avoid Header Modification after sending the request * [Task] #10 JSON Data pretty output * [Task] #32 update types to reflect subobjects of entry * [Task] #10 write time * [Task] #32 added logging for time edgecases * [Task] #10 output seconds * [Task] #10 calculate distance based on lat and lon * [Task] #32 writing tests for time and distance * [Task] #32 change distance calculation to use pythagoras * [Task] #38 add favicon * [Task] #32 time converted to seconds * [Taskk] #32 speed calculation and output and tests * [Task] #32 speed tests * [Task] #33 add ignore * [Task] #32 test finetuning * [Task] #32 add angle between entries * [Task] #32 test for angle, extracted getData function * [change] #32 test to include optional leading 0 for days * [!!!Task] #18 add uncaughtExeption handler as last resort * [Task] #7 enhance static options to include common filetypes; index file start is used as index file to avoid collisions with host provider * [change] #32 validation to be used more explictly * [change] #32 add index to log while writing * [Task] #32 test if 1000 calls can be made with randomized data * [!!! Task] #32 limit JSON Data to be 1000 lines: replace last line with most recent entry * [Change, Task] #32 if 1000 entries exceeded, only replace last if hdop is good * [Change] build action enable button to on manually * [temp] test y tests fail * Create node.js.yml * Create main.yml * [!!!Fix] Created new workflow to build / test node, commented tests back in. Increased time between server calls in test, to check difference time more accurately * [Task] #33 moved ignore to its own file since it creates data rather than validating it * 42 output json (#44) * [Task] #42, created route to output json * [Task] #42 added tests for read json * 41 add rate limiter (#45) * [Task] #18, limit request size for security reasons * [Task] #43, introduce gzip to transfer data * [Task] #34 improve error handling, log server shutdowns * [Task] #34 installed and integrated tooBusy to send 503 when load is high * [Task] #34 improved tooBusy, improved formatting * [Task, Temp] #41 installed ratelimiter and slowDown * [Task] #42 cleanup ipv6 addresses * [Change] #10 error handling for better gitBash and txt output, also reduced stack in case of validation errors * [Task] #41 prepare Log for RateLImit errors * [Temp] #41 write route rateLImited temp: see Todos * [Task] #34 colorize prefix in console * [Task] #42 extract middlewares and move to folder * [Task] #41 ratelimiter cleaning up periodicly * [Task] #41 skip tests in rateLimiting * Bump follow-redirects from 1.15.5 to 1.15.6 (#47) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.5...v1.15.6) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 43 secure output route (#46) * [Task] #43 create color pallette via atmos * [Task] #43 create color pallette via atmos * [Task] #43 cleanup colors and svg * [Task] #41 remove test code * [CHANGE] #3 reconfigured nodemon to copy static files * [Task] #18 replaced getRawBody with builtIn express urlEncoded * [Temp, Task] #43 basic login page, not yet used as middleware * [Temp] #43, create and validate json web token * [Task] #43, add slowDown and RateLimit for failed login attempts * [Task] #43, ratelimit for login page * [Task] #43, add global ratelimiter * [fix] #7, improve error handeling for express errors * [Task] #43 rework body limitations to be checked only appropiate methods * [Task] #43 added check for data before using it * [Task] #43 check that body is ignored for GET in request * [Task] #43 login test * [Task] #43 create tests for login * [Task] #43 fine tune error handling * [Task] #43, finished login and jwt related tests * [Change] #34, no further need for test logging * [Task] #43, fine tune jwt, middleware process improved * [CHANGE] #43 created new esLint to have clientside js without ts * [Temp] #43 test to see new linter configuration * [Change] #43 switched to bcrypt for passwords * [Task] #43 read return json in all cases * [Task] #43 introduced color classes * [Task] #43, prq feedback * [Temp} #43 figuring out why tests dont run on github * [Task] #43 code cleanup * 48 move login to seperate controller (#49) * [Task] #43, add label to form * [Task] #48 login controller * 50 integrate csrf protection for login form (#53) * [Task] #50, create CSRF Validation for login form * [Task] #43, added icon to repository for later use * [Task] #50, cleanup cetntralized; rename token functions * [Task] #50, reduced token length and improved error handling * [Task] #50 csrf tests added to login * [Task] #50, added test case for csrf, repaired integration * fix: upgrade express-rate-limit from 7.1.5 to 7.2.0 (#52) Snyk has created this PR to upgrade express-rate-limit from 7.1.5 to 7.2.0. See this package in npm: https://www.npmjs.com/package/express-rate-limit See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: package.json & package-lock.json to reduce vulnerabilities (#54) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-EXPRESS-6474509 Co-authored-by: snyk-bot * [Snyk] Upgrade express from 4.18.2 to 4.18.3 (#51) * fix: upgrade express from 4.18.2 to 4.18.3 Snyk has created this PR to upgrade express from 4.18.2 to 4.18.3. See this package in npm: https://www.npmjs.com/package/express See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr * 50 integrate csrf protection for login form (#53) * [Task] #50, create CSRF Validation for login form * [Task] #43, added icon to repository for later use * [Task] #50, cleanup cetntralized; rename token functions * [Task] #50, reduced token length and improved error handling * [Task] #50 csrf tests added to login * [Task] #50, added test case for csrf, repaired integration * fix: upgrade express-rate-limit from 7.1.5 to 7.2.0 (#52) Snyk has created this PR to upgrade express-rate-limit from 7.1.5 to 7.2.0. See this package in npm: https://www.npmjs.com/package/express-rate-limit See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot --------- Co-authored-by: snyk-bot * [Task] update dev after main merge * [Task] npm upgrade * 58 react setup (#59) * [Task] #58 install react via npm, incl. types and eslint plugins * [Task] #58, tsconfig for react folder * [Task] #58 esLint config * [Task] #58, webpack and react setup * [Task] #58, render welcome from express instead of static * [Task] #58 eslint scripts * [Task] #58, eslint react setup * [TASK] #58 integrate webpack in build and dev npm scripts * [Temp] Test csp * [FIX] Add views to be deployed to prod * [Task] disable csp for local development * [Task] #58 base css including colors, deleted color classes in favor of variables * [Task] #58 typescript setup for react * [Task] #58 webpack setup for react and typescript * [Task] #58 app setup react * [Temp] #58 conctact module css * [Task] #58 remove learning files * [Task] #61, create font * Revert "[Task] #58 remove learning files" This reverts commit b63bb97045a9443e11ca9d8658f1e7faecf96e3b. * [Task] #61, adjust for darkmode * [Task] #61 apply base style to login * [Task] #58, dev tesing rule to disable * [Task] #58, adjust styles for headline * [Task] #58, create Contacts wrapper Component * [Task] #58 apply wrapper component * [Task] #58 adjust contact component to expect object * [Task] #58, toggle state * [Task] #58 learn context api provider and consumer * [Task] #58 add delete via dispatch * [Task] #58, react-router, move contacts to new url * [Task] #58 fetch more contacts * fix: package.json & package-lock.json to reduce vulnerabilities (#62) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-EJS-6689533 Co-authored-by: snyk-bot * Bump tar and npm (#60) Bumps [tar](https://github.com/isaacs/node-tar) to 6.2.1 and updates ancestor dependency [npm](https://github.com/npm/cli). These dependencies need to be updated together. Updates `tar` from 6.2.0 to 6.2.1 - [Release notes](https://github.com/isaacs/node-tar/releases) - [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1) Updates `npm` from 10.5.0 to 10.5.2 - [Release notes](https://github.com/npm/cli/releases) - [Changelog](https://github.com/npm/cli/blob/latest/CHANGELOG.md) - [Commits](https://github.com/npm/cli/compare/v10.5.0...v10.5.2) --- updated-dependencies: - dependency-name: tar dependency-type: indirect - dependency-name: npm dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump ejs from 3.1.9 to 3.1.10 (#63) Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10. - [Release notes](https://github.com/mde/ejs/releases) - [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10) --- updated-dependencies: - dependency-name: ejs dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [Task] #58, webpack configuriation to allow regular css files as well as modules * [Task] #58, clean up react learn files * [Task] #58, setup react router * [Task] #61 install Material UI * [Task] #61, test mui * [CHANGE, MultiLine] #61 color variables levels removed, MUI Overwrites introduced color variables levels are replaced by color-mix. MUI Experimental API with Variables is used and to overwrite theme colors in css (since I want CSS to be single source of truth for colors) * [Temp] #61 introduce darkmode to MUI * [Task] #61, create new start module so that App can act as root * [Task] #61, naming update * [Task] #61, move router to root App * [Task] #61, add font to preload * [Task] #61, dim colors in dark mode * [Task] #61, introduce modeswitcher * [Change] #64, refactoring splitting pages and components * [Task] #61, mobile Theme Swticher placed on top right * [Task] #61, mobile theme switcher icon only on mobile * [Task] #61, button color and background improvement * [Task] #63, login page first draft * [Temp] #61, login controller commented out unused route, TO BE REFACTORED * [Task] #63, login validation * [Task] #63, add error icon * [Task] #61, cut design update * [Task] #53, apply cut, rename FormData to FormInfo to avoid confusion with reserved name * [Task] #63, send login request * [Task] #61, loading icon * [Task] #63, get csrfToken, fullfill login request * [Fix] #63, fail gracefully when too many tokens * [Task] #63, error Handling in login form * [Task] #81, remove password log * [Task] #80, cleanup todo token * fix: upgrade multiple dependencies with Snyk (#68) Snyk has created this PR to upgrade: - react from 18.2.0 to 18.3.1. See this package in npm: https://www.npmjs.com/package/react - react-dom from 18.2.0 to 18.3.1. See this package in npm: https://www.npmjs.com/package/react-dom See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * [Fix] #64, disable express header * [Task] #64, protect csrf token page with custom http header * [FIx] #64, fix csrf test * [Task] #64, repair test cases * fix: upgrade express-slow-down from 2.0.1 to 2.0.2 (#69) Snyk has created this PR to upgrade express-slow-down from 2.0.1 to 2.0.2. See this package in npm: express-slow-down See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * [fix] #64, linter fixes * [Task] Editor Config * [Task] #61, convert background line to svg and animate * [Task] #61, main headline style * [Task] #61, fine tune background pattern * [Task] #61, font-weight reduced in darkmode * [Task] #64, login design improvements * [Task] #61, update design with minor ripples and edges * [Task] #70, store token after login * Bump braces from 3.0.2 to 3.0.3 (#76) Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: upgrade @mui/icons-material from 5.15.16 to 5.15.18 (#75) Snyk has created this PR to upgrade @mui/icons-material from 5.15.16 to 5.15.18. See this package in npm: @mui/icons-material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade react-router-dom from 6.23.0 to 6.23.1 (#74) Snyk has created this PR to upgrade react-router-dom from 6.23.0 to 6.23.1. See this package in npm: react-router-dom See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade express-slow-down from 2.0.2 to 2.0.3 (#73) Snyk has created this PR to upgrade express-slow-down from 2.0.2 to 2.0.3. See this package in npm: express-slow-down See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade express-rate-limit from 7.2.0 to 7.3.0 (#82) Snyk has created this PR to upgrade express-rate-limit from 7.2.0 to 7.3.0. See this package in npm: express-rate-limit See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade express-validator from 7.0.1 to 7.1.0 (#81) Snyk has created this PR to upgrade express-validator from 7.0.1 to 7.1.0. See this package in npm: express-validator See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade axios from 1.7.1 to 1.7.2 (#80) Snyk has created this PR to upgrade axios from 1.7.1 to 1.7.2. See this package in npm: axios See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade @mui/icons-material from 5.15.18 to 5.15.19 (#79) Snyk has created this PR to upgrade @mui/icons-material from 5.15.18 to 5.15.19. See this package in npm: @mui/icons-material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade @mui/icons-material from 5.15.19 to 5.15.20 (#88) Snyk has created this PR to upgrade @mui/icons-material from 5.15.19 to 5.15.20. See this package in npm: @mui/icons-material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade react-router-dom from 6.23.1 to 6.24.0 (#91) Snyk has created this PR to upgrade react-router-dom from 6.23.1 to 6.24.0. See this package in npm: react-router-dom See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * 77 design base layout (#85) * [Task] #77 1st draft layout * [Change] #70 update token expire date * [Temp] #77, log out data on valid request, temp: error handling and display * [Temp] * [Task] #77, login Button functionality, default state * [Task] #77, removed outdated comments * [Task] #77, introduced linearBuffer Bar for login * [Task] #77, added modeSwticher to start page * [Task] #77, display last entry on map demo * [Task] #77, enhance login, show pastUser if availabe, show user on mainpage * [!!!Task] #77 first draft of functionality * [Task] #77 move map to new location * [Task] #77 create testData * [Fix] #77 codeFactor complains * [Task] #77, draft of status content * [FIX] #77 change data accumulation * [Task] #77 improve test example data * fix: upgrade @mui/material from 5.15.16 to 5.15.20 (#92) Snyk has created this PR to upgrade @mui/material from 5.15.16 to 5.15.20. See this package in npm: @mui/material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * [Fix] #94, refactor-ignore logic (multiline) (#95) Serverside: When writing entry, the most recent previous entry is checked wether to be ignored. Also if more than 2 items already exist meaning writing is preparing at least the 3rd entry, we recalculate distances and timing if previousItems are ignored. Frontend: In order to benefit and get the recent information that a previous item is being ignored, frontEnd askes for the current item again and merges it and following items. Remember the most recent item can never be ignored due to policy. Maybe there is no further writing, so I want to have the latest datapoint. * [Task] #94, add logging if logical error with ignore * [Task] #94, cleanup console.logs * [Fix] #93, offline message improvement (#96) * fix: package.json & package-lock.json to reduce vulnerabilities (#101) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-AXIOS-7361793 Co-authored-by: snyk-bot * fix: upgrade @mui/material from 5.15.20 to 5.16.5 (#102) Snyk has created this PR to upgrade @mui/material from 5.15.20 to 5.16.5. See this package in npm: @mui/material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * 93 fix error message when server not available (#103) * [Fix] #93, offline message improvement * [Task] #93, removed background in status module when no data is present * [Task] #61, add cut class to map for styling * [Fix] #93 fix tests, be more specific on url, and let test fail non silently when csrf is not found * [Fix] #94, repair overwriting the last data point * fix: upgrade @emotion/react from 11.11.4 to 11.13.0 (#104) Snyk has created this PR to upgrade @emotion/react from 11.11.4 to 11.13.0. See this package in npm: @emotion/react See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade @emotion/styled from 11.11.5 to 11.13.0 (#105) Snyk has created this PR to upgrade @emotion/styled from 11.11.5 to 11.13.0. See this package in npm: @emotion/styled See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade react-router-dom from 6.25.0 to 6.25.1 (#106) Snyk has created this PR to upgrade react-router-dom from 6.25.0 to 6.25.1. See this package in npm: react-router-dom See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade @mui/icons-material from 5.16.4 to 5.16.5 (#107) Snyk has created this PR to upgrade @mui/icons-material from 5.16.4 to 5.16.5. See this package in npm: @mui/icons-material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade express-rate-limit from 7.3.1 to 7.4.0 (#108) Snyk has created this PR to upgrade express-rate-limit from 7.3.1 to 7.4.0. See this package in npm: express-rate-limit See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * 109 marker and line design (#110) * [Task] #109, start polyline * [Task] #94, marker * [Task] #109, gradient color polyline color based on speed * [Task] #109 linter fixes * fix: upgrade react-router-dom from 6.25.1 to 6.26.0 (#113) Snyk has created this PR to upgrade react-router-dom from 6.25.1 to 6.26.0. See this package in npm: react-router-dom See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * fix: upgrade @mui/material from 5.16.5 to 5.16.6 (#112) Snyk has created this PR to upgrade @mui/material from 5.16.5 to 5.16.6. See this package in npm: @mui/material See this project in Snyk: https://app.snyk.io/org/type-style/project/e2bcd002-cb74-409c-ba55-fb6349df1cbc?utm_source=github&utm_medium=referral&page=upgrade-pr Co-authored-by: snyk-bot * Switch polyline (#114) * [Revert] #109 remove polyColor Plugin * [Fix, MultiLine] #109, refactor coloring lines; while fetchinng new data vs reloading MaxSpeed might change the more entries are fetched. Example Testcase and after 6 entries are there, reload and see colors change ... well not with this fix. * [Task] #109, improve polyline display, remove unused code * [Task] #77, change timing to round up, so it "feels" more accurate * [Task] #115, remove SVG Animation on startup based on media Query * [Task] #77 improve test example data * [Task] #77, calculate more Status data * [Task] #77, improve example test data * [Task] #109, line dashed when diff is high, marker start icon when diff is higher * [Task] #77, status design * [Task] #83, forced scheme for map * [Task] #83, change context, mode globally available * [Task] #83, react update, cluster install * [Task, multiline] #83, map tilelayer Introduced new map TileLayers using layers control, and styled it Introduced markerClusterGroup from @changey, since others had issues like broken marker images, or lack for typescript support Refined dashed array styles Addapted context changes, to fetch mode globally, for seperate map theme Markers have none style if neither end or start, to be targeted Introduced Layer array for tilelayers When Layers are changed theme for map is set/updated * [Task] #77 improve responsive design, hide images, status overlays map * [Task] #77, adjust coloring and opacity, used for status * [Task] #83, adjust imports * [Task] #77, changed responsive design for mobile * [Task] #83, extracted to own module, added fly option * [Task] #83, layers extracted, clickable minimap, corrected for mapbox tileSize * Bump webpack from 5.91.0 to 5.94.0 (#117) Bumps [webpack](https://github.com/webpack/webpack) from 5.91.0 to 5.94.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.91.0...v5.94.0) --- updated-dependencies: - dependency-name: webpack dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: snyk-bot --- .eslintrc.json | 4 +- .github/workflows/eslint.yml | 2 + .github/workflows/ftp.yml | 3 + .vscode/settings.json | 6 +- httpdocs/css/base.css | 450 ++ httpdocs/css/colors.css | 95 - httpdocs/css/login.css | 17 +- httpdocs/font/OFL.txt | 95 + httpdocs/font/science-gothic.woff2 | Bin 0 -> 85308 bytes httpdocs/images/marker.svg | 4 + httpdocs/index.html | 57 - httpdocs/js/login.js | 1 - jest.config.js | 2 +- jest.testData.config.js | 10 + package-lock.json | 3948 ++++++++++++++++-- package.json | 50 +- src/app.ts | 9 +- src/cache.ts | 15 - src/client/.eslintrc.json | 32 + src/client/components/App.tsx | 58 + src/client/components/LinearBuffer.tsx | 46 + src/client/components/Map.tsx | 179 + src/client/components/MapCenter.tsx | 16 + src/client/components/MiniMap.tsx | 33 + src/client/components/ModeSwitcher.tsx | 29 + src/client/components/Status.tsx | 146 + src/client/components/removeSvgAnimation.tsx | 28 + src/client/css/login.css | 143 + src/client/css/map.css | 69 + src/client/css/modeSwticher.module.css | 32 + src/client/css/start.css | 241 ++ src/client/css/status.css | 70 + src/client/index.tsx | 27 + src/client/pages/Login.tsx | 213 + src/client/pages/Start.tsx | 183 + src/client/scripts/layers.ts | 48 + src/client/scripts/maxSpeed.ts | 7 + src/client/tsconfig.json | 10 + src/client/types.d.ts | 23 + src/controller/login.ts | 12 +- src/error.ts | 32 - src/models/entry.ts | 34 +- src/scripts/ignore.ts | 4 +- src/scripts/token.ts | 13 +- src/testData/createTestData.test.ts | 70 + src/tests/app.test.ts | 18 +- src/tests/integration.test.ts | 37 +- src/tests/login.test.ts | 26 +- tsconfig.json | 2 +- types.d.ts | 2 +- views/index.ejs | 73 + views/login-form.ejs | 4 +- webpack.config.js | 49 + 53 files changed, 6229 insertions(+), 548 deletions(-) create mode 100644 httpdocs/css/base.css delete mode 100644 httpdocs/css/colors.css create mode 100644 httpdocs/font/OFL.txt create mode 100644 httpdocs/font/science-gothic.woff2 create mode 100644 httpdocs/images/marker.svg delete mode 100644 httpdocs/index.html create mode 100644 jest.testData.config.js delete mode 100644 src/cache.ts create mode 100644 src/client/.eslintrc.json create mode 100644 src/client/components/App.tsx create mode 100644 src/client/components/LinearBuffer.tsx create mode 100644 src/client/components/Map.tsx create mode 100644 src/client/components/MapCenter.tsx create mode 100644 src/client/components/MiniMap.tsx create mode 100644 src/client/components/ModeSwitcher.tsx create mode 100644 src/client/components/Status.tsx create mode 100644 src/client/components/removeSvgAnimation.tsx create mode 100644 src/client/css/login.css create mode 100644 src/client/css/map.css create mode 100644 src/client/css/modeSwticher.module.css create mode 100644 src/client/css/start.css create mode 100644 src/client/css/status.css create mode 100644 src/client/index.tsx create mode 100644 src/client/pages/Login.tsx create mode 100644 src/client/pages/Start.tsx create mode 100644 src/client/scripts/layers.ts create mode 100644 src/client/scripts/maxSpeed.ts create mode 100644 src/client/tsconfig.json create mode 100644 src/client/types.d.ts delete mode 100644 src/error.ts create mode 100644 src/testData/createTestData.test.ts create mode 100644 views/index.ejs create mode 100644 webpack.config.js diff --git a/.eslintrc.json b/.eslintrc.json index aa4c83b..f09bcb4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,7 @@ "root": true, "parser": "@typescript-eslint/parser", "parserOptions": { - "ecmaVersion": 2024, + "ecmaVersion": "latest", "sourceType": "module", "project": "tsconfig.json" }, @@ -22,6 +22,6 @@ //"@typescript-eslint/no-unused-vars": "warn" "jest/no-conditional-expect": "off" }, - "ignorePatterns": ["dist", "jest.config.js", "httpdocs"] + "ignorePatterns": ["dist", "jest.config.js", "httpdocs", "webpack.config.js", "src/client"] } diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 95578d7..d8e79a7 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -19,3 +19,5 @@ jobs: run: npx eslint src/ --fix - name: Lint client-side code run: npx eslint httpdocs/js/ --fix + - name: Lint react code + run: npx eslint src/client/ --fix diff --git a/.github/workflows/ftp.yml b/.github/workflows/ftp.yml index 7d20652..653f6fb 100644 --- a/.github/workflows/ftp.yml +++ b/.github/workflows/ftp.yml @@ -17,6 +17,9 @@ jobs: run: npm i - name: Build run: npm run build:prod + - name: copy views to be deployed + run: | + cp -R views/ dist/ - name: Upload ftp uses: airvzxf/ftp-deployment-action@latest with: diff --git a/.vscode/settings.json b/.vscode/settings.json index 700d626..8d2c763 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,8 @@ { "workbench.editor.enablePreview": false, - "editor.rename.enablePreview": false + "editor.rename.enablePreview": false, + "typescript.tsdk": "node_modules\\typescript\\lib", + "html.format.wrapLineLength": 150, + "javascript.preferences.quoteStyle": "double", + "typescript.preferences.quoteStyle": "double" } \ No newline at end of file diff --git a/httpdocs/css/base.css b/httpdocs/css/base.css new file mode 100644 index 0000000..85d43b8 --- /dev/null +++ b/httpdocs/css/base.css @@ -0,0 +1,450 @@ +@charset "UTF-8"; + +/* --------------------------------------------------------------------- +Project Name: LOREX +------------------------------------------------------------------------ +*1. Reset +*2. Global styles / Variables +*3. Helper styles +*4. Grid styles +*5. Overrides +*6. Media Queries +----------------------------------------------------------------------- */ + +/* ============================== + *1. Reset +================================= */ + +html { + font-size: 62.5%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + text-size-adjust: none; + scroll-behavior: smooth; + color-scheme: light dark; +} +html, textarea, input, button { + font-family: Science-Gothic, sans-serif; + font-kerning: normal; +} +html, body { + height: 100%; +} + + +body, +p, h1, h2, h3, h4, h5, h6, +div, ul, ol, li, dd, dt, dl, table, td, th +blockquote, address, hr, pre, +article, aside, audio, canvas, details, figure, figcaption, footer, header, hgroup, +iframe, main, menu, nav, section, summary, video, +form, fieldset, legend, label, input, textarea { + margin: 0; padding: 0; + box-sizing: border-box; +} +::before, ::after { box-sizing: border-box; } + + +p, li, h1, h2, h3, h4, h5, h6 { + font-weight: normal; + font-size: 1em; + -webkit-text-size-adjust: none; + -ms-text-size-adjust: none; + text-size-adjust: none; + /* -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing : grayscale; */ + + hyphens: auto; + -webkit-hyphenate-limit-lines: 1; + hyphenate-limit-lines: 1; /* consecutive */ + hyphenate-limit-chars: 6 3 3; +} + +a {background-color: inherit;} +a:is(:hover, :active) {text-decoration: underline;} +a:visited {color: #509; /* background-color: #eee; */} +a:active, button:active {outline: none;} + +:focus {outline: 0.1em dotted; outline-offset: 0.1em;} +:focus:not(:focus-visible) { outline: none; } +embed:focus, object:focus, a img {border: none;} + +img, object, embed {display: inline-block; max-width: 100%; vertical-align: baseline;} + +img:-moz-broken, img:-moz-user-disabled {display: none;} + +abbr[title], dfn[title], q {cursor: help; border-bottom: 0.1em dotted;} +input[disabled], textarea[disabled], button[disabled] {cursor: not-allowed;} + +button::-moz-focus-inner, input::-moz-focus-inner { + border: 0; padding: 0; +} + +label[for], button, select, summary, [type=radio], [type=submit], [type=checkbox] { + cursor: pointer; +} +svg.hidden { + position:absolute; + clip:rect(0 0 0 0); + border:0; + margin:-1px; +} + +/* touch devices, and anything other where there is no mouse */ +@media screen and (pointer: coarse) { + label[for] { font-size: 1.05em; } + [type="checkbox"] { width: 1.5rem; height: 1.5rem; } + button { min-height: 3rem; } +} + +/* ============================== + *2. Global styles / Variables +================================= */ + +@font-face { + font-family: 'Science-Gothic'; + src: url('/font/science-gothic.woff2') format('woff2'); /* variable font, no tech or variations here, due to browsers support and no fallback font anyway */ + font-weight: 100 900; + font-stretch: 50% 200%; + unicode-range: U+0020-007E, U+2026; +} + +/* +created by atmos https://app.atmos.style/65cc9eaec76d443c0a796d4b + +** base configuration colors ** +Main: #f90 +Info: #231aee +Danger: #ff0000 +Success: #59ec04 +Neutral: #131211 +*/ +:root, [data-mui-color-scheme="light"] { + --main: oklch(77.2% 0.1738 64.55); + --info: oklch(50% 0.2838 268.01); + --alert: oklch(62.5% 0.2577 29.23); + --success: oklch(77.2% 0.2607 138.96); + --neutral: oklch(25% 0.0026 67.66); + + --bg: color-mix(in oklch, var(--neutral) 20%, white); + --text: color-mix(in oklch, var(--neutral) 20%, black); + --textOnColor: var(--neutral); + --semiBg: #ffffffbb; + --contrastText: white; + --contrastBackground: black; + --semiContrastBackground: #00000077; + + + --baseFontWeightModifier: 50; + + font-weight: calc(400 + var(--baseFontWeightModifier)); + + accent-color: var(--main); + + /* dark theme, initial state (prefers mq) by react */ + &[data-mui-color-scheme="dark"], [data-mui-color-scheme="dark"] { + --main: oklch(75% 0.1738 64.55); + --info: oklch(47.5% 0.2838 268.01); + --alert: oklch(60% 0.2577 29.23); + --success: oklch(75% 0.2607 138.96); + + --bg: color-mix(in oklch, var(--neutral) 20%, black); + --text: color-mix(in oklch, var(--neutral) 20%, white); + --semiBg: #00000055; + + --contrastText: black; + --contrastBackground: white; + --semiContrastBackground: #ffffffbb; + + --baseFontWeightModifier: -50; + } +} + + +/* ============================== + *3. Helper styles +================================= */ + +.visually-hidden { + clip:rect(0 0 0 0); + border:0; + height:1px; + margin:-1px; + overflow:hidden; + padding:0; + position:absolute; + width:1px; +} + +.cut, .cut-after::after { + --cut: 2em; + clip-path: polygon(0% var(--cut), var(--cut) 0%, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%); +} + +.bg { + --bg1: color-mix(in oklch, var(--main) 90%, white); + --bg2: var(--main); + + [data-mui-color-scheme="dark"] & { + --bg1: color-mix(in oklch, var(--neutral) 90%, white); + --bg2: var(--neutral); + } +} +.bg-pattern { + position: absolute; + inset: 0; + width: 100%; height: 100%; + z-index: -1; + filter: url(#rough-light); +} + +.rough-edges { + filter: url(#rough-edges); +} + +.headline { + font-variation-settings: "YOPQ" 32; + font-style: oblique 7.11deg; + font-stretch: 110%; + font-weight: calc(800 + var(--baseFontWeightModifier)); +} + +.fade { animation: fade 1s 2s forwards; } +.fadeIn { animation: reverse fade 1s forwards; } +@keyframes fade { + to { + font-size: 0; + opacity: 0; + } +} + +@media screen and + (prefers-reduced-motion: reduce), + (update: slow) { + :root { + scroll-behavior: auto; + } + * { + animation-duration: 0.001ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.001ms !important; + } + + /* note this does not remove SVG Animations */ +} + +/* development */ +#html:target::before, #html:target::after { + content: ""; + font-size: 200%; + position: fixed; top: 1em; left: 1em; + width: 10em; + padding: 0.5em; + opacity: 0.8; + + border: 0.2em solid red; + background: rgba(255, 50, 50, 0.6); + font-weight: bold; + text-align: center; + text-shadow: 0.1em 0.1em 0.2em #fff; + z-index: 100; +} +#html:target::after { + content: "landscape"; + border-color: blue; + background: rgba(50, 50, 255, 0.6); + left: 14em; +} + + + +/* ============================== + *4. Grid styles +================================= */ + +#react-root { + display: contents; +} + + +/* ============================== + *5. Overrites +================================= */ + +/** MUI OVERWRITES **/ +:root { + &[data-mui-color-scheme="dark"] body { + --mui-palette-common-onBackgroundChannel: 255 255 255; + } + body { + --mui-palette-common-black: black; + --mui-palette-common-white: white; + --mui-palette-common-background: color-mix(in oklch, var(--neutral) 5%, white); + --mui-palette-common-onBackground: color-mix(in oklch, var(--neutral) 40%, black); + --mui-palette-common-backgroundChannel: 255 255 255; + --mui-palette-common-onBackgroundChannel:0 0 0; + --mui-palette-primary-main: var(--main); + --mui-palette-primary-light: color-mix(in oklch, var(--mui-palette-primary-main) 90%, white); + --mui-palette-primary-dark: color-mix(in oklch, var(--mui-palette-primary-main) 90%, black); + --mui-palette-primary-contrastText: var(--textOnColor); + --mui-palette-primary-mainChannel: 255 125 0; + --mui-palette-primary-lightChannel: var(--mui-palette-primary-mainChannel); + --mui-palette-primary-darkChannel: var(--mui-palette-primary-mainChannel); + --mui-palette-primary-contrastTextChannel: 0 0 0; + --mui-palette-secondary-main: color-mix(in oklch, var(--mui-palette-primary-main) 90%, black); + --mui-palette-secondary-light: color-mix(in oklch, var(--mui-palette-secondary-main) 90%, white); + --mui-palette-secondary-dark: color-mix(in oklch, var(--mui-palette-secondary-main) 90%, black); + --mui-palette-secondary-contrastText: var(--mui-palette-common-onBackground); + --mui-palette-secondary-mainChannel: 240 110 0; + --mui-palette-secondary-lightChannel: var(--mui-palette-secondary-mainChannel); + --mui-palette-secondary-darkChannel: var(--mui-palette-secondary-mainChannel); + --mui-palette-secondary-contrastTextChannel: 255 255 255; + --mui-palette-error-main: var(--alert); + --mui-palette-error-light: color-mix(in oklch, var(--mui-palette-error-main) 90%, white); + --mui-palette-error-dark: color-mix(in oklch, var(--mui-palette-error-main) 90%, black); + --mui-palette-error-contrastText: var(--textOnColor); + --mui-palette-error-mainChannel: 255 47 47; + --mui-palette-error-lightChannel: var(--mui-palette-error-mainChannel); + --mui-palette-error-darkChannel: var(--mui-palette-error-mainChannel); + --mui-palette-error-contrastTextChannel: 0 0 0; + --mui-palette-warning-main: var(--mui-palette-primary-main); + --mui-palette-warning-light: var(--mui-palette-primary-main-light); + --mui-palette-warning-dark: var(--mui-palette-primary-main-dark); + --mui-palette-warning-contrastText: var(--mui-palette-primary-contrastText); + --mui-palette-warning-mainChannel: var(--mui-palette-primary-mainChannel); + --mui-palette-warning-lightChannel: var(--mui-palette-primary-mainChannel); + --mui-palette-warning-darkChannel: var(--mui-palette-primary-mainChannel); + --mui-palette-warning-contrastTextChannel: var(--mui-palette-primary-contrastTextChannel); + --mui-palette-info-main: var(--info); + --mui-palette-info-light: color-mix(in oklch, var(--mui-palette-info-main) 90%, white); + --mui-palette-info-dark: color-mix(in oklch, var(--mui-palette-info-main) 90%, black); + --mui-palette-info-contrastText: var(--textOnColor); + --mui-palette-info-mainChannel: 79 71 240; + --mui-palette-info-lightChannel: var(--mui-palette-info-mainChannel); + --mui-palette-info-darkChannel: var(--mui-palette-info-mainChannel); + --mui-palette-info-contrastTextChannel: 255 255 255; + --mui-palette-success-main: var(--success); + --mui-palette-success-light: color-mix(in oklch, var(--mui-palette-success-main) 90%, white); + --mui-palette-success-dark: color-mix(in oklch, var(--mui-palette-success-main) 90%, black); + --mui-palette-success-contrastText: var(--text); + --mui-palette-success-mainChannel: 122 240 50; + --mui-palette-success-lightChannel: var(--mui-palette-success-mainChannel); + --mui-palette-success-darkChannel: var(--mui-palette-success-mainChannel); + --mui-palette-success-contrastTextChannel: 0 0 0; + /* --mui-palette-grey-50: #fafafa; + --mui-palette-grey-100:#f5f5f5; + --mui-palette-grey-200:#eeeeee; + --mui-palette-grey-300:#e0e0e0; + --mui-palette-grey-400:#bdbdbd; + --mui-palette-grey-500:#9e9e9e; + --mui-palette-grey-600:#757575; + --mui-palette-grey-700:#616161; + --mui-palette-grey-800:#424242; + --mui-palette-grey-900:#212121; + --mui-palette-grey-A100:#f5f5f5; + --mui-palette-grey-A200:#eeeeee; + --mui-palette-grey-A400:#bdbdbd; + --mui-palette-grey-A700:#616161; */ + --mui-palette-text-primary: var(--text); + --mui-palette-text-secondary:var(--mui-palette-text-primary); + --mui-palette-text-disabled: color-mix(in oklch, var(--mui-palette-text-primary) 75%, transparent); + --mui-palette-text-primaryChannel: 0 0 0; + --mui-palette-text-secondaryChannel: var(--mui-palette-text-primaryChannel); + --mui-palette-divider: var(--mui-palette-text-disabled); + --mui-palette-background-paper: var(--mui-palette-common-background); + --mui-palette-background-default: var(--mui-palette-common-background); + --mui-palette-background-defaultChannel: 255 255 255; + --mui-palette-background-paperChannel: 255 255 255; + /* --mui-palette-action-active:rgba(0, 0, 0, 0.54); + --mui-palette-action-hover:rgba(0, 0, 0, 0.04); + --mui-palette-action-hoverOpacity:0.04; + --mui-palette-action-selected:rgba(0, 0, 0, 0.08); + --mui-palette-action-selectedOpacity:0.08; + --mui-palette-action-disabled:rgba(0, 0, 0, 0.26); + --mui-palette-action-disabledBackground:rgba(0, 0, 0, 0.12); + --mui-palette-action-disabledOpacity:0.38; + --mui-palette-action-focus:rgba(0, 0, 0, 0.12); + --mui-palette-action-focusOpacity:0.12; + --mui-palette-action-activatedOpacity:0.12; + --mui-palette-action-activeChannel:0 0 0; + --mui-palette-action-selectedChannel:0 0 0; */ + --mui-palette-Alert-errorColor: var(--mui-palette-error-main); + --mui-palette-Alert-infoColor: var(--mui-palette-info-main); + --mui-palette-Alert-successColor: var(--mui-palette-success-main); + --mui-palette-Alert-warningColor: var(--mui-palette-warning-main); + --mui-palette-Alert-errorFilledBg: var(--mui-palette-error-main); + --mui-palette-Alert-infoFilledBg: var(--mui-palette-info-main); + --mui-palette-Alert-successFilledBg: var(--mui-palette-success-main); + --mui-palette-Alert-warningFilledBg: var(--mui-palette-warning-main); + --mui-palette-Alert-errorFilledColor: var(--mui-palette-error-contrastText); + --mui-palette-Alert-infoFilledColor: var(--mui-palette-info-contrastText); + --mui-palette-Alert-successFilledColor: var(--mui-palette-success-contrastText); + --mui-palette-Alert-warningFilledColor: var(--mui-palette-waring-contrastText); + --mui-palette-Alert-errorStandardBg: var(--mui-palette-common-background); + --mui-palette-Alert-infoStandardBg: var(--mui-palette-common-background); + --mui-palette-Alert-successStandardBg: var(--mui-palette-common-background); + --mui-palette-Alert-warningStandardBg: var(--mui-palette-common-background); + --mui-palette-Alert-errorIconColor: var(--mui-palette-error-main); + --mui-palette-Alert-infoIconColor: var(--mui-palette-info-main); + --mui-palette-Alert-successIconColor: var(--mui-palette-success-main); + --mui-palette-Alert-warningIconColor: var(--mui-palette-warning-main); + --mui-palette-AppBar-defaultBg: var(--mui-palette-grey-100); + --mui-palette-Avatar-defaultBg: var(--mui-palette-grey-400); + --mui-palette-Button-inheritContainedBg: var(--mui-palette-grey-300); + --mui-palette-Button-inheritContainedHoverBg: var(--mui-palette-grey-A100); + --mui-palette-Chip-defaultBorder: var(--mui-palette-grey-400); + --mui-palette-Chip-defaultAvatarColor: var(--mui-palette-grey-700); + --mui-palette-Chip-defaultIconColor: var(--mui-palette-grey-700); + /* --mui-palette-FilledInput-bg:rgba(0, 0, 0, 0.06); + --mui-palette-FilledInput-hoverBg:rgba(0, 0, 0, 0.09); + --mui-palette-FilledInput-disabledBg:rgba(0, 0, 0, 0.12); */ + --mui-palette-LinearProgress-primaryBg: color-mix(in oklch, var(--mui-palette-primary-main) 50%, transparent); + --mui-palette-LinearProgress-secondaryBg: color-mix(in oklch, var(--mui-palette-secondary-main) 50%, transparent); + --mui-palette-LinearProgress-errorBg: color-mix(in oklch, var(--mui-error-primary-main) 50%, transparent); + --mui-palette-LinearProgress-infoBg: color-mix(in oklch, var(--mui-palette-info-main) 50%, transparent); + --mui-palette-LinearProgress-successBg: color-mix(in oklch, var(--mui-palette-success-main) 50%, transparent); + --mui-palette-LinearProgress-warningBg: color-mix(in oklch, var(--mui-palette-warning-main) 50%, transparent); + --mui-palette-Skeleton-bg: rgba(var(--mui-palette-text-primaryChannel) / 0.11); + --mui-palette-Slider-primaryTrack: var(--mui-palette-primary-main); + --mui-palette-Slider-secondaryTrack: var(--mui-palette-secondary-main); + --mui-palette-Slider-errorTrack: var(--mui-error-primary-main); + --mui-palette-Slider-infoTrack: var(--mui-palette-info-main); + --mui-palette-Slider-successTrack: var(--mui-palette-success-main); + --mui-palette-Slider-warningTrack: var(--mui-palette-warning-main); + /* --mui-palette-SnackbarContent-bg:rgb(50, 50, 50); + --mui-palette-SnackbarContent-color:#fff; + --mui-palette-SpeedDialAction-fabHoverBg:rgb(216, 216, 216); */ + --mui-palette-StepConnector-border:var(--mui-palette-grey-400); + --mui-palette-StepContent-border: var(--mui-palette-grey-400); + --mui-palette-Switch-defaultColor: var(--mui-palette-common-white); + --mui-palette-Switch-defaultDisabledColor: var(--mui-palette-grey-100); + --mui-palette-Switch-primaryDisabledColor: color-mix(in oklch, var(--mui-palette-primary-main) 85%, transparent); + --mui-palette-Switch-secondaryDisabledColor: color-mix(in oklch, var(--mui-palette-secondary-main) 85%, transparent); + --mui-palette-Switch-errorDisabledColor: color-mix(in oklch, var(--mui-error-primary-main) 85%, transparent); + --mui-palette-Switch-infoDisabledColor: color-mix(in oklch, var(--mui-palette-info-main) 85%, transparent); + --mui-palette-Switch-successDisabledColor: color-mix(in oklch, var(--mui-palette-success-main) 85%, transparent); + --mui-palette-Switch-warningDisabledColor: color-mix(in oklch, var(--mui-palette-warning-main) 85%, transparent); + /* --mui-palette-TableCell-border:rgba(224, 224, 224, 1); + --mui-palette-Tooltip-bg:rgba(97, 97, 97, 0.92); + --mui-palette-dividerChannel:0 0 0; + --mui-opacity-inputPlaceholder:0.42; + --mui-opacity-inputUnderline:0.42; + --mui-opacity-switchTrackDisabled:0.12; + --mui-opacity-switchTrack:0.38; */ + } +} + + + + + +/* ============================== + *6. Media Queries +================================= */ + +@media (min-width: 30em){#html:target::before {content: ">= 480px"; }} +@media (min-width: 48em){#html:target::before {content: ">= 768px"; }} +@media (min-width: 64em){#html:target::before {content: ">= 1024px"; }} +@media (min-width: 75em){#html:target::before {content: ">= 1200px"; }} +@media (min-width: 100em){#html:target::before {content: ">= 1600px"; }} +@media (orientation: portrait) {#html:target::after {content: "portrait"; }} \ No newline at end of file diff --git a/httpdocs/css/colors.css b/httpdocs/css/colors.css deleted file mode 100644 index d77a7fd..0000000 --- a/httpdocs/css/colors.css +++ /dev/null @@ -1,95 +0,0 @@ -/* -created by atmos https://app.atmos.style/65cc9eaec76d443c0a796d4b - -** base configuration colors ** -Main: #f90 -Info: #231aee -Danger: #ff0000 -Success: #59ec04 -Neutral: #131211 -*/ - -[class*=color] { - --lightness: 67.66%; - --hue: 64.55; - --chroma: 0.007; - color: oklch(var(--lightness) var(--chroma) var(--hue)); - - &[class*=l1] {--lightness: 10%;} - &[class*=l2] {--lightness: 25%;} - &[class*=l3] {--lightness: 37.5%;} - &[class*=l4] {--lightness: 50%;} - &[class*=l5] {--lightness: 62.5%;} - &[class*=l6] {--lightness: 77.2%;} - &[class*=l7] {--lightness: 90%;} - - &[class*=main] { - --lightness: 77.2%; - --chroma: 0.1738; - --hue: 64.55; - - &[class*=l1] {--chroma: 0.02;} - &[class*=l2] {--chroma: 0.056;} - &[class*=l3] {--chroma: 0.085;} - &[class*=l4] {--chroma: 0.114;} - &[class*=l5] {--chroma: 0.142;} - &[class*=l6] {--chroma: 0.1738;} /* base */ - &[class*=l7] {--chroma: 0.06;} - } - - &[class*=info] { - --lightness: 44.87%; - --chroma: 0.2838; - --hue: 268.0; - - &[class*=l1] {--chroma: 0.055;} - &[class*=l2] {--chroma: 0.158;} - &[class*=l3] {--chroma: 0.237;} - &[class*=l4] {--chroma: 0.2838;} /* base */ - &[class*=l5] {--chroma: 0.19;} - &[class*=l6] {--chroma: 0.109;} - &[class*=l7] {--chroma: 0.04;} - } - - &[class*=alert] { - --lightness: 62.8%; - --chroma: 0.2577; - --hue: 29.23; - - &[class*=l1] {--chroma: 0.036;} - &[class*=l2] {--chroma: 0.103;} - &[class*=l3] {--chroma: 0.154;} - &[class*=l4] {--chroma: 0.195;} - &[class*=l5] {--chroma: 0.2577;} /* base */ - &[class*=l6] {--chroma: 0.133;} - &[class*=l7] {--chroma: 0.045;} - } - - &[class*=success] { - --lightness: 83%; - --chroma: 0.2607; - --hue: 138.96; - - &[class*=l1] {--chroma: 0.029;} - &[class*=l2] {--chroma: 0.083;} - &[class*=l3] {--chroma: 0.124;} - &[class*=l4] {--chroma: 0.157;} - &[class*=l5] {--chroma: 0.208;} - &[class*=l6] {--chroma: 0.2607;} /* base */ - &[class*=l7] {--chroma: 0.201;} - } - - &[class*=neutral] { - --lightness: 18.3%; - --chroma: 0.0026; - --hue: 67.66; - - &[class*=l1] {--chroma: 0.001;} - &[class*=l2] {--chroma: 0.0026;} /* base */ - &[class*=l3] {--chroma: 0.006;} - &[class*=l4] {--chroma: 0.007;} - &[class*=l5] {--chroma: 0.009;} - &[class*=l6] {--chroma: 0.011;} - &[class*=l7] {--chroma: 0.004;} - } -} diff --git a/httpdocs/css/login.css b/httpdocs/css/login.css index b9d1d7c..2980784 100644 --- a/httpdocs/css/login.css +++ b/httpdocs/css/login.css @@ -1,13 +1,20 @@ form { + font-size: 2rem; margin-inline: auto; - display: flex; - flex-wrap: wrap; - justify-content: space-between; max-width: 500px; - gap: 10px; +} +label { + display: block; + margin-block: 1em; } input, button { - flex-grow: 1; + height: 2em; + display: block; + margin-block: 0.25em 2em; + font-size: inherit; +} +button { + cursor: pointer; } textarea, h1 { flex-basis: 100%; diff --git a/httpdocs/font/OFL.txt b/httpdocs/font/OFL.txt new file mode 100644 index 0000000..737571f --- /dev/null +++ b/httpdocs/font/OFL.txt @@ -0,0 +1,95 @@ +Copyright © 2019–2024 Font Detective LLC + +This Font Software is licensed under the SIL Open Font License, Version 1.1, +with no Reserved Font Name. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org/ + +ADDITIONAL non-font source files are licensed to others under the Apache 2.0 open source license (https://www.apache.org/licenses/LICENSE-2.0). + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/httpdocs/font/science-gothic.woff2 b/httpdocs/font/science-gothic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..948e930bd75a98c4e328d972ca297b9c6e28d4b5 GIT binary patch literal 85308 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πafojw%G_C= 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

GD;u$KKkjJkL{*;U z&(aSN-R%XzkRY704Z-;gZG@26*g#ezh|e^(7ZC2q`*Lj~M%p9E%EC!UF0Bhffgm(* z5X)>tN028my;$qFP}q=|hcUb{naf2If^sbTibQy{`BKK_QyE{brno#%HfC^VIg+H( zOja39&+Lt?DlC|n#j+V9pKJK1IFk40<_(nm9y5yz6c<8#AVV^%Sq}mkAZDltlC;w9U++46M?G7?^?|WvHa| zBt6~Ga;0X + Marker Arrow + + \ No newline at end of file diff --git a/httpdocs/index.html b/httpdocs/index.html deleted file mode 100644 index 99843e4..0000000 --- a/httpdocs/index.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - Welcome Page - - - -

Welcome

- - diff --git a/httpdocs/js/login.js b/httpdocs/js/login.js index 8b13789..e69de29 100644 --- a/httpdocs/js/login.js +++ b/httpdocs/js/login.js @@ -1 +0,0 @@ - diff --git a/jest.config.js b/jest.config.js index 0a57f54..5cada10 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,7 +2,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', - modulePathIgnorePatterns: ['/dist/'], + modulePathIgnorePatterns: ['/dist/', '/src/testData/'], moduleNameMapper: { '^@src/(.*)$': '/src/$1', }, diff --git a/jest.testData.config.js b/jest.testData.config.js new file mode 100644 index 0000000..f8e72a3 --- /dev/null +++ b/jest.testData.config.js @@ -0,0 +1,10 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} */ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + moduleNameMapper: { + '^@src/(.*)$': '/src/$1', + }, + testMatch: ['/src/testData/createTestData.test.ts'], + bail: true +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2953ac7..740c503 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,18 +8,34 @@ "name": "lorex", "version": "0.0.1", "dependencies": { + "@changey/react-leaflet-markercluster": "^4.0.0-rc1", + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.16.5", + "@mui/material": "^5.16.6", + "@types/leaflet-rotatedmarker": "^0.2.5", + "axios": "^1.7.4", "bcrypt": "^5.1.1", "chalk": "^4.1.2", "compression": "^1.7.4", - "ejs": "^3.1.9", + "culori": "^4.0.1", + "dotenv": "^16.4.5", + "ejs": "^3.1.10", "express": "^4.19.2", - "express-rate-limit": "^7.2.0", - "express-slow-down": "^2.0.1", - "express-validator": "^7.0.1", + "express-rate-limit": "^7.4.0", + "express-slow-down": "^2.0.3", + "express-validator": "^7.1.0", "helmet": "^7.1.0", "hpp": "^0.2.3", "jsonwebtoken": "^9.0.2", + "leaflet": "^1.9.4", + "leaflet-defaulticon-compatibility": "^0.1.2", + "leaflet-rotatedmarker": "^0.2.0", "module-alias": "^2.2.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-leaflet": "^4.2.1", + "react-router-dom": "^6.26.0", "toobusy-js": "^0.5.1" }, "devDependencies": { @@ -27,26 +43,37 @@ "@tsconfig/node20": "^20.1.4", "@types/bcrypt": "^5.0.2", "@types/compression": "^1.7.5", + "@types/culori": "^2.1.1", "@types/express": "^4.17.21", "@types/hpp": "^0.2.5", "@types/jest": "^29.5.11", "@types/jsonwebtoken": "^9.0.6", + "@types/leaflet": "^1.9.12", "@types/node": "^20.11.30", + "@types/react": "^18.3.4", + "@types/react-dom": "^18.2.24", "@types/toobusy-js": "^0.5.4", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", - "axios": "^1.6.5", "concurrently": "^8.2.2", - "dotenv": "^16.3.1", + "css-loader": "^7.1.0", "eslint": "^8.56.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.0", "install": "^0.13.0", "jest": "^29.7.0", "nodemon": "^3.0.2", - "npm": "^10.5.0", + "npm": "^10.5.2", + "style-loader": "^4.0.0", "ts-jest": "^29.1.2", + "ts-loader": "^9.5.1", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "webpack": "^5.94.0", + "webpack-cli": "^5.1.4" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -75,7 +102,6 @@ "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", - "dev": true, "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -88,7 +114,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -100,7 +125,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -114,7 +138,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -122,14 +145,12 @@ "node_modules/@babel/code-frame/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -308,7 +329,6 @@ "version": "7.22.15", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, "dependencies": { "@babel/types": "^7.22.15" }, @@ -372,7 +392,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -381,7 +400,6 @@ "version": "7.22.20", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -413,7 +431,6 @@ "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", @@ -427,7 +444,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -439,7 +455,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -453,7 +468,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -461,14 +475,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -666,7 +678,6 @@ "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -745,7 +756,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", - "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -761,6 +771,23 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@changey/react-leaflet-markercluster": { + "version": "4.0.0-rc1", + "resolved": "https://registry.npmjs.org/@changey/react-leaflet-markercluster/-/react-leaflet-markercluster-4.0.0-rc1.tgz", + "integrity": "sha512-gS1lEQiQwyeI6Y6Wuxuqqffwywm7giQw4tbcqtJP8zyT5bc3AzW2/EVJGwWORYo/PLDdDnvOrpI+lUJy2UA5MQ==", + "license": "MIT", + "dependencies": { + "@react-leaflet/core": "^2.0.0", + "leaflet": "^1.8.0", + "leaflet.markercluster": "^1.5.3", + "react-leaflet": "^4.0.0" + }, + "peerDependencies": { + "leaflet": "^1.8.0", + "leaflet.markercluster": "^1.5.3", + "react-leaflet": "^4.0.0" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -773,6 +800,192 @@ "node": ">=12" } }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz", + "integrity": "sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz", + "integrity": "sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, "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", @@ -1341,19 +1554,29 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", @@ -1364,14 +1587,34 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", @@ -1443,6 +1686,230 @@ "node": ">=6" } }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", + "integrity": "sha512-RtsCt4Geed2/v74sbihWzzRs+HsIQCfclHeORh5Ynu2fS4icIKozcSubwuG7vtzq2uW3fOR1zITSP84TNt2GoQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.16.5.tgz", + "integrity": "sha512-bn88xxU/J9UV0s6+eutq7o3TTOrOlbCX+KshFb8kxgIxJZZfYz3JbAXVMivvoMF4Md6jCVUzM9HEkf4Ajab4tw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.16.6.tgz", + "integrity": "sha512-0LUIKBOIjiFfzzFNxXZBRAyr9UQfmTAFzbt6ziOU2FDXhorNN2o3N9/32mNJbCA8zJo2FqFU6d3dtoqUDyIEfA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/core-downloads-tracker": "^5.16.6", + "@mui/system": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.3.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.16.6.tgz", + "integrity": "sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.16.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.6.tgz", + "integrity": "sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.11.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.16.7", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.16.7.tgz", + "integrity": "sha512-Jncvs/r/d/itkxh7O7opOunTqbbSSzMTHzZkNLM+FjAOg+cYAZHrPDlYe1ZGKUYORwwb2XexlWnpZp0kZ4AHuA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.16.6", + "@mui/styled-engine": "^5.16.6", + "@mui/types": "^7.2.15", + "@mui/utils": "^5.16.6", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.15.tgz", + "integrity": "sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.16.6.tgz", + "integrity": "sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "^7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1478,6 +1945,35 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "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/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1610,6 +2106,19 @@ "@types/node": "*" } }, + "node_modules/@types/culori": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/culori/-/culori-2.1.1.tgz", + "integrity": "sha512-NzLYD0vNHLxTdPp8+RlvGbR2NfOZkwxcYGFwxNtm+WH2NuUNV8785zv1h0sulFQ5aFQ9n/jNDUuJeo3Bh7+oFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -1634,6 +2143,12 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.14", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", + "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==", + "license": "MIT" + }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -1698,6 +2213,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "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/jsonwebtoken": { "version": "9.0.6", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", @@ -1707,7 +2228,25 @@ "@types/node": "*" } }, - "node_modules/@types/mime": { + "node_modules/@types/leaflet": { + "version": "1.9.12", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", + "integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/leaflet-rotatedmarker": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@types/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.5.tgz", + "integrity": "sha512-GaKK1bdQ6NYGkVdZj2cHe8Eu1BVf40Jhtmd8pZj5gQSJcTy5iTog0hsMIhf6QQDKnaEgrRJzm4OES6B9vxi4dw==", + "license": "MIT", + "dependencies": { + "@types/leaflet": "*" + } + }, + "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", @@ -1722,6 +2261,16 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" + }, "node_modules/@types/qs": { "version": "6.9.11", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", @@ -1734,6 +2283,33 @@ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, + "node_modules/@types/react": { + "version": "18.3.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", + "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.24", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.24.tgz", + "integrity": "sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -2100,6 +2676,208 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2129,6 +2907,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -2195,6 +2982,15 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2286,11 +3082,56 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "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.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "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", @@ -2300,6 +3141,135 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "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.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz", + "integrity": "sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.1.0", + "es-shim-unscopables": "^1.0.2" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "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.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -2308,20 +3278,52 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "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/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -2374,6 +3376,20 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, "node_modules/babel-preset-current-node-syntax": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", @@ -2473,12 +3489,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2578,7 +3594,6 @@ "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" } @@ -2690,6 +3705,15 @@ "node": ">=10" } }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -2725,12 +3749,35 @@ "node": ">=12" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, - "engines": { + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" } @@ -2765,11 +3812,16 @@ "color-support": "bin.js" } }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "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==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2777,6 +3829,12 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -2917,6 +3975,21 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -2958,6 +4031,124 @@ "node": ">= 8" } }, + "node_modules/css-loader": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.0.tgz", + "integrity": "sha512-VFNj47MAG84MqYDdh9puJG0h98Xs7gEYaX0aeGkfjYqBLB0seOE325sVbqWwaNu3hMZwEP4bB+F4gvF+A63qMA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/culori": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/culori/-/culori-4.0.1.tgz", + "integrity": "sha512-LSnjA6HuIUOlkfKVbzi2OlToZE8OjFi667JWN9qNymXVXzGDmvuP60SSgC+e92sd7B7158f7Fy3Mb6rXS5EDPw==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "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/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/date-fns": { "version": "2.30.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", @@ -3027,11 +4218,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "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==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -3049,6 +4256,15 @@ "node": ">= 0.8" } }, + "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/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -3117,16 +4333,24 @@ "node": ">=6.0.0" } }, + "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/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true, + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/ecdsa-sig-formatter": { @@ -3143,9 +4367,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/ejs": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", - "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dependencies": { "jake": "^10.8.5" }, @@ -3187,15 +4411,99 @@ "node": ">= 0.8" } }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -3215,6 +4523,89 @@ "node": ">= 0.4" } }, + "node_modules/es-iterator-helpers": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.0.tgz", + "integrity": "sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "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", @@ -3233,7 +4624,6 @@ "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" }, @@ -3296,50 +4686,175 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-plugin-jest": { - "version": "27.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", - "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "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": { - "@typescript-eslint/utils": "^5.10.0" + "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-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" + "node": ">=4" }, "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { + "eslint": { "optional": true } } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "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": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "ms": "^2.1.1" } }, - "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { - "version": "5.62.0", + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "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/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "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-jest": { + "version": "27.6.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", + "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "eslint": "^7.0.0 || ^8.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/types": { + "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, @@ -3466,6 +4981,124 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/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/eslint-plugin-react": { + "version": "7.34.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz", + "integrity": "sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlast": "^1.2.4", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.3", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.17", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7", + "object.hasown": "^1.1.3", + "object.values": "^1.1.7", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.10" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "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.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "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/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", @@ -3609,6 +5242,15 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3699,9 +5341,10 @@ } }, "node_modules/express-rate-limit": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.2.0.tgz", - "integrity": "sha512-T7nul1t4TNyfZMJ7pKRKkdeVJWa2CqB8NA1P8BwYaoDI5QSBZARv5oMS43J7b7I5P+4asjVXjb7ONuwDKucahg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.4.0.tgz", + "integrity": "sha512-v1204w3cXu5gCDmAvgvzI6qjzZzoMWKnyVDk3ACgfswTQLYiGen+r8w0VnXnGMmzEN/g8fwIQ4JrFFd4ZP6ssg==", + "license": "MIT", "engines": { "node": ">= 16" }, @@ -3713,9 +5356,10 @@ } }, "node_modules/express-slow-down": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/express-slow-down/-/express-slow-down-2.0.1.tgz", - "integrity": "sha512-zRogSZhNXJYKDBekhgFfFXGrOngH7Fub7Mx2g8OQ4RUBwSJP/3TVEKMgSGR/WlneT0mJ6NBUnidHhIELGVPe3w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/express-slow-down/-/express-slow-down-2.0.3.tgz", + "integrity": "sha512-vATCiFd8uQHtTeK5/Q0nLUukhZh+RV5zkcHxLQr0X5dEFVEYqzVXEe48nW23Z49fwtR+ApD9zn9sZRisTCR99w==", + "license": "MIT", "dependencies": { "express-rate-limit": "7" }, @@ -3723,16 +5367,17 @@ "node": ">= 16" }, "peerDependencies": { - "express": ">= 4" + "express": "4 || 5 || ^5.0.0-beta.1" } }, "node_modules/express-validator": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", - "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.1.0.tgz", + "integrity": "sha512-ePn6NXjHRZiZkwTiU1Rl2hy6aUqmi6Cb4/s8sfUsKH7j2yYl9azSpl8xEHcOj1grzzQ+UBEoLWtE1s6FDxW++g==", + "license": "MIT", "dependencies": { "lodash": "^4.17.21", - "validator": "^13.9.0" + "validator": "~13.12.0" }, "engines": { "node": ">= 8.0.0" @@ -3772,6 +5417,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fastq": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", @@ -3830,9 +5484,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -3858,6 +5512,11 @@ "node": ">= 0.8" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3874,6 +5533,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -3898,7 +5566,6 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -3914,11 +5581,19 @@ } } }, + "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==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3971,20 +5646,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3993,6 +5654,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -4069,6 +5757,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4100,6 +5805,12 @@ "node": ">= 6" } }, + "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==", + "dev": true + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -4115,6 +5826,21 @@ "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", @@ -4158,11 +5884,19 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "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": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -4200,15 +5934,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -4224,6 +5973,19 @@ "node": ">=16.0.0" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/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/hpp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hpp/-/hpp-0.2.3.tgz", @@ -4310,9 +6072,21 @@ "node": ">=0.10.0" } }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { @@ -4329,7 +6103,6 @@ "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" @@ -4392,6 +6165,29 @@ "node": ">= 0.10" } }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -4400,11 +6196,53 @@ "node": ">= 0.10" } }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "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-binary-path": { "version": "2.1.0", @@ -4418,11 +6256,38 @@ "node": ">=8" } }, + "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.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, "dependencies": { "hasown": "^2.0.0" }, @@ -4430,6 +6295,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "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-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4439,6 +6334,18 @@ "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-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -4456,6 +6363,21 @@ "node": ">=6" } }, + "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", @@ -4468,6 +6390,30 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "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", @@ -4477,6 +6423,21 @@ "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", @@ -4486,6 +6447,61 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4498,12 +6514,112 @@ "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.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "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.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -4623,6 +6739,19 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -5207,8 +7336,7 @@ "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==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -5243,8 +7371,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -5296,6 +7423,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "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/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -5324,6 +7466,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5333,6 +7484,50 @@ "node": ">=6" } }, + "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.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + }, + "node_modules/leaflet-defaulticon-compatibility": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/leaflet-defaulticon-compatibility/-/leaflet-defaulticon-compatibility-0.1.2.tgz", + "integrity": "sha512-IrKagWxkTwzxUkFIumy/Zmo3ksjuAu3zEadtOuJcKzuXaD76Gwvg2Z1mLyx7y52ykOzM8rAH5ChBs4DnfdGa6Q==", + "license": "BSD-2-Clause" + }, + "node_modules/leaflet-rotatedmarker": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/leaflet-rotatedmarker/-/leaflet-rotatedmarker-0.2.0.tgz", + "integrity": "sha512-yc97gxLXwbZa+Gk9VCcqI0CkvIBC9oNTTjFsHqq4EQvANrvaboib4UdeQLyTnEqDpaXHCqzwwVIDHtvz2mUiDg==", + "license": "MIT" + }, + "node_modules/leaflet.markercluster": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==", + "license": "MIT", + "peerDependencies": { + "leaflet": "^1.3.1" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -5358,8 +7553,16 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } }, "node_modules/locate-path": { "version": "6.0.0", @@ -5428,6 +7631,17 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "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", @@ -5568,6 +7782,15 @@ "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/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -5620,6 +7843,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "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", @@ -5634,6 +7875,12 @@ "node": ">= 0.6" } }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -5746,9 +7993,9 @@ } }, "node_modules/npm": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.0.tgz", - "integrity": "sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A==", + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.5.2.tgz", + "integrity": "sha512-cHVG7QEJwJdZyOrK0dKX5uf3R5Fd0E8AcmSES1jLtO52UT1enUKZ96Onw/xwq4CbrTZEnDuu2Vf9kCQh/Sd12w==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -5757,6 +8004,7 @@ "@npmcli/map-workspaces", "@npmcli/package-json", "@npmcli/promise-spawn", + "@npmcli/redact", "@npmcli/run-script", "@sigstore/tuf", "abbrev", @@ -5827,27 +8075,28 @@ "@npmcli/arborist": "^7.2.1", "@npmcli/config": "^8.0.2", "@npmcli/fs": "^3.1.0", - "@npmcli/map-workspaces": "^3.0.4", - "@npmcli/package-json": "^5.0.0", + "@npmcli/map-workspaces": "^3.0.6", + "@npmcli/package-json": "^5.0.2", "@npmcli/promise-spawn": "^7.0.1", + "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^7.0.4", - "@sigstore/tuf": "^2.3.1", + "@sigstore/tuf": "^2.3.2", "abbrev": "^2.0.0", "archy": "~1.0.0", "cacache": "^18.0.2", "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", - "cli-table3": "^0.6.3", + "cli-table3": "^0.6.4", "columnify": "^1.6.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", - "glob": "^10.3.10", + "glob": "^10.3.12", "graceful-fs": "^4.2.11", "hosted-git-info": "^7.0.1", - "ini": "^4.1.1", - "init-package-json": "^6.0.0", - "is-cidr": "^5.0.3", + "ini": "^4.1.2", + "init-package-json": "^6.0.2", + "is-cidr": "^5.0.5", "json-parse-even-better-errors": "^3.0.1", "libnpmaccess": "^8.0.1", "libnpmdiff": "^6.0.3", @@ -5861,11 +8110,11 @@ "libnpmteam": "^6.0.0", "libnpmversion": "^5.0.1", "make-fetch-happen": "^13.0.0", - "minimatch": "^9.0.3", + "minimatch": "^9.0.4", "minipass": "^7.0.4", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^10.0.1", + "node-gyp": "^10.1.0", "nopt": "^7.2.0", "normalize-package-data": "^6.0.0", "npm-audit-report": "^5.0.0", @@ -5873,7 +8122,7 @@ "npm-package-arg": "^11.0.1", "npm-pick-manifest": "^9.0.0", "npm-profile": "^9.0.0", - "npm-registry-fetch": "^16.1.0", + "npm-registry-fetch": "^16.2.0", "npm-user-validate": "^2.0.0", "npmlog": "^7.0.1", "p-map": "^4.0.0", @@ -5881,12 +8130,12 @@ "parse-conflict-json": "^3.0.1", "proc-log": "^3.0.0", "qrcode-terminal": "^0.12.0", - "read": "^2.1.0", + "read": "^3.0.1", "semver": "^7.6.0", - "spdx-expression-parse": "^3.0.1", + "spdx-expression-parse": "^4.0.0", "ssri": "^10.0.5", "supports-color": "^9.4.0", - "tar": "^6.2.0", + "tar": "^6.2.1", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "treeverse": "^3.0.0", @@ -5998,7 +8247,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/@npmcli/agent": { - "version": "2.2.1", + "version": "2.2.2", "dev": true, "inBundle": true, "license": "ISC", @@ -6007,14 +8256,14 @@ "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.1" + "socks-proxy-agent": "^8.0.3" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "7.4.0", + "version": "7.4.2", "dev": true, "inBundle": true, "license": "ISC", @@ -6028,6 +8277,7 @@ "@npmcli/node-gyp": "^3.0.0", "@npmcli/package-json": "^5.0.0", "@npmcli/query": "^3.1.0", + "@npmcli/redact": "^1.1.0", "@npmcli/run-script": "^7.0.2", "bin-links": "^4.0.1", "cacache": "^18.0.0", @@ -6035,12 +8285,12 @@ "hosted-git-info": "^7.0.1", "json-parse-even-better-errors": "^3.0.0", "json-stringify-nice": "^1.1.4", - "minimatch": "^9.0.0", + "minimatch": "^9.0.4", "nopt": "^7.0.0", "npm-install-checks": "^6.2.0", "npm-package-arg": "^11.0.1", "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^16.0.0", + "npm-registry-fetch": "^16.2.0", "npmlog": "^7.0.1", "pacote": "^17.0.4", "parse-conflict-json": "^3.0.0", @@ -6061,14 +8311,14 @@ } }, "node_modules/npm/node_modules/@npmcli/config": { - "version": "8.2.0", + "version": "8.2.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "@npmcli/map-workspaces": "^3.0.2", "ci-info": "^4.0.0", - "ini": "^4.1.0", + "ini": "^4.1.2", "nopt": "^7.0.0", "proc-log": "^3.0.0", "read-package-json-fast": "^3.0.2", @@ -6119,7 +8369,7 @@ } }, "node_modules/npm/node_modules/@npmcli/git": { - "version": "5.0.4", + "version": "5.0.5", "dev": true, "inBundle": true, "license": "ISC", @@ -6154,7 +8404,7 @@ } }, "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "3.0.4", + "version": "3.0.6", "dev": true, "inBundle": true, "license": "ISC", @@ -6202,7 +8452,7 @@ } }, "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "5.0.0", + "version": "5.0.2", "dev": true, "inBundle": true, "license": "ISC", @@ -6243,6 +8493,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/npm/node_modules/@npmcli/run-script": { "version": "7.0.4", "dev": true, @@ -6270,19 +8529,19 @@ } }, "node_modules/npm/node_modules/@sigstore/bundle": { - "version": "2.2.0", + "version": "2.3.1", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/protobuf-specs": "^0.3.0" + "@sigstore/protobuf-specs": "^0.3.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/@sigstore/core": { - "version": "1.0.0", + "version": "1.1.0", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -6291,23 +8550,23 @@ } }, "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.0", + "version": "0.3.1", "dev": true, "inBundle": true, "license": "Apache-2.0", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/@sigstore/sign": { - "version": "2.2.3", + "version": "2.3.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.2.0", + "@sigstore/bundle": "^2.3.0", "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0", + "@sigstore/protobuf-specs": "^0.3.1", "make-fetch-happen": "^13.0.0" }, "engines": { @@ -6315,7 +8574,7 @@ } }, "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "2.3.1", + "version": "2.3.2", "dev": true, "inBundle": true, "license": "Apache-2.0", @@ -6328,14 +8587,14 @@ } }, "node_modules/npm/node_modules/@sigstore/verify": { - "version": "1.1.0", + "version": "1.2.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.2.0", - "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0" + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -6373,7 +8632,7 @@ } }, "node_modules/npm/node_modules/agent-base": { - "version": "7.1.0", + "version": "7.1.1", "dev": true, "inBundle": true, "license": "MIT", @@ -6461,12 +8720,15 @@ } }, "node_modules/npm/node_modules/binary-extensions": { - "version": "2.2.0", + "version": "2.3.0", "dev": true, "inBundle": true, "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/npm/node_modules/brace-expansion": { @@ -6479,7 +8741,7 @@ } }, "node_modules/npm/node_modules/builtins": { - "version": "5.0.1", + "version": "5.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -6547,7 +8809,7 @@ } }, "node_modules/npm/node_modules/cidr-regex": { - "version": "4.0.3", + "version": "4.0.5", "dev": true, "inBundle": true, "license": "BSD-2-Clause", @@ -6581,7 +8843,7 @@ } }, "node_modules/npm/node_modules/cli-table3": { - "version": "0.6.3", + "version": "0.6.4", "dev": true, "inBundle": true, "license": "MIT", @@ -6859,16 +9121,16 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "10.3.10", + "version": "10.3.12", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", + "jackspeak": "^2.3.6", "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" }, "bin": { "glob": "dist/esm/bin.mjs" @@ -6893,7 +9155,7 @@ "license": "ISC" }, "node_modules/npm/node_modules/hasown": { - "version": "2.0.1", + "version": "2.0.2", "dev": true, "inBundle": true, "license": "MIT", @@ -6992,7 +9254,7 @@ } }, "node_modules/npm/node_modules/ini": { - "version": "4.1.1", + "version": "4.1.2", "dev": true, "inBundle": true, "license": "ISC", @@ -7001,15 +9263,15 @@ } }, "node_modules/npm/node_modules/init-package-json": { - "version": "6.0.0", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { + "@npmcli/package-json": "^5.0.0", "npm-package-arg": "^11.0.0", "promzard": "^1.0.0", - "read": "^2.0.0", - "read-package-json": "^7.0.0", + "read": "^3.0.1", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "^5.0.0" @@ -7050,12 +9312,12 @@ } }, "node_modules/npm/node_modules/is-cidr": { - "version": "5.0.3", + "version": "5.0.5", "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { - "cidr-regex": "4.0.3" + "cidr-regex": "^4.0.4" }, "engines": { "node": ">=14" @@ -7158,20 +9420,20 @@ "license": "MIT" }, "node_modules/npm/node_modules/libnpmaccess": { - "version": "8.0.2", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "npm-package-arg": "^11.0.1", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^16.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmdiff": { - "version": "6.0.7", + "version": "6.0.9", "dev": true, "inBundle": true, "license": "ISC", @@ -7179,19 +9441,19 @@ "@npmcli/arborist": "^7.2.1", "@npmcli/disparity-colors": "^3.0.0", "@npmcli/installed-package-contents": "^2.0.2", - "binary-extensions": "^2.2.0", + "binary-extensions": "^2.3.0", "diff": "^5.1.0", - "minimatch": "^9.0.0", + "minimatch": "^9.0.4", "npm-package-arg": "^11.0.1", "pacote": "^17.0.4", - "tar": "^6.2.0" + "tar": "^6.2.1" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "7.0.8", + "version": "7.0.10", "dev": true, "inBundle": true, "license": "ISC", @@ -7203,7 +9465,7 @@ "npmlog": "^7.0.1", "pacote": "^17.0.4", "proc-log": "^3.0.0", - "read": "^2.0.0", + "read": "^3.0.1", "read-package-json-fast": "^3.0.2", "semver": "^7.3.7", "walk-up-path": "^3.0.1" @@ -7213,7 +9475,7 @@ } }, "node_modules/npm/node_modules/libnpmfund": { - "version": "5.0.5", + "version": "5.0.7", "dev": true, "inBundle": true, "license": "ISC", @@ -7225,33 +9487,33 @@ } }, "node_modules/npm/node_modules/libnpmhook": { - "version": "10.0.1", + "version": "10.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^16.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmorg": { - "version": "6.0.2", + "version": "6.0.3", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^16.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmpack": { - "version": "6.0.7", + "version": "6.0.9", "dev": true, "inBundle": true, "license": "ISC", @@ -7266,7 +9528,7 @@ } }, "node_modules/npm/node_modules/libnpmpublish": { - "version": "9.0.4", + "version": "9.0.5", "dev": true, "inBundle": true, "license": "ISC", @@ -7274,7 +9536,7 @@ "ci-info": "^4.0.0", "normalize-package-data": "^6.0.0", "npm-package-arg": "^11.0.1", - "npm-registry-fetch": "^16.0.0", + "npm-registry-fetch": "^16.2.0", "proc-log": "^3.0.0", "semver": "^7.3.7", "sigstore": "^2.2.0", @@ -7285,25 +9547,25 @@ } }, "node_modules/npm/node_modules/libnpmsearch": { - "version": "7.0.1", + "version": "7.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^16.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm/node_modules/libnpmteam": { - "version": "6.0.1", + "version": "6.0.2", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { "aproba": "^2.0.0", - "npm-registry-fetch": "^16.0.0" + "npm-registry-fetch": "^16.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -7357,7 +9619,7 @@ } }, "node_modules/npm/node_modules/minimatch": { - "version": "9.0.3", + "version": "9.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -7565,7 +9827,7 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "10.0.1", + "version": "10.1.0", "dev": true, "inBundle": true, "license": "MIT", @@ -7716,11 +9978,12 @@ } }, "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "16.1.0", + "version": "16.2.0", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { + "@npmcli/redact": "^1.1.0", "make-fetch-happen": "^13.0.0", "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", @@ -7828,12 +10091,12 @@ } }, "node_modules/npm/node_modules/path-scurry": { - "version": "1.10.1", + "version": "1.10.2", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", + "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { @@ -7844,7 +10107,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.0.15", + "version": "6.0.16", "dev": true, "inBundle": true, "license": "MIT", @@ -7903,12 +10166,12 @@ } }, "node_modules/npm/node_modules/promzard": { - "version": "1.0.0", + "version": "1.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "read": "^2.0.0" + "read": "^3.0.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -7923,12 +10186,12 @@ } }, "node_modules/npm/node_modules/read": { - "version": "2.1.0", + "version": "3.0.1", "dev": true, "inBundle": true, "license": "ISC", "dependencies": { - "mute-stream": "~1.0.0" + "mute-stream": "^1.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -8054,17 +10317,17 @@ } }, "node_modules/npm/node_modules/sigstore": { - "version": "2.2.2", + "version": "2.3.0", "dev": true, "inBundle": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.2.0", + "@sigstore/bundle": "^2.3.1", "@sigstore/core": "^1.0.0", - "@sigstore/protobuf-specs": "^0.3.0", - "@sigstore/sign": "^2.2.3", + "@sigstore/protobuf-specs": "^0.3.1", + "@sigstore/sign": "^2.3.0", "@sigstore/tuf": "^2.3.1", - "@sigstore/verify": "^1.1.0" + "@sigstore/verify": "^1.2.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -8081,7 +10344,7 @@ } }, "node_modules/npm/node_modules/socks": { - "version": "2.8.0", + "version": "2.8.3", "dev": true, "inBundle": true, "license": "MIT", @@ -8090,17 +10353,17 @@ "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 16.0.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.2", + "version": "8.0.3", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "agent-base": "^7.0.2", + "agent-base": "^7.1.1", "debug": "^4.3.4", "socks": "^2.7.1" }, @@ -8118,6 +10381,16 @@ "spdx-license-ids": "^3.0.0" } }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/npm/node_modules/spdx-exceptions": { "version": "2.5.0", "dev": true, @@ -8125,7 +10398,7 @@ "license": "CC-BY-3.0" }, "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "3.0.1", + "version": "4.0.0", "dev": true, "inBundle": true, "license": "MIT", @@ -8219,7 +10492,7 @@ } }, "node_modules/npm/node_modules/tar": { - "version": "6.2.0", + "version": "6.2.1", "dev": true, "inBundle": true, "license": "ISC", @@ -8343,6 +10616,16 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/npm/node_modules/validate-npm-package-name": { "version": "5.0.0", "dev": true, @@ -8549,6 +10832,113 @@ "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.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "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.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -8651,7 +11041,6 @@ "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" }, @@ -8663,7 +11052,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -8714,8 +11102,7 @@ "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 + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "0.1.7", @@ -8726,7 +11113,6 @@ "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" } @@ -8822,6 +11208,121 @@ "node": ">=8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "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.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", + "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "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", @@ -8870,6 +11371,21 @@ "node": ">= 6" } }, + "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/prop-types/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/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -8885,8 +11401,7 @@ "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==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pstree.remy": { "version": "1.1.8", @@ -8953,6 +11468,15 @@ } ] }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -8966,20 +11490,105 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "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-router": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.19.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" }, "engines": { - "node": ">= 0.8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "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/readable-stream": { "version": "3.6.2", @@ -9006,11 +11615,61 @@ "node": ">=8.10.0" } }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "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.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/require-directory": { "version": "2.1.1", @@ -9025,7 +11684,6 @@ "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9063,7 +11721,6 @@ "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" } @@ -9139,6 +11796,24 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -9158,11 +11833,55 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -9205,6 +11924,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -9240,11 +11968,38 @@ "node": ">= 0.4" } }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9333,6 +12088,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -9418,6 +12182,81 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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", @@ -9459,44 +12298,182 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "dev": true, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser": { + "version": "5.30.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.3.tgz", + "integrity": "sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/terser-webpack-plugin/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/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=4" + "node": ">= 10.13.0" } }, - "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==", + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "node_modules/test-exclude": { @@ -9529,7 +12506,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -9643,6 +12619,35 @@ } } }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -9686,6 +12691,39 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/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/tsconfig-paths/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/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -9752,6 +12790,79 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", @@ -9765,6 +12876,21 @@ "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/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -9868,9 +12994,10 @@ } }, "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -9892,11 +13019,169 @@ "makeerror": "1.0.12" } }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, + "node_modules/webpack": { + "version": "5.94.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", + "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -9921,6 +13206,85 @@ "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.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -9929,6 +13293,12 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -9978,6 +13348,14 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 4e3216f..83797bd 100644 --- a/package.json +++ b/package.json @@ -5,16 +5,19 @@ "main": "index.js", "scripts": { "prebuild": "rm -rf dist/*", - "build": "npx tsc", - "build:prod": "npx tsc -p ./tsconfig.prod.json", + "build": "tsc && webpack", + "build:prod": "tsc -p ./tsconfig.prod.json && webpack --mode production", "postbuild": "cp -R httpdocs/ dist/", "start": "node dist/app.js", "dev": "npm run prebuild && npm run postbuild && concurrently \"npm:dev:*\"", "dev:ts": "nodemon --config nodemon-ts.json", "dev:static": "nodemon --config nodemon-static.json", + "dev:webpack": "webpack --watch", "lint": "eslint . --fix", "lint:client": "eslint httpdocs/js/ --fix", + "lint:react": "eslint src/client/ --fix", "test": "jest", + "test:data": "jest --config jest.testData.config.js", "test:app": "jest src/tests/app.test.ts", "test:login": "jest src/tests/login.test.ts", "test:unit": "jest src/tests/unit.test.ts", @@ -27,40 +30,67 @@ "@tsconfig/node20": "^20.1.4", "@types/bcrypt": "^5.0.2", "@types/compression": "^1.7.5", + "@types/culori": "^2.1.1", "@types/express": "^4.17.21", "@types/hpp": "^0.2.5", "@types/jest": "^29.5.11", "@types/jsonwebtoken": "^9.0.6", + "@types/leaflet": "^1.9.12", "@types/node": "^20.11.30", + "@types/react": "^18.3.4", + "@types/react-dom": "^18.2.24", "@types/toobusy-js": "^0.5.4", "@typescript-eslint/eslint-plugin": "^6.18.1", "@typescript-eslint/parser": "^6.18.1", - "axios": "^1.6.5", "concurrently": "^8.2.2", - "dotenv": "^16.3.1", + "css-loader": "^7.1.0", "eslint": "^8.56.0", + "eslint-plugin-import": "^2.29.1", "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.0", "install": "^0.13.0", "jest": "^29.7.0", "nodemon": "^3.0.2", - "npm": "^10.5.0", + "npm": "^10.5.2", + "style-loader": "^4.0.0", "ts-jest": "^29.1.2", + "ts-loader": "^9.5.1", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "webpack": "^5.94.0", + "webpack-cli": "^5.1.4" }, "dependencies": { + "@changey/react-leaflet-markercluster": "^4.0.0-rc1", + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.11.5", + "@mui/icons-material": "^5.16.5", + "@mui/material": "^5.16.6", + "@types/leaflet-rotatedmarker": "^0.2.5", + "axios": "^1.7.4", "bcrypt": "^5.1.1", "chalk": "^4.1.2", "compression": "^1.7.4", - "ejs": "^3.1.9", + "culori": "^4.0.1", + "dotenv": "^16.4.5", + "ejs": "^3.1.10", "express": "^4.19.2", - "express-rate-limit": "^7.2.0", - "express-slow-down": "^2.0.1", - "express-validator": "^7.0.1", + "express-rate-limit": "^7.4.0", + "express-slow-down": "^2.0.3", + "express-validator": "^7.1.0", "helmet": "^7.1.0", "hpp": "^0.2.3", "jsonwebtoken": "^9.0.2", + "leaflet": "^1.9.4", + "leaflet-defaulticon-compatibility": "^0.1.2", + "leaflet-rotatedmarker": "^0.2.0", "module-alias": "^2.2.3", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-leaflet": "^4.2.1", + "react-router-dom": "^6.26.0", "toobusy-js": "^0.5.1" }, "_moduleAliases": { diff --git a/src/app.ts b/src/app.ts index 17afecb..92bc792 100644 --- a/src/app.ts +++ b/src/app.ts @@ -19,6 +19,7 @@ import { cleanupCSRF } from "@src/scripts/token"; config(); // dotenv const app = express(); +app.disable("x-powered-by"); app.set('view engine', 'ejs'); @@ -38,7 +39,9 @@ app.use((req, res, next) => { // clean up IPv6 Addresses } }) -app.use(helmet({ contentSecurityPolicy: { directives: { "default-src": "'self'", "img-src": "*" } } })); +if (process.env.NODE_ENV != "development") { + app.use(helmet({ contentSecurityPolicy: { directives: { "default-src": "'self'", "img-src": "*" } } })); +} app.use(cache); app.use(compression()) app.use(hpp()); @@ -52,9 +55,9 @@ app.use((req, res, next) => { // limit body for specific http methods // routes -app.get('/', (req, res) => { +app.get(['/', '/login'], (req, res) => { logger.log(req.ip + " - " + res.locals.ip, true); - res.send('Hello World, via TypeScript and Node.js! ' + `ENV: ${process.env.NODE_ENV}`); + res.render("index"); }); app.use('/write', writeRouter); diff --git a/src/cache.ts b/src/cache.ts deleted file mode 100644 index c64ae4a..0000000 --- a/src/cache.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Request, Response, NextFunction } from 'express'; - -const setCache = function (req: Request, res: Response, next: NextFunction) { - const seconds = 60 * 5; // 5 minuits - - // cache get requests but nothing else - if (req.method == "GET") { - res.set("Cache-control", `public, max-age=${seconds}`); - } else { - res.set("Cache-control", 'no-store'); - } - - next(); -} -export default setCache; \ No newline at end of file diff --git a/src/client/.eslintrc.json b/src/client/.eslintrc.json new file mode 100644 index 0000000..fe23f14 --- /dev/null +++ b/src/client/.eslintrc.json @@ -0,0 +1,32 @@ +{ + "root": true, + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "plugin:react/recommended", + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "react", + "@typescript-eslint" + ], + "settings": { + "react": { + "version": "detect" + } + }, + "rules": { + //"react/jsx-key": false + } +} \ No newline at end of file diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx new file mode 100644 index 0000000..6229027 --- /dev/null +++ b/src/client/components/App.tsx @@ -0,0 +1,58 @@ +import React, { createContext, useEffect, useState } from 'react'; +import { createBrowserRouter, RouterProvider } from "react-router-dom"; +import { useColorScheme } from '@mui/material/styles'; +import { useMediaQuery } from '@mui/material'; +import Start from '../pages/Start'; +import Login from '../pages/Login'; + +export const Context = createContext([]); + +export function convertJwt() { + const token = localStorage?.jwt; + if (!token) { return false } + try { + const { user, exp } = JSON.parse(window.atob(token.split('.')[1])); + return { user, exp }; + } catch (error) { + console.error("Unable to parse JWT Data"); + return false; + } +} + +function loginDefault(userInfo) { + if (!userInfo) { return false; } + + const date = new Date(); + const exp = userInfo.exp + return date.getTime() / 1000 <= exp; +} + +const router = createBrowserRouter([ + { + path: "/", + element: , + }, + { + path: "/login", + element: , + } +]); + +const App = () => { + const [userInfo, setUserInfo] = useState(convertJwt()); + const [isLoggedIn, setLogin] = useState(loginDefault(userInfo)); + const { mode, setMode } = useColorScheme(); + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); + + useEffect(() => { + setMode(prefersDarkMode ? "dark" : "light"); + }, [prefersDarkMode, setMode]); + + return ( + + + + ); +} + +export default App; \ No newline at end of file diff --git a/src/client/components/LinearBuffer.tsx b/src/client/components/LinearBuffer.tsx new file mode 100644 index 0000000..3b6bc86 --- /dev/null +++ b/src/client/components/LinearBuffer.tsx @@ -0,0 +1,46 @@ +import * as React from 'react'; +import LinearProgress from '@mui/material/LinearProgress'; + +export default function LinearBuffer({ msStart, msFinish, variant = "buffer" }: { msStart: number, msFinish: number, variant?: "buffer" | "determinate" }) { + const [progress, setProgress] = React.useState(0); + const [buffer, setBuffer] = React.useState(10); + + const progressRef = React.useRef(() => { }); + React.useEffect(() => { + if (!msStart || !msFinish) { + console.log("LinearProgress did not recieve correct data") + } + progressRef.current = () => { + let progressValue; + const duration = msFinish - msStart; // duration based on input props + const date = new Date(); + const now = date.getTime(); + const progressCalcValue = ((now - msStart) / duration) * 100; + progressValue = progressCalcValue; + if (variant == "buffer") { + const secondPhase = duration == 1000; + const bufferValue = secondPhase ? 100 : 90; + progressValue = secondPhase ? 100 : Math.min(progressCalcValue, bufferValue); + + setBuffer(bufferValue); + } + + setProgress(progressValue); + + }; + }); + + React.useEffect(() => { + const timer = setInterval(() => { + progressRef.current(); + }, 300); + + return () => { + clearInterval(timer); + }; + }, []); + + return ( + + ); +} \ No newline at end of file diff --git a/src/client/components/Map.tsx b/src/client/components/Map.tsx new file mode 100644 index 0000000..9882e0f --- /dev/null +++ b/src/client/components/Map.tsx @@ -0,0 +1,179 @@ +import React, { useContext, useState } from 'react' +import { Context } from "../components/App"; +import { LayersControl, MapContainer, Marker, Polyline, Popup, TileLayer, useMap, useMapEvents } from 'react-leaflet' +import { toGamut, parse, Oklch, formatCss } from 'culori'; +import L from 'leaflet'; +import 'leaflet-rotatedmarker'; +import 'leaflet/dist/leaflet.css'; +import "../css/map.css"; +import { getMaxSpeed } from "../scripts/maxSpeed"; +import { layers } from "../scripts/layers"; +import MarkerClusterGroup from "@changey/react-leaflet-markercluster"; +import "@changey/react-leaflet-markercluster/dist/styles.min.css"; +import { MapRecenter } from "./MapCenter"; + +const MultiColorPolyline = ({ cleanEntries }: { cleanEntries: Models.IEntry[] }) => { + const [useRelativeColors] = useState(true); // Change candidate; Use color in range to maximum speed, like from 0 to max, rather than fixed range + + let maxSpeed = 0; + const startColor = parse('oklch(62.8% 0.2577 29.23)') as Oklch; // red + const calculateHue = function (baseHue, maxSpeed, currentSpeed) { + // range of currentSpeed and maxSpeed transfered to range from 0 to 360 + const hueOffset = (currentSpeed / maxSpeed) * 360; + // add baseHue to the hueOffset and overflow at 360 + return (baseHue + hueOffset) % 360; + } + + if (useRelativeColors) { + maxSpeed = getMaxSpeed(cleanEntries); + } + + return cleanEntries.map((entry, index) => { + if (!index) { return false; } + const previousEntry = cleanEntries[index - 1]; + const color = startColor; + const currentSpeed = entry.speed.gps * 3.6; // convert to km/h + + color.h = calculateHue(color.h, maxSpeed, currentSpeed); + color.l = currentSpeed > maxSpeed * 0.75 ? color.l = currentSpeed / maxSpeed : color.l; + + const correctedColor = toGamut('rgb', 'oklch', null)(color); // map OKLCH to the RGB gamut + + let strokeDashArray = null; + + if (entry.time.diff > 100) { strokeDashArray = "4 8"; } + return () + }); +} + +function Map({ entries }: { entries: Models.IEntry[] }) { + if (!entries?.length) { + return No Data to be displayed + } + const [, , , , mode] = useContext(Context); + const [mapStyle, setMapStyle] = useState(mode); + + const lastEntry = entries.at(-1); + const cleanEntries = entries.filter((entry) => !entry.ignore); + const cleanEntriesWithoutLast = cleanEntries.slice(0, -1); + + + + // Function to create custom icon with dynamic className + function createCustomIcon(entry: Models.IEntry) { + let className = "none"; + let iconSize = 14; + if (entry.index == 0 || entry.time.diff >= 300) { + className = "start" + } + if (entry == lastEntry) { + className = "end" + } + + if (className != "none") { + iconSize = 22; + } + + return L.divIcon({ + html: ` + + Marker Arrow + + `, + shadowUrl: null, + shadowSize: null, + shadowAnchor: null, + iconSize: [iconSize, iconSize], + iconAnchor: [iconSize / 2, iconSize / 2], + popupAnchor: [0, 0], + className: `customMarkerIcon ${className}`, + }); + } + + // custom hook to handle map events and track active layer + // used to switch marker design + const LayerChangeHandler = () => { + useMapEvents({ + baselayerchange: (event) => { + const newLayer = layers.filter((layer) => layer.name == event.name); + if (newLayer[0].markerStyle != mapStyle) { + setMapStyle(newLayer[0].markerStyle); + } + }, + }); + return null; + }; + + + return ( +
+ + + + + {layers.map((layer, index) => { + return ( + + + + ) + })} + + + + {cleanEntriesWithoutLast.map((entry) => { + return ( + + +
{JSON.stringify(entry, null, 2)}
+
+
+ ) + })} +
+ + + {/* lastEntry */} + + +
{JSON.stringify(lastEntry, null, 2)}
+
+
+ + +
+
+ ) +} + +export default Map diff --git a/src/client/components/MapCenter.tsx b/src/client/components/MapCenter.tsx new file mode 100644 index 0000000..9847261 --- /dev/null +++ b/src/client/components/MapCenter.tsx @@ -0,0 +1,16 @@ +import { useEffect } from 'react' +import { useMap } from "react-leaflet"; + +// Used to recenter the map to new coordinates +export const MapRecenter = ({ lat, lon, zoom, fly }: { lat: number, lon: number, zoom: number, fly: boolean }) => { + const map = useMap(); + useEffect(() => { + // Fly to that coordinates and set new zoom level + if (fly) { + map.flyTo([lat, lon], zoom); + } else { + map.setView([lat, lon], zoom); + } + }, [lat, lon]); + return null; +}; \ No newline at end of file diff --git a/src/client/components/MiniMap.tsx b/src/client/components/MiniMap.tsx new file mode 100644 index 0000000..ddac239 --- /dev/null +++ b/src/client/components/MiniMap.tsx @@ -0,0 +1,33 @@ +import React from 'react' +import { MapContainer, TileLayer } from "react-leaflet"; +import { MapRecenter } from "./MapCenter"; + +export default function MiniMap({ layer, lastEntry, index }: client.MiniMapProps) { + function handleClick() { + const elements = document.querySelectorAll('input.leaflet-control-layers-selector'); + const el = elements[index] as HTMLInputElement | null; + if (!elements || !el) { return; } + + el.click(); + } + + return ( +
+ + + + +
); +} diff --git a/src/client/components/ModeSwitcher.tsx b/src/client/components/ModeSwitcher.tsx new file mode 100644 index 0000000..f8f6523 --- /dev/null +++ b/src/client/components/ModeSwitcher.tsx @@ -0,0 +1,29 @@ +import React, { useContext} from 'react'; +import { Context } from "../components/App"; +import { Button } from '@mui/material'; +import { LightMode, Nightlight } from '@mui/icons-material'; +import * as css from "../css/modeSwticher.module.css"; + +function ModeSwitcher() { + const [, , , , mode, setMode] = useContext(Context); + + return ( + + ); +} + + +export default ModeSwitcher; diff --git a/src/client/components/Status.tsx b/src/client/components/Status.tsx new file mode 100644 index 0000000..6dd5c88 --- /dev/null +++ b/src/client/components/Status.tsx @@ -0,0 +1,146 @@ +import React from 'react' +import { getMaxSpeed } from "../scripts/maxSpeed"; +import "../css/status.css"; +import StorageIcon from '@mui/icons-material/Storage'; +import NetworkCheckIcon from '@mui/icons-material/NetworkCheck'; +import SpeedIcon from '@mui/icons-material/Speed'; +import BoltIcon from '@mui/icons-material/Bolt'; +import ShowChartIcon from '@mui/icons-material/ShowChart'; +import EastIcon from '@mui/icons-material/East'; + +function getStatusData(entries) { + const cleanEntries = entries.filter((entry: Models.IEntry) => !entry.ignore); + + function getMean(prop) { + const props = prop.split('.'); + let divider = 0; // cannot be hardcoded to cleanEntries.length because some properties don't exist on first or last dataPoint + const value = cleanEntries.reduce((accumulatorValue, current) => { + // find potentially nested value + let value = current; // overwritten recursively, start as current + for (const prop of props) { // iterate over split props (passed as parameter) + value = value[prop]; // replace current with the next level or finished value + } + + if (typeof value == "undefined") { + return accumulatorValue; + } + + divider++; // keep track of how many entries there are + return parseFloat(accumulatorValue) + parseFloat(value); + + }, 0) / divider; // now that all values have been added together, devide by amount of them + + //console.log(prop + ": " + value + " divider: " + divider); + return value; + } + + + function getVertical() { + let up = 0, down = 0; + + for (let index = 0; index < cleanEntries.length; index++) { + const entry = cleanEntries[index]; + if (!entry.distance) { continue; } + + const vertical = parseFloat(entry.distance.vertical); + + if (vertical > 0) { + up += vertical; + } else if (vertical < 0) { + down += vertical; + } + } + + return [(up / 1000).toFixed(2), (down / 1000).toFixed(2)]; + } + + function getDistance() { + return cleanEntries.reduce((accumulatorValue: number, entry) => { + console.log(accumulatorValue); + if (!entry.distance) { return accumulatorValue } + return accumulatorValue + parseFloat(entry.distance.horizontal); + }, 0) / 1000; + } + + const ignoredEntries = entries.length - cleanEntries.length; + const uploadMean = getMean("time.uploadDuration").toFixed(3); + const speedGPSMean = (getMean("speed.gps") * 3.6).toFixed(1); + const speedCalcMean = (getMean("speed.horizontal") * 3.6).toFixed(1); + const verticalCalc = getVertical(); + const maxSpeed = getMaxSpeed(cleanEntries); + const distance = getDistance().toFixed(2); + + return { + ignoredEntries, + uploadMean, + speedGPSMean, + speedCalcMean, + maxSpeed, + verticalCalc, + distance + } +} + +function Status({ entries }: { entries: Models.IEntry[] }) { + if (!entries?.length) { + return No Data to be displayed + } + const statusData = getStatusData(entries); + //const lastEntry = entries.at(-1); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
data + {entries.length - statusData.ignoredEntries}({statusData.ignoredEntries}) +
Ø upload + {statusData.uploadMean}s +
Ø speed + GPS: {statusData.speedGPSMean}km/h Calc: {statusData.speedCalcMean == "NaN" ? " - " : statusData.speedCalcMean}km/h +
maxSpeed + {statusData.maxSpeed}km/h +
vertical + {statusData.verticalCalc[0]}km up, {statusData.verticalCalc[1]}km down +
Distance + {statusData.distance}km +
+ ) +} + +export default Status diff --git a/src/client/components/removeSvgAnimation.tsx b/src/client/components/removeSvgAnimation.tsx new file mode 100644 index 0000000..60ef9c4 --- /dev/null +++ b/src/client/components/removeSvgAnimation.tsx @@ -0,0 +1,28 @@ +document.addEventListener('DOMContentLoaded', () => { + const mq = window.matchMedia('(prefers-reduced-motion: reduce), (update: slow)'); + + // -- create small SVG to inject to see when SVG animations are rendered and started -- + const svgTemplate = ``; + + const container = document.createElement('div'); + container.innerHTML = svgTemplate; + + const animateElement = container.querySelector('animate'); + animateElement.addEventListener('beginEvent', () => { + if (mq.matches) { + const animations = document.querySelectorAll('animate, animateTransform'); + animations.forEach(animationElement => { + (animationElement as SVGAnimateElement).endElement(); + }); + } + }); + + + // Append the SVG directly to the document body + document.body.appendChild(container.firstElementChild as SVGElement); + +}); \ No newline at end of file diff --git a/src/client/css/login.css b/src/client/css/login.css new file mode 100644 index 0000000..624f753 --- /dev/null +++ b/src/client/css/login.css @@ -0,0 +1,143 @@ +@keyframes move-it { + to { + background-position: 200px 0px; + } +} + +.login { + --text: color-mix(in oklch, var(--neutral) 50%, black); + + [data-mui-color-scheme="dark"] & { + --text: var(--main); + } + + min-height: 100%; + display: flex; + justify-content: center; + align-content: center; + flex-wrap: wrap; + + color: var(--text); + + .fixed { + position: fixed; + inset: 1rem 1rem auto auto; + } + + .wrapper { + max-width: 50em; + padding: 2.5em; + margin: 2.5em; + position: relative; + filter: drop-shadow(10px 10px var(--semiBg)); + [data-mui-color-scheme="dark"] & { + filter: none; + &::after { box-shadow: var(--text) 0 0 1em;} + } + + &::after { + content: ""; + position: absolute; + inset: 0; + background: var(--semiBg); + + filter: url(#rough-edges); + z-index: -1; + } + + --cut: 3em; + .cut { /* reset for child elements */ + --cut: 1.1em + } + + + } + + .headline { + margin-inline: auto; + padding-block: 1em; + text-align: center; + font-size: 3.5rem; + + &.sub { + font-size: 2.1em; + } + } + + form { + display: flex; + flex-flow: nowrap column; + gap: 2em; + margin-bottom: 10vh; + + .MuiSvgIcon-root { + font-size: 2.7rem; + max-height: 100%; + } + + .MuiInputAdornment-root { + max-height: 100%; + height: 4.15em; + } + + p { + margin-top: 0.5em; + } + } + + input { + font-size: 2.2rem; + } + + label { + font-size: 1.8rem; + margin-bottom: 0.5em; + + &.Mui-focused { + color: var(--text); + } + } + + .subWrapper { + display: flex; + width: 100%; + align-items: center; + } + + .submit { + font-size: 1.5rem; + margin-left: auto; + min-width: 9em; + min-height: 3.5em; + border-radius: 0; + + [data-mui-color-scheme="light"] &:not([disabled]) { + color: var(--main); + background-color: color-mix(in oklch, var(--neutral) 90%, transparent); + } + + .MuiButton-icon { + font-size: 0.8em; + } + } + + .message { + font-size: 1.8em; + font-style: italics; + margin: 0; + + strong { + display: inline-block; + vertical-align: middle; + margin-right: 0.4em; + } + } + .message--error { + color: var(--alert); + } + .message--success { + color: var(--success); + } + + +} \ No newline at end of file diff --git a/src/client/css/map.css b/src/client/css/map.css new file mode 100644 index 0000000..b2646a7 --- /dev/null +++ b/src/client/css/map.css @@ -0,0 +1,69 @@ +.mapStyle { + display: contents; +} + +.mapContainer { + height: 100%; +} + +.leaflet-control-layers-base { + font-size: 1.4rem; + + label { + cursor: pointer; + margin-bottom: 0.3em; + } + + input { + top: 0; + } +} + +.leaflet-popup-content { + font-size: 1.2rem; + min-width: min-content; +} + +.leaflet-overlay-pane canvas { /* polyline */ + filter: drop-shadow(0px 0px 3px var(--neutral)); +} + +.marker-cluster-small[class] { /* overwrite default cluster style */ + background: none; + div { + background-color: var(--semiContrastBackground); + font-weight: bold; + box-shadow: inset 0 0 2px 2px var(--contrastBackground); + span { + color: var(--contrastText); + font-size: 1.5rem; + } + } +} + +.customMarkerIcon { + + &.start, &.end { + display: flex; + place-content: center; + border: 2px solid var(--contrastBackground); + outline: 3px solid var(--contrastBackground); + outline-offset: 3px; + border-radius: 50%; + background: var(--contrastBackground); + + svg { + height: 80%; + } + } + + &.start { + outline: none; + } + + &.none { + filter: drop-shadow(0 0 5px var(--contrastBackground)); + } + + +} \ No newline at end of file diff --git a/src/client/css/modeSwticher.module.css b/src/client/css/modeSwticher.module.css new file mode 100644 index 0000000..88f91fa --- /dev/null +++ b/src/client/css/modeSwticher.module.css @@ -0,0 +1,32 @@ +.modeSwitcher[class] { + color: var(--text); + border-color: currentColor; + + /* mobile show only icon */ + visibility: hidden; + font-size: 0; + + & > span { + visibility: visible; + margin: 0; + } + + &:hover { + background-color: color-mix(in oklch, var(--neutral) 20%, transparent); + border-color: currentColor; + } + + [data-mui-color-scheme="dark"] & { + color: var(--main); + + &:hover { + background-color: color-mix(in oklch, white 10%, transparent); + } + } + + @media (min-width: 30em) { + /* show text */ + font-size: 1rem; + visibility: visible; + } +} \ No newline at end of file diff --git a/src/client/css/start.css b/src/client/css/start.css new file mode 100644 index 0000000..b68fa16 --- /dev/null +++ b/src/client/css/start.css @@ -0,0 +1,241 @@ +@keyframes move-it { + to { + background-position: 200px 0px; + } +} + +.start { + /* theming */ + --text: color-mix(in oklch, var(--neutral) 50%, black); + + [data-mui-color-scheme="dark"] & { + --text: var(--main); + } + + color: var(--text); + background: var(--semiBg); + + + /* grid layout */ + height: 100%; + display: grid; + grid-template-columns: 1fr minmax(16rem, 40vmin); + grid-template-rows: minmax(3em, auto) 1fr 1fr 1fr minmax(3em, auto); + + .grid-item { + + &.info { + display: flex; + width: 100%; + justify-content: space-between; + padding: 0.5em 0.8em; + + @media (min-width: 30em) { + padding: 0.7em 2em; + } + } + + &.theme { + grid-row: 1; + grid-column: 2; + display: grid; + align-items: center; + justify-items: center; + } + + &.map { + grid-column: 1; + grid-row: 2 / span 3; + margin-right: 1em; + + background-color: color-mix(in oklab, transparent 50%, var(--main)); + + @media (max-width: 35em) { + grid-column: 1 / -1; + margin-right: 0; + } + } + + &.status { + grid-column: 2; + grid-row: 2; + margin: 1em 1em 1em 0; + position: relative; + z-index: 0; + + &.emptyData::after { + content: none; + } + + &::after { + content: ""; + position: absolute; + inset: 0; + z-index: -1; + + background-color: var(--semiBg); + + --shadowColor: var(--text); + filter: url(#rough-light); + box-shadow: 0 0 0.2em var(--shadowColor); + } + + [data-mui-color-scheme="dark"] &::after { + --shadowColor: var(--main); + filter: url(#rough-light) drop-shadow(0 3px 5px var(--shadowColor)); + } + + } + + &.images { + grid-column: 2; + grid-row: 3 / span 2; + + display: grid; + overflow: auto; + + @media (max-width: 35em) { + display: none; + } + } + + .image { + display: inline-block; + aspect-ratio: 16/9; + margin-bottom: 0.5rem; + cursor: pointer; + + > * { + width: 100%; + height: 100%; + } + } + + + &.subinfo { + grid-column: 1 / -1; + padding: 0.5em 0.8em; + + @media (min-width: 35em) { + padding: 0.7em 2em; + grid-column: 1; + } + + .MuiLinearProgress-root { + margin: -0.5em 0 1em -0.8em; + + @media (min-width: 30em) { + margin: -0.7em -1em 1em -2em; + } + } + + .info { + display: inline-block; + padding-inline: 1em; + border-right: 0.1rem solid; + + &:last-child, + &.noDivider { + border: none; + padding-right: 0; + } + } + } + } + + .message { + display: inline-flex; + flex-wrap: wrap; + align-content: center; + justify-content: center; + font-size: 0.9em; + + @media (min-width: 30em) { + font-size: 1.3em; + } + + &.center { + margin-left: auto; + } + + &.error { + color: var(--alert); + } + + .title { + font-size: 1.1em; + + @media (min-width: 30em) { + font-size: inherit; + } + + width: 100%; + text-align: center; + } + } + + .loginButton { + color: white; + + [data-mui-color-scheme="dark"] & { + color: black; + } + + margin-left: auto; + cursor: pointer; + white-space: nowrap; + + font-size: 0; + padding: 0; + + @media (min-width: 30em) { + /* reset to MUI default */ + font-size: 1.3rem; + padding: 8px 22px; + } + + .MuiButton-icon { + font-size: 1.3rem; + + @media (min-width: 30em) { + font-size: inherit; + } + } + + .MuiButton-startIcon { + margin-left: 6px; + + @media (min-width: 30em) { + margin-left: 0px; + } + } + + .MuiButton-endIcon { + margin-left: 0; + + @media (min-width: 30em) { + margin-left: 4px; + } + } + + + &.loginButton--loggedIn { + svg { + position: relative; + top: -0.1em; + right: 0.1em; + } + } + } +} + +.noData { + display: block; + font-size: 1.4em; + text-align: center; + width: min-content; + margin: 2.5em auto; + padding: 2.5em; + color: var(--alert); + background-color: var(--semiBg); +} \ No newline at end of file diff --git a/src/client/css/status.css b/src/client/css/status.css new file mode 100644 index 0000000..07747e0 --- /dev/null +++ b/src/client/css/status.css @@ -0,0 +1,70 @@ +.status { + container-type: inline-size; +} + + +.statusTable { + font-size: 1.4rem; + padding: 0.7rem 0.2em 0.2em 1em; + height: 100%; + + th { + text-align: left; + padding: 0 1rem; + } + + td { + font-stretch: 120%; + font-weight: 350; + font-style: oblique 10deg; + letter-spacing: 0.0125em; + } + + .strike { + font-style: normal; + position: relative; + + &::after { + content: ""; + position: absolute; + top: 40%; + left: 60%; + transform: translate(-50%, -50%); + border-top: 1px solid; + width: 100%; + } + } + + span { + white-space: nowrap; + } +} + +@container (max-width: 30rem) { + .statusTable { + padding: 0.5rem 0.2rem; + font-size: 1.3rem; + } + + th { + display: none; + } + + td { + padding-inline: 0.2rem; + } +} + +@container (max-width: 20rem) { + .statusTable { + padding: 0.3rem 0.1rem; + font-size: 1.15rem; + } + + td { + padding: 0 0 0 0.1rem; + font-stretch: 100%; + font-weight: 400; + letter-spacing: normal; + } +} \ No newline at end of file diff --git a/src/client/index.tsx b/src/client/index.tsx new file mode 100644 index 0000000..9030437 --- /dev/null +++ b/src/client/index.tsx @@ -0,0 +1,27 @@ +import "./components/removeSvgAnimation"; +import * as React from 'react'; +import { Root, createRoot } from 'react-dom/client'; +import { Experimental_CssVarsProvider as CssVarsProvider, experimental_extendTheme as extendTheme } from '@mui/material/styles'; +import App from "./components/App"; + +const theme = extendTheme({ // color pallette overwritten in css + typography: { + fontFamily: "Science-Gothic, sans-serif", + fontSize: 20, + } +}); + +const container = document.getElementById('react-root'); +let root: Root; +if (container) { + root = createRoot(container); + root.render( + + + + ); +} else { + console.error("root not found"); +} + + diff --git a/src/client/pages/Login.tsx b/src/client/pages/Login.tsx new file mode 100644 index 0000000..2b2d9a7 --- /dev/null +++ b/src/client/pages/Login.tsx @@ -0,0 +1,213 @@ +import React, { useContext, useState } from 'react'; +import { TextField, Button, InputAdornment, CircularProgress } from '@mui/material'; +import { AccountCircle, Lock, HighlightOff, Login as LoginIcon, Check } from '@mui/icons-material'; +import "../css/login.css"; +import ModeSwitcher from '../components/ModeSwitcher'; +import axios from 'axios'; +import qs from 'qs'; +import { Context, convertJwt } from '../components/App'; +import { useNavigate } from 'react-router-dom'; +import LinearBuffer from '../components/LinearBuffer'; + +function Login() { + const [finish, setFinish] = useState(1); + const [start, setStart] = useState(1); + const navigate = useNavigate(); + const [isLoggedIn, setLogin, userInfo, setUserInfo] = useContext(Context); + const [formInfo, updateFormInfo] = useState({ + user: { + isError: false, + message: "Minimum 2", + value: userInfo?.user || "" + }, + password: { + isError: false, + message: "Enter Password", + value: "" + }, + token: "" + }); + const [isLoading, setLoading] = React.useState(false); + const [errorObj, setMessageObj] = React.useState({ isError: null, status: null, message: null }); + + const isFormValid = formInfo.user.value && !formInfo.user.isError && formInfo.password.value && !formInfo.password.isError; + + function updateField(name: string, value: string) { + const hasError = validateField(name, value, false); + const newObj = { ...formInfo, [name]: { ...formInfo[name], value: value } } + if (!hasError) { newObj[name].isError = false } // remove error state while typing but don't add before blur event + updateFormInfo(newObj) + } + + function validateField(name: string, value: string, update = true) { + const isError = value.length <= 1; + if (update) { + updateFormInfo({ ...formInfo, [name]: { ...formInfo[name], isError: isError } }) + } else { + return isError; + } + } + + async function submit(e) { + e.preventDefault(); + const date = new Date(); + setStart(date.getTime()); + const milliseconds = 9 * 1000; // Estimated bcrypt Time + setFinish(new Date(date.getTime() + milliseconds).getTime()); + + setLoading(true); + setMessageObj({ isError: null, status: null, message: null }); + + + let token = null; // get csrf token + try { + token = await axios({ + method: "post", + url: "/login/csrf", + headers: { + "content-type": "application/x-www-form-urlencoded", + "x-requested-with": "XMLHttpRequest" + } + }) + updateFormInfo({ ...formInfo, token: token.data }); + } catch (error) { + console.log(error); + setMessageObj({ isError: true, status: error.response.data.status || error.response.status, message: error.response.data.message || error.message }) + } + + if (!token) { setLoading(false); return; } // skip when the first request has an error + + // collect data and convert to urlencoded string then send + const bodyFormData = { "user": formInfo.user.value, "password": formInfo.password.value, csrfToken: token.data }; + try { + const response = await axios({ + method: "post", + url: "/login", + data: qs.stringify(bodyFormData), + headers: { "content-type": "application/x-www-form-urlencoded" } + }) + const token = response.data.token; + localStorage.setItem("jwt", token); + setLogin(true); + setMessageObj({ isError: false, status: , message: "Success!" }) + + // update linearBar for delay until redirect + const date = new Date(); + setStart(date.getTime()); + setFinish(new Date(date.getTime() + 1000).getTime()); + setUserInfo(convertJwt()); + + // redirect back to main page + setTimeout(() => { setLoading(false); navigate("/") }, 1000); + + } catch (error) { + console.log(error); + setMessageObj({ isError: true, status: error.response.data.status || error.response.status, message: error.response.data.message || error.message }) + setLoading(false); // Reset loading after request is complete + } + } + + return ( +
+
+ +
+
+

+ Login Page +

+ {isLoggedIn && +

You are logged in

+ } +
+ updateField(e.target.name, e.target.value)} + onBlur={(e) => validateField(e.target.name, e.target.value)} + error={formInfo.user.isError} + helperText={formInfo.user.isError ? formInfo.user.message : false} + required + autoFocus={!userInfo?.user} + InputProps={{ + classes: { + root: "cut", + }, + name: "user", + startAdornment: ( + + + + ), + endAdornment: formInfo.user.isError ? ( + + + + ) : null + }} + /> + + updateField(e.target.name, e.target.value)} + onBlur={(e) => validateField(e.target.name, e.target.value)} + required + error={formInfo.password.isError} + helperText={formInfo.password.isError ? formInfo.password.message : false} + autoFocus={!!userInfo?.user} + InputProps={{ + classes: { + root: "cut", + }, + name: "password", + startAdornment: ( + + + + ), + endAdornment: formInfo.password.isError ? ( + + + + ) : null + }} + /> + +
+ {errorObj.status ? ( +

+ {errorObj.status} + {errorObj.message.split('\n').map((line: string, index: string) => ( + + {line} +
+
+ ))} +

+ ) : null} + +
+ {isLoading && } + +
+ + + +
+ ) +} + +export default Login; diff --git a/src/client/pages/Start.tsx b/src/client/pages/Start.tsx new file mode 100644 index 0000000..fcef444 --- /dev/null +++ b/src/client/pages/Start.tsx @@ -0,0 +1,183 @@ +import React, { useEffect, useState, useContext, useRef } from 'react' +import "../css/start.css"; +import axios from 'axios'; +import { Context } from "../components/App"; +import { HighlightOff, Check } from '@mui/icons-material'; +import { Button } from '@mui/material'; +import ModeSwitcher from '../components/ModeSwitcher'; +import Map from '../components/Map'; +import Status from '../components/Status'; +import LinearBuffer from "../components/LinearBuffer"; +import MiniMap from "../components/MiniMap"; +import { layers } from "../scripts/layers"; + + +function timeAgo(timestamp: number): string { + if (!Number.isInteger(timestamp)) { + return ""; + } + const now = Date.now(); + const diffInSeconds = Math.floor((now - timestamp) / 1000); + + const seconds = diffInSeconds; + const minutes = Math.round(diffInSeconds / 60); + const hours = Math.round(diffInSeconds / 3600); + const days = Math.round(diffInSeconds / 86400); + const months = Math.round(diffInSeconds / 2592000); + const years = Math.round(diffInSeconds / 31536000); + + if (seconds < 8) return "Instant"; + else if (seconds < 25) return "Just now"; + else if (seconds < 50) return "a moment ago"; + else if (minutes < 60) return `${minutes} ${minutes === 1 ? "minute" : "minutes"} ago`; + else if (hours < 24) return `${hours} ${hours === 1 ? "hour" : "hours"} ago`; + else if (days < 30) return `${days} ${days === 1 ? "day" : "days"} ago`; + else if (months < 12) return `${months} ${months === 1 ? "month" : "months"} ago`; + else return `${years} ${years === 1 ? "year" : "years"} ago`; + +} + +function Start() { + const [isLoggedIn, setLogin, userInfo] = useContext(Context); + const [entries, setEntries] = useState([]); + const [messageObj, setMessageObj] = useState({ isError: null, status: null, message: null }); + const [lastFetch, setLastFetch] = useState(); + const [nextFetch, setNextFetch] = useState(); + + const index = useRef(0); + const intervalID = useRef(); + + const fetchIntervalMs = 1000 * 55; + + const getData = async () => { + const token = localStorage.getItem("jwt"); + let response; + + if (!token) { + setLogin(false); + setMessageObj({ isError: true, status: "403", message: "No valid login" }) + return false; + } + + try { + const now = new Date().getTime(); + setLastFetch(now); + response = await axios({ + method: 'get', + url: "/read?index=" + (Math.max(index.current - 1, 0)) + "&noCache=" + now, + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + const newEntries = response.data.entries; + + if (newEntries.length) { + setEntries((prevEntries) => { + let allButLastPrevEntries, mergedEntries = []; + + if (prevEntries.length) { + allButLastPrevEntries = prevEntries.slice(0, prevEntries.length - 1); + mergedEntries = [...allButLastPrevEntries, ...newEntries]; + } else { + mergedEntries = newEntries; + } + + index.current = mergedEntries.length; + + return mergedEntries; + }); + + } + + setMessageObj({ isError: null, status: null, message: null }); + setNextFetch(new Date().getTime() + fetchIntervalMs); + } catch (error) { + console.log("error fetching data %o", error); + + if (!error.response) { + setMessageObj({ isError: true, status: 499, message: error.message || "offline" }); + setNextFetch(new Date().getTime() + fetchIntervalMs); + return; + } + + if (error.response.status == 403) { setLogin(false) } + + setMessageObj({ isError: true, status: error.response.data.status || error.response.status, message: error.response.data.message || error.message }); + + clearInterval(intervalID.current); intervalID.current = null; + console.info("cleared Interval"); + setNextFetch(null); + } + }; + + useEffect(() => { + if (isLoggedIn) { + getData(); + intervalID.current = setInterval(getData, fetchIntervalMs); // capture interval ID as return from setInterval and pass to state + return () => { console.log("cleanup"); clearInterval(intervalID.current); intervalID.current = null; }; + } else if (userInfo) { // no valid login but userInfo + setMessageObj({ isError: true, status: "403", message: "Login expired" }) + } + }, []); + + return ( + <> +
+
+ {messageObj.isError && +
+ {messageObj.status} {messageObj.message} +
+ } + {!messageObj.isError && userInfo && +
+ {userInfo.user} Welcome back +
+ } + +
+ +
+
+
+
+ {entries.at(-1) && layers.map((layer, index) => { + return ( + + ) + })} +
+ +
+ {isLoggedIn && intervalID && + + } + {isLoggedIn && intervalID && entries?.length > 0 && + <> + GPS: + {entries.at(-1).lat} / {entries.at(-1).lon} + {timeAgo(entries.at(-1).time.created)} + + } +
+
+ + + + + ) +} + +export default Start \ No newline at end of file diff --git a/src/client/scripts/layers.ts b/src/client/scripts/layers.ts new file mode 100644 index 0000000..0ede698 --- /dev/null +++ b/src/client/scripts/layers.ts @@ -0,0 +1,48 @@ +export const layers:client.Layer[] = [ + { + name: "OSM DE", + attribution: '© OpenStreetMap contributors', + url: 'https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png', + markerStyle: "" + }, + { + name: "Carto Voyager Light", + attribution: '© OpenStreetMap contributors © CARTO', + url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', + markerStyle: "light", + default: "light" + }, + { + name: "Stadia AlidadeSmoothDark", + attribution: '© Stadia Maps © OpenMapTiles © OpenStreetMap contributors', + url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png', + markerStyle: "dark", + default: "dark" + }, + { + name: "ArcGis WorldImagery", + attribution: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', + url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', + markerStyle: "dark" + }, + // { + // name: "OpenRailway", + // attribution: 'Map data: © OpenStreetMap contributors | Map style: © Stadia Maps © OpenMapTiles © OpenStreetMap contributors', + url: 'https://tiles.stadiamaps.com/tiles/alidade_satellite/{z}/{x}/{y}{r}.jpg', + markerStyle: "dark" + }, + { + name: "Mapbox Satelite Streets", + attribution: '© Mapbox', + url: 'https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoidHlwZS1zdHlsZSIsImEiOiJjbGJ4aG14enEwZ2toM3BvNW5uanhuOGRvIn0.7TUEM9vA-EYSt3WW_bcsAA', + markerStyle: "dark", + size: 512, + zoomOffset: -1 + } +] \ No newline at end of file diff --git a/src/client/scripts/maxSpeed.ts b/src/client/scripts/maxSpeed.ts new file mode 100644 index 0000000..7477af6 --- /dev/null +++ b/src/client/scripts/maxSpeed.ts @@ -0,0 +1,7 @@ +export const getMaxSpeed = function (cleanEntries:Models.IEntry[]) { + let maxSpeed = cleanEntries.reduce((maxSpeed, entry:Models.IEntry) => { + // compare the current entry's GPS speed with the maxSpeed found so far + return Math.max(maxSpeed, entry.speed.gps); + }, cleanEntries[0].speed.gps); + return maxSpeed *= 3.6; // convert M/S to KM/h +}; \ No newline at end of file diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json new file mode 100644 index 0000000..7777c58 --- /dev/null +++ b/src/client/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "lib": ["dom","ES6"], + "outDir": "../../dist/httpdocs", + "rootDir": "../../", + "jsx": "react", + "esModuleInterop": true + }, + "include": ["**/*.tsx", "**/*.ts", "types.d.ts", "../../types.d.ts"] +} \ No newline at end of file diff --git a/src/client/types.d.ts b/src/client/types.d.ts new file mode 100644 index 0000000..6542881 --- /dev/null +++ b/src/client/types.d.ts @@ -0,0 +1,23 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +declare module "*.module.css"; +declare namespace client { + type MarkerStyle = "" | "light" | "dark"; + + interface Layer { + name: string; + attribution: string; + url: string; + markerStyle: MarkerStyle; + default?: MarkerStyle; // Optional property since not all layers have a default style + size?: number; + zoomOffset?: number; + } + + interface MiniMapProps { + layer: client.Layer; + lastEntry: Models.IEntry + index?: number + } +} + + diff --git a/src/controller/login.ts b/src/controller/login.ts index 6a47f4c..6eaa313 100644 --- a/src/controller/login.ts +++ b/src/controller/login.ts @@ -7,11 +7,15 @@ import { createJWT, createCSRF, validateCSRF } from '@src/scripts/token'; const router = express.Router(); -router.get("/", baseSlowDown, baseRateLimiter, async function login(req: Request, res: Response, next: NextFunction) { +router.post("/csrf", baseSlowDown, baseRateLimiter, async function csrf(req: Request, res: Response, next: NextFunction) { loginLimiter(req, res, () => { + if (req.headers['x-requested-with'] !== 'XMLHttpRequest') { + return createError(res, 403, "Unable to provide token", next); + } const csrfToken = createCSRF(res, next); - res.locals = {...res.locals, text: 'start', csrfToken: csrfToken}; - res.render("login-form"); + if (csrfToken) { + res.json(csrfToken); + } }); }); @@ -23,7 +27,7 @@ router.post("/", loginSlowDown, async function postLogin(req: Request, res: Resp const password = req.body.password; let userFound = false; if (!user || !password) { return createError(res, 422, "Body does not contain all expected information", next); } - if (!token || !validateCSRF(req.body.csrfToken)) { return createError(res, 403, "Invalid CSRF Token", next); } + if (!token || !validateCSRF(req.body.csrfToken)) { return createError(res, 403, "Invalid CSRF Token \n retry in 5 Minuits", next); } // Loop through all environment variables for (const key in process.env) { diff --git a/src/error.ts b/src/error.ts deleted file mode 100644 index 0b0bc04..0000000 --- a/src/error.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Request, Response, NextFunction } from "express"; - -export function notFound(req: Request, res: Response, next: NextFunction) { - res.status(404); - const error = new Error(`🔍 - Not Found - ${req.originalUrl}`); - next(error); -} - -export function handler(err: Error, req: Request, res: Response, next: NextFunction) { - const statusCode = res.statusCode !== 200 ? res.statusCode : 500; - res.status(statusCode); - - let message; - try { - const jsonMessage = JSON.parse(err.message); - message = jsonMessage; - } catch (e) { - message = err.message; - } - - const responseBody = { - status: statusCode, - name: err.name, - message: message, - stack: process.env.NODE_ENV === "development" ? err.stack : "---" - }; - - //logger.error(responseBody); - res.json(responseBody); - - next(); -} diff --git a/src/models/entry.ts b/src/models/entry.ts index e7fc107..34dbb75 100644 --- a/src/models/entry.ts +++ b/src/models/entry.ts @@ -21,6 +21,7 @@ export const entry = { } const entries = fileObj.content.entries; const lastEntry = fileObj.content.entries.at(-1); + let previousEntry = fileObj.content.entries.at(-1); // potentially overwritten if entry is set to ignore const entry = {} as Models.IEntry; entry.altitude = Number(req.query.altitude); @@ -32,11 +33,32 @@ export const entry = { entry.user = req.query.user as string; entry.ignore = false; - if (lastEntry) { // so there is a previous entry - entry.time = getTime(Number(req.query.timestamp), lastEntry); - lastEntry.ignore = getIgnore(lastEntry, entry); - entry.angle = getAngle(lastEntry, entry); - entry.distance = getDistance(entry, lastEntry) + if (lastEntry && previousEntry) { + entry.time = getTime(Number(req.query.timestamp), lastEntry); // time data is needed for ignore calculation + + if (entries.length > 1) { // the very first entry one shall never be ignored + lastEntry.ignore = getIgnore(lastEntry, entry); + } else { + lastEntry.ignore = false; + } + + if (lastEntry.ignore) { // rectify or replace previousEntry with last non ignored element + for (let i = entries.length - 1; i >= 0; i--) { + if (!entries[i].ignore) { + previousEntry = entries[i]; + break; + } + } + + if (previousEntry === fileObj.content.entries.at(-1)) { + logger.error("previousEntry was not replaced"); + } + + } + + entry.time = getTime(Number(req.query.timestamp), previousEntry); // overwrite time in case previousEnty was changed + entry.angle = getAngle(previousEntry, entry); + entry.distance = getDistance(entry, previousEntry) entry.speed = getSpeed(Number(req.query.speed), entry); } else { entry.angle = undefined; @@ -46,7 +68,7 @@ export const entry = { if (entries.length >= 1000) { logger.log(`File over 1000 lines: ${fileObj.path}`); - if (entry.hdop < 12 || (lastEntry && entry.hdop < lastEntry.hdop)) { + if (entry.hdop < 12 || (previousEntry && entry.hdop < previousEntry.hdop)) { entries[entries.length - 1] = entry; // replace last entry } } else { diff --git a/src/scripts/ignore.ts b/src/scripts/ignore.ts index 3e92857..d16bb1c 100644 --- a/src/scripts/ignore.ts +++ b/src/scripts/ignore.ts @@ -4,10 +4,10 @@ export function getIgnore(lastEntry: Models.IEntry, entry: Models.IEntry): boole const timing = Math.max(lastEntry.time.diff, entry.time.diff) - // Threshold increases with older previous entries or farther future entries. + // Threshold increases with older previous entries if (timing > 32) { threshold += Math.min(lastEntry.time.diff / 60, maxThreshold); } - + return lastEntry.hdop > threshold; } \ No newline at end of file diff --git a/src/scripts/token.ts b/src/scripts/token.ts index f9f4d7a..9a012f2 100644 --- a/src/scripts/token.ts +++ b/src/scripts/token.ts @@ -6,10 +6,11 @@ import { create as createError } from '@src/middleware/error'; const csrfTokens: Set = new Set(); -export function createCSRF(res: Response, next: NextFunction): string { +export function createCSRF(res: Response, next: NextFunction): string | false { if (csrfTokens.size > 100) { // Max Number of Tokens in memory res.set('Retry-After', '300'); // 5 minutes - createError(res, 503, "Too many tokens", next); + createError(res, 503, "Too many tokens \n retry after 5 Minuits", next); + return false; } const token = crypto.randomBytes(16).toString('hex'); @@ -58,7 +59,11 @@ export function validateJWT(req: Request) { } catch (err) { let message = "could not verify"; if (err instanceof Error) { - message = `${err.name} - ${err.message}`; + if (err.name == "TokenExpiredError") { + message = "Login expired"; + } else { + message = `${err.name} - ${err.message}`; + } } return { success: false, status: 403, message: message }; @@ -81,7 +86,7 @@ export function createJWT(req: Request, res: Response) { date: dateString, user: req.body.user }; - const token = jwt.sign(payload, key, { expiresIn: 60 * 2 }); + const token = jwt.sign(payload, key, { expiresIn: 60 * 30 }); res.locals.token = token; return token; } diff --git a/src/testData/createTestData.test.ts b/src/testData/createTestData.test.ts new file mode 100644 index 0000000..8838124 --- /dev/null +++ b/src/testData/createTestData.test.ts @@ -0,0 +1,70 @@ +import axios, { AxiosError } from 'axios'; + + +async function callServer(timestamp = new Date().getTime(), query: string, expectStatus: number = 200, method: string = "HEAD") { + const url = new URL("http://localhost:80/write?"); + url.search = "?" + query; + const params = new URLSearchParams(url.search); + params.set("timestamp", timestamp.toString()); + url.search = params.toString(); + + + let response; + if (expectStatus == 200) { + if (method == "GET") { + response = await axios.get(url.toString()); + } else { + response = await axios.head(url.toString()); + } + expect(response.status).toBe(expectStatus); + } else { + try { + await axios.head(url.toString()); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + expect(axiosError.response.status).toBe(expectStatus); + } else { + console.error(axiosError); + } + } + } +} + + + + +describe('test Data', () => { + const entries = 6; + const start = { lat: 52.51625, lon: 13.37661 }; + const end = { lat: 52.50960, lon: 13.27457 }; + const diff = {lat: end.lat - start.lat, lon: end.lon - start.lon}; + + // eslint-disable-next-line jest/expect-expect + it('create ' + entries + ' entries', () => { + return new Promise(done => { + + for (let i = 0; i < entries; i++) { + const lat = (start.lat + (diff.lat / (entries - 1) * i)).toFixed(8); + const lon = (start.lon + (diff.lon / (entries - 1) * i)).toFixed(8); + setTimeout(async () => { + await callServer(undefined, `user=xx&lat=${lat}&lon=${lon}×tamp=R3Pl4C3&hdop=${Math.floor(Math.random() * 15) + 1}&altitude=${i+1}&speed=${39 + i*2.5}&heading=${262 + Math.floor(Math.random() * 20) - 10}&key=test`, 200, "GET"); + console.log("called server " + (i + 1) + "/" + entries); + + }, 1000 * 30 * i); + } + + setTimeout(async () => { + done(); + }, 1000 * 30 * entries); + }) + }, 1000 * 30 * (entries + 1)); + +}); + + + + + + + diff --git a/src/tests/app.test.ts b/src/tests/app.test.ts index 44ba08d..ee74eb6 100644 --- a/src/tests/app.test.ts +++ b/src/tests/app.test.ts @@ -9,8 +9,24 @@ const randomData = qs.stringify({ describe('Server Status', () => { it('The server is running', async () => { let serverStatus; + let response; try { - const response = await axios.get('http://localhost:80/'); + response = await axios.get('http://localhost:80/'); + serverStatus = response.status; + } catch (error) { + console.error(error); + return; + } + + expect(serverStatus).toBe(200); + expect(response.data).toContain("js/bundle.js"); + }) + + it('bundle.js exists', async () => { + let serverStatus; + let response; + try { + response = await axios.get('http://localhost:80/js/bundle.js'); serverStatus = response.status; } catch (error) { console.error(error); diff --git a/src/tests/integration.test.ts b/src/tests/integration.test.ts index 067d3ea..e79be6f 100644 --- a/src/tests/integration.test.ts +++ b/src/tests/integration.test.ts @@ -195,16 +195,23 @@ describe("GET /write", () => { it('check ignore', async () => { let jsonData = getData(filePath); - let entry = jsonData.entries[1]; - const lastEntry = jsonData.entries[0]; + let entry = jsonData.entries.at(-1); + let firstEntry = jsonData.entries[0]; + let previousEntry = null; - expect(entry.ignore).toBe(false); // current one to be false allways - expect(lastEntry.ignore).toBe(true); // last one to high hdop to be true + expect(entry.ignore).toBe(false); // current one to be false always + expect(firstEntry.ignore).toBe(false); // start entry to be false always await callServer(undefined, "user=xx&lat=52.51627&lon=13.37770×tamp=R3Pl4C3&hdop=50&altitude=4000.000&speed=150.000&heading=180.0&key=test", 200, "GET"); + jsonData = getData(filePath); - entry = jsonData.entries[1]; // same data point, but not last now therefore ignore true - expect(entry.ignore).toBe(true); + entry = jsonData.entries.at(-1); + previousEntry = jsonData.entries.at(-2); + firstEntry = jsonData.entries[0]; + + expect(entry.ignore).toBe(false); // current one to be false always + expect(firstEntry.ignore).toBe(false); // start entry to be false always + expect(previousEntry.ignore).toBe(true); // now since there is 3 entries the previous can be ignored }); }); @@ -237,17 +244,23 @@ describe('read and login', () => { csrfToken: "" } - it('form available / get Token', async () => { + it('get csrfToken', async () => { let response = {data:""}; try { - response = await axios.get('http://localhost:80/login'); + response = await axios({ + method: "post", + url: "http://localhost/login/csrf", + headers: { + "content-type": "application/x-www-form-urlencoded", + "x-requested-with": "XMLHttpRequest" + } + }) } catch (error) { console.error(error); } - - const regex = /name="csrfToken" value="([^"]*)"/; - const match = response.data.match(regex); - testData.csrfToken = match ? match[1] : '-'; + + testData.csrfToken = response.data; + expect(testData.csrfToken).toBeTruthy(); }) test(`redirect without logged in`, async () => { diff --git a/src/tests/login.test.ts b/src/tests/login.test.ts index e177826..e7a593e 100644 --- a/src/tests/login.test.ts +++ b/src/tests/login.test.ts @@ -19,22 +19,31 @@ const userDataWithToken = { }; describe('Login', () => { - it('form available', async () => { + it('csrf available', async () => { let serverStatus = {}; let response = { data: "", status: "" }; try { - response = await axios.get('http://localhost:80/login'); + response = await axios({ + method: "post", + url: "http://localhost:80/login/csrf", + headers: { + "content-type": "application/x-www-form-urlencoded", + "x-requested-with": "XMLHttpRequest" + } + }) serverStatus = response.status; } catch (error) { console.error(error); + throw Error("fail"); } + expect(serverStatus).toBe(200); - expect(response.data).toContain(' { @@ -71,7 +80,8 @@ describe('Login', () => { it('test invalid credentials to return error', async () => { try { - userDataWithToken.csrfToken = csrfToken + userDataWithToken.csrfToken = csrfToken; + console.log("csrfToken %o", userDataWithToken.csrfToken); await axios.post('http://localhost:80/login', qs.stringify(userDataWithToken)); } catch (error) { const axiosError = error as AxiosError; diff --git a/tsconfig.json b/tsconfig.json index 5f168cd..64098b6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "@tsconfig/node20/tsconfig.json", "include": ["src/**/*"], - "exclude": ["node_modules"], + "exclude": ["node_modules", "src/client/"], "compilerOptions": { "rootDir": "src", "outDir": "dist", diff --git a/types.d.ts b/types.d.ts index 3cde1ce..0bab5de 100644 --- a/types.d.ts +++ b/types.d.ts @@ -30,7 +30,7 @@ namespace File { namespace Models { interface IEntries { - entries: Models.IEntry[] + entries: IEntry[] } interface IEntry { diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..ff3d550 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,73 @@ + + + + + + + + LOREX - Osmand Webtracking Frontend + + + + + + + + + + + + + + + + + + + + + + + + +
+

Lorex

+
+ + + + + \ No newline at end of file diff --git a/views/login-form.ejs b/views/login-form.ejs index 34bf551..b0eef5e 100644 --- a/views/login-form.ejs +++ b/views/login-form.ejs @@ -5,7 +5,7 @@ Login Form - Lorex - + @@ -21,7 +21,7 @@ diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..4e5df71 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,49 @@ +const path = require('path'); + +module.exports = (args) => { + const mode = args.mode || 'development'; + return { + mode: mode, + entry: './src/client/index.tsx', + module: { + rules: [ + { + test: /\.tsx?$/, + use: { + loader: 'ts-loader', + options: { + configFile: 'src/client/tsconfig.json' + } + }, + exclude: /node_modules/, + }, + { + test: /\.css$/, + use: [ + "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 1, + modules: true, + }, + }, + ], + include: /\.module\.css$/, + }, + { + test: /\.css$/, + use: ["style-loader", "css-loader"], + exclude: /\.module\.css$/, + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'], + }, + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist/httpdocs/js'), + } + } +};