diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..22254b08 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c86e1cef --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/flask-server/venv \ No newline at end of file diff --git a/client/my-app/.gitignore b/client/my-app/.gitignore new file mode 100644 index 00000000..4d29575d --- /dev/null +++ b/client/my-app/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/client/my-app/.prettierrc b/client/my-app/.prettierrc new file mode 100644 index 00000000..b1f6bfff --- /dev/null +++ b/client/my-app/.prettierrc @@ -0,0 +1,6 @@ +{ + "arrowParens": "avoid", + "trailingComma": "es5", + "singleQuote": true, + "semi": true +} diff --git a/client/my-app/README.md b/client/my-app/README.md new file mode 100644 index 00000000..54ef0943 --- /dev/null +++ b/client/my-app/README.md @@ -0,0 +1,68 @@ +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `npm start` + +Runs the app in the development mode.
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser. + +The page will reload if you make edits.
+You will also see any lint errors in the console. + +### `npm test` + +Launches the test runner in the interactive watch mode.
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `npm run build` + +Builds the app for production to the `build` folder.
+It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.
+Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `npm run eject` + +**Note: this is a one-way operation. Once you `eject`, you can’t go back!** + +If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. + +You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). + +### Code Splitting + +This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting + +### Analyzing the Bundle Size + +This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size + +### Making a Progressive Web App + +This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app + +### Advanced Configuration + +This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration + +### Deployment + +This section has moved here: https://facebook.github.io/create-react-app/docs/deployment + +### `npm run build` fails to minify + +This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify diff --git a/client/my-app/gitPractice b/client/my-app/gitPractice new file mode 100644 index 00000000..59342050 --- /dev/null +++ b/client/my-app/gitPractice @@ -0,0 +1 @@ +practice diff --git a/client/my-app/package-lock.json b/client/my-app/package-lock.json new file mode 100644 index 00000000..47d3e33a --- /dev/null +++ b/client/my-app/package-lock.json @@ -0,0 +1,19037 @@ +{ + "name": "my-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "my-app", + "version": "0.1.0", + "dependencies": { + "@chakra-ui/react": "^2.5.1", + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "axios": "^1.3.5", + "cors": "^2.8.5", + "framer-motion": "^6.5.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^3.11.0", + "react-router-hash-link": "^2.4.3", + "react-scripts": "5.0.1", + "web-vitals": "^2.1.4" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz", + "integrity": "sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.0", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.0", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.0", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/eslint-parser/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "dependencies": { + "@babel/types": "^7.21.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", + "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", + "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", + "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", + "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "dependencies": { + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", + "dependencies": { + "@babel/types": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", + "dependencies": { + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.21.0.tgz", + "integrity": "sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.21.0.tgz", + "integrity": "sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", + "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", + "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", + "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.19.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", + "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz", + "integrity": "sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-flow": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", + "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", + "dependencies": { + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-identifier": "^7.19.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz", + "integrity": "sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz", + "integrity": "sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz", + "integrity": "sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz", + "integrity": "sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-typescript": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "dependencies": { + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.0.tgz", + "integrity": "sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-transform-typescript": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.1", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "node_modules/@chakra-ui/accordion": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/accordion/-/accordion-2.1.9.tgz", + "integrity": "sha512-a9CKIAUHezc0f5FR/SQ4GVxnWuIb2HbDTxTEKTp58w/J9pecIbJaNrJ5TUZ0MVbDU9jkgO9RsZ29jkja8PomAw==", + "dependencies": { + "@chakra-ui/descendant": "3.0.13", + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/transition": "2.0.15" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/alert": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/alert/-/alert-2.0.17.tgz", + "integrity": "sha512-0Y5vw+HkeXpwbL1roVpSSNM6luMRmUbwduUSHEA4OnX1ismvsDb1ZBfpi4Vxp6w8euJ2Uj6df3krbd5tbCP6tg==", + "dependencies": { + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/spinner": "2.0.13" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/anatomy": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/anatomy/-/anatomy-2.1.2.tgz", + "integrity": "sha512-pKfOS/mztc4sUXHNc8ypJ1gPWSolWT770jrgVRfolVbYlki8y5Y+As996zMF6k5lewTu6j9DQequ7Cc9a69IVQ==" + }, + "node_modules/@chakra-ui/avatar": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/avatar/-/avatar-2.2.5.tgz", + "integrity": "sha512-TEHXuGE79+fEn61qJ7J/A0Ec+WjyNwobrDTATcLg9Zx2/WEMmZNfrWIAlI5ANQAwVbdSWeGVbyoLAK5mbcrE0A==", + "dependencies": { + "@chakra-ui/image": "2.0.15", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/breadcrumb": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@chakra-ui/breadcrumb/-/breadcrumb-2.1.4.tgz", + "integrity": "sha512-vyBx5TAxPnHhb0b8nyRGfqyjleD//9mySFhk96c9GL+T6YDO4swHw5y/kvDv3Ngc/iRwJ9hdI49PZKwPxLqsEg==", + "dependencies": { + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/breakpoint-utils": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/breakpoint-utils/-/breakpoint-utils-2.0.8.tgz", + "integrity": "sha512-Pq32MlEX9fwb5j5xx8s18zJMARNHlQZH2VH1RZgfgRDpp7DcEgtRW5AInfN5CfqdHLO1dGxA7I3MqEuL5JnIsA==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5" + } + }, + "node_modules/@chakra-ui/button": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@chakra-ui/button/-/button-2.0.16.tgz", + "integrity": "sha512-NjuTKa7gNhnGSUutKuTc8HoAOe9WWIigpciBG7yj3ok67kg8bXtSzPyQFZlgTY6XGdAckWTT+Do4tvhwa5LA+g==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/spinner": "2.0.13" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/card": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/card/-/card-2.1.6.tgz", + "integrity": "sha512-fFd/WAdRNVY/WOSQv4skpy0WeVhhI0f7dTY1Sm0jVl0KLmuP/GnpsWtKtqWjNcV00K963EXDyhlk6+9oxbP4gw==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/checkbox": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@chakra-ui/checkbox/-/checkbox-2.2.10.tgz", + "integrity": "sha512-vzxEjw99qj7loxAdP1WuHNt4EAvj/t6cc8oxyOB2mEvkAzhxI34rLR+3zWDuHWsmhyUO+XEDh4FiWdR+DK5Siw==", + "dependencies": { + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-callback-ref": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/react-use-update-effect": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/visually-hidden": "2.0.15", + "@zag-js/focus-visible": "0.2.1" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/clickable": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@chakra-ui/clickable/-/clickable-2.0.14.tgz", + "integrity": "sha512-jfsM1qaD74ZykLHmvmsKRhDyokLUxEfL8Il1VoZMNX5RBI0xW/56vKpLTFF/v/+vLPLS+Te2cZdD4+2O+G6ulA==", + "dependencies": { + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/close-button": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/close-button/-/close-button-2.0.17.tgz", + "integrity": "sha512-05YPXk456t1Xa3KpqTrvm+7smx+95dmaPiwjiBN3p7LHUQVHJd8ZXSDB0V+WKi419k3cVQeJUdU/azDO2f40sw==", + "dependencies": { + "@chakra-ui/icon": "3.0.16" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/color-mode": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@chakra-ui/color-mode/-/color-mode-2.1.12.tgz", + "integrity": "sha512-sYyfJGDoJSLYO+V2hxV9r033qhte5Nw/wAn5yRGGZnEEN1dKPEdWQ3XZvglWSDTNd0w9zkoH2w6vP4FBBYb/iw==", + "dependencies": { + "@chakra-ui/react-use-safe-layout-effect": "2.0.5" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/control-box": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@chakra-ui/control-box/-/control-box-2.0.13.tgz", + "integrity": "sha512-FEyrU4crxati80KUF/+1Z1CU3eZK6Sa0Yv7Z/ydtz9/tvGblXW9NFanoomXAOvcIFLbaLQPPATm9Gmpr7VG05A==", + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/counter": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@chakra-ui/counter/-/counter-2.0.14.tgz", + "integrity": "sha512-KxcSRfUbb94dP77xTip2myoE7P2HQQN4V5fRJmNAGbzcyLciJ+aDylUU/UxgNcEjawUp6Q242NbWb1TSbKoqog==", + "dependencies": { + "@chakra-ui/number-utils": "2.0.7", + "@chakra-ui/react-use-callback-ref": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/css-reset": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@chakra-ui/css-reset/-/css-reset-2.0.12.tgz", + "integrity": "sha512-Q5OYIMvqTl2vZ947kIYxcS5DhQXeStB84BzzBd6C10wOx1gFUu9pL+jLpOnHR3hhpWRMdX5o7eT+gMJWIYUZ0Q==", + "peerDependencies": { + "@emotion/react": ">=10.0.35", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/descendant": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@chakra-ui/descendant/-/descendant-3.0.13.tgz", + "integrity": "sha512-9nzxZVxUSMc4xPL5fSaRkEOQjDQWUGjGvrZI7VzWk9eq63cojOtIxtWMSW383G9148PzWJjJYt30Eud5tdZzlg==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/dom-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/dom-utils/-/dom-utils-2.0.6.tgz", + "integrity": "sha512-PVtDkPrDD5b8aoL6Atg7SLjkwhWb7BwMcLOF1L449L3nZN+DAO3nyAh6iUhZVJyunELj9d0r65CDlnMREyJZmA==" + }, + "node_modules/@chakra-ui/editable": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@chakra-ui/editable/-/editable-2.0.19.tgz", + "integrity": "sha512-YxRJsJ2JQd42zfPBgTKzIhg1HugT+gfQz1ZosmUN+IZT9YZXL2yodHTUz6Lee04Vc/CdEqgBFLuREXEUNBfGtA==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-callback-ref": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-focus-on-pointer-down": "2.0.6", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/react-use-update-effect": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/event-utils": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/event-utils/-/event-utils-2.0.8.tgz", + "integrity": "sha512-IGM/yGUHS+8TOQrZGpAKOJl/xGBrmRYJrmbHfUE7zrG3PpQyXvbLDP1M+RggkCFVgHlJi2wpYIf0QtQlU0XZfw==" + }, + "node_modules/@chakra-ui/focus-lock": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@chakra-ui/focus-lock/-/focus-lock-2.0.16.tgz", + "integrity": "sha512-UuAdGCPVrCa1lecoAvpOQD7JFT7a9RdmhKWhFt5ioIcekSLJcerdLHuuL3w0qz//8kd1/SOt7oP0aJqdAJQrCw==", + "dependencies": { + "@chakra-ui/dom-utils": "2.0.6", + "react-focus-lock": "^2.9.2" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/form-control": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/form-control/-/form-control-2.0.17.tgz", + "integrity": "sha512-34ptCaJ2LNvQNOlB6MAKsmH1AkT1xo7E+3Vw10Urr81yTOjDTM/iU6vG3JKPfRDMyXeowPjXmutlnuk72SSjRg==", + "dependencies": { + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/hooks": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/hooks/-/hooks-2.1.6.tgz", + "integrity": "sha512-oMSOeoOF6/UpwTVlDFHSROAA4hPY8WgJ0erdHs1ZkuwAwHv7UzjDkvrb6xYzAAH9qHoFzc5RIBm6jVoh3LCc+Q==", + "dependencies": { + "@chakra-ui/react-utils": "2.0.12", + "@chakra-ui/utils": "2.0.15", + "compute-scroll-into-view": "1.0.20", + "copy-to-clipboard": "3.3.3" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/icon": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-3.0.16.tgz", + "integrity": "sha512-RpA1X5Ptz8Mt39HSyEIW1wxAz2AXyf9H0JJ5HVx/dBdMZaGMDJ0HyyPBVci0m4RCoJuyG1HHG/DXJaVfUTVAeg==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/image": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@chakra-ui/image/-/image-2.0.15.tgz", + "integrity": "sha512-w2rElXtI3FHXuGpMCsSklus+pO1Pl2LWDwsCGdpBQUvGFbnHfl7MftQgTlaGHeD5OS95Pxva39hKrA2VklKHiQ==", + "dependencies": { + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/input": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@chakra-ui/input/-/input-2.0.20.tgz", + "integrity": "sha512-ypmsy4n4uNBVgn6Gd24Zrpi+qRf/T9WEzWkysuYC9Qfxo+i7yuf3snp7XmBy8KSGVSiXE11eO8ZN5oCg6Xg0jg==", + "dependencies": { + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/object-utils": "2.0.8", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/layout": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@chakra-ui/layout/-/layout-2.1.16.tgz", + "integrity": "sha512-QFS3feozIGsvB0H74lUocev55aRF26eNrdmhfJifwikZAiq+zzZAMdBdNU9UJhHClnMOU8/iGZ0MF7ti4zQS1A==", + "dependencies": { + "@chakra-ui/breakpoint-utils": "2.0.8", + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/object-utils": "2.0.8", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/lazy-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/lazy-utils/-/lazy-utils-2.0.5.tgz", + "integrity": "sha512-UULqw7FBvcckQk2n3iPO56TMJvDsNv0FKZI6PlUNJVaGsPbsYxK/8IQ60vZgaTVPtVcjY6BE+y6zg8u9HOqpyg==" + }, + "node_modules/@chakra-ui/live-region": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@chakra-ui/live-region/-/live-region-2.0.13.tgz", + "integrity": "sha512-Ja+Slk6ZkxSA5oJzU2VuGU7TpZpbMb/4P4OUhIf2D30ctmIeXkxTWw1Bs1nGJAVtAPcGS5sKA+zb89i8g+0cTQ==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/media-query": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/@chakra-ui/media-query/-/media-query-3.2.12.tgz", + "integrity": "sha512-8pSLDf3oxxhFrhd40rs7vSeIBfvOmIKHA7DJlGUC/y+9irD24ZwgmCtFnn+y3gI47hTJsopbSX+wb8nr7XPswA==", + "dependencies": { + "@chakra-ui/breakpoint-utils": "2.0.8", + "@chakra-ui/react-env": "3.0.0", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/menu": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/menu/-/menu-2.1.9.tgz", + "integrity": "sha512-ue5nD4QJcl3H3UwN0zZNJmH89XUebnvEdW6THAUL41hDjJ0J/Fjpg9Sgzwug2aBbBXBNbVMsUuhcCj6x91d+IQ==", + "dependencies": { + "@chakra-ui/clickable": "2.0.14", + "@chakra-ui/descendant": "3.0.13", + "@chakra-ui/lazy-utils": "2.0.5", + "@chakra-ui/popper": "3.0.13", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-animation-state": "2.0.8", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-disclosure": "2.0.8", + "@chakra-ui/react-use-focus-effect": "2.0.9", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-outside-click": "2.0.7", + "@chakra-ui/react-use-update-effect": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/transition": "2.0.15" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/modal": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/modal/-/modal-2.2.9.tgz", + "integrity": "sha512-nTfNp7XsVwn5+xJOtstoFA8j0kq/9sJj7KesyYzjEDaMKvCZvIOntRYowoydho43jb4+YC7ebKhp0KOIINS0gg==", + "dependencies": { + "@chakra-ui/close-button": "2.0.17", + "@chakra-ui/focus-lock": "2.0.16", + "@chakra-ui/portal": "2.0.15", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/transition": "2.0.15", + "aria-hidden": "^1.2.2", + "react-remove-scroll": "^2.5.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/number-input": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@chakra-ui/number-input/-/number-input-2.0.18.tgz", + "integrity": "sha512-cPkyAFFHHzeFBselrT1BtjlzMkJ6TKrTDUnHFlzqXy6aqeXuhrjFhMfXucjedSpOqedsP9ZbKFTdIAhu9DdL/A==", + "dependencies": { + "@chakra-ui/counter": "2.0.14", + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-callback-ref": "2.0.7", + "@chakra-ui/react-use-event-listener": "2.0.7", + "@chakra-ui/react-use-interval": "2.0.5", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/react-use-update-effect": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/number-utils": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/number-utils/-/number-utils-2.0.7.tgz", + "integrity": "sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg==" + }, + "node_modules/@chakra-ui/object-utils": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/object-utils/-/object-utils-2.0.8.tgz", + "integrity": "sha512-2upjT2JgRuiupdrtBWklKBS6tqeGMA77Nh6Q0JaoQuH/8yq+15CGckqn3IUWkWoGI0Fg3bK9LDlbbD+9DLw95Q==" + }, + "node_modules/@chakra-ui/pin-input": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@chakra-ui/pin-input/-/pin-input-2.0.19.tgz", + "integrity": "sha512-6O7s4vWz4cqQ6zvMov9sYj6ZqWAsTxR/MNGe3DNgu1zWQg8veNCYtj1rNGhNS3eZNUMAa8uM2dXIphGTP53Xow==", + "dependencies": { + "@chakra-ui/descendant": "3.0.13", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/popover": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/popover/-/popover-2.1.8.tgz", + "integrity": "sha512-ob7fAz+WWmXIq7iGHVB3wDKzZTj+T+noYBT/U1Q+jIf+jMr2WOpJLTfb0HTZcfhvn4EBFlfBg7Wk5qbXNaOn7g==", + "dependencies": { + "@chakra-ui/close-button": "2.0.17", + "@chakra-ui/lazy-utils": "2.0.5", + "@chakra-ui/popper": "3.0.13", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-animation-state": "2.0.8", + "@chakra-ui/react-use-disclosure": "2.0.8", + "@chakra-ui/react-use-focus-effect": "2.0.9", + "@chakra-ui/react-use-focus-on-pointer-down": "2.0.6", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/popper": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@chakra-ui/popper/-/popper-3.0.13.tgz", + "integrity": "sha512-FwtmYz80Ju8oK3Z1HQfisUE7JIMmDsCQsRBu6XuJ3TFQnBHit73yjZmxKjuRJ4JgyT4WBnZoTF3ATbRKSagBeg==", + "dependencies": { + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@popperjs/core": "^2.9.3" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/portal": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@chakra-ui/portal/-/portal-2.0.15.tgz", + "integrity": "sha512-z8v7K3j1/nMuBzp2+wRIIw7s/eipVtnXLdjK5yqbMxMRa44E8Mu5VNJLz3aQFLHXEUST+ifqrjImQeli9do6LQ==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/progress": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/progress/-/progress-2.1.5.tgz", + "integrity": "sha512-jj5Vp4lxUchuwp4RPCepM0yAyKi344bgsOd3Apd+ldxclDcewPc82fbwDu7g/Xv27LqJkT+7E/SlQy04wGrk0g==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/provider": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@chakra-ui/provider/-/provider-2.1.2.tgz", + "integrity": "sha512-4lLlz8QuJv00BhfyKzWpzfoti9MDOdJ/MqXixJV/EZ02RMBOdE9qy9bSz/WckPC2MVhtRUuwMkxH+0QY21PXuw==", + "dependencies": { + "@chakra-ui/css-reset": "2.0.12", + "@chakra-ui/portal": "2.0.15", + "@chakra-ui/react-env": "3.0.0", + "@chakra-ui/system": "2.5.1", + "@chakra-ui/utils": "2.0.15" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0", + "@emotion/styled": "^11.0.0", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/radio": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@chakra-ui/radio/-/radio-2.0.19.tgz", + "integrity": "sha512-PlJiV59eGSmeKP4v/4+ccQUWGRd0cjPKkj/p3L+UbOf8pl9dWm8y9kIeL5TYbghQSDv0nzkrH4+yMnnDTZjdMQ==", + "dependencies": { + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@zag-js/focus-visible": "0.2.1" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-2.5.1.tgz", + "integrity": "sha512-ugkaqfcNMb9L4TkalWiF3rnqfr0TlUUD46JZaDIZiORVisaSwXTZTQrVfG40VghhaJT28rnC5WtiE8kd567ZBQ==", + "dependencies": { + "@chakra-ui/accordion": "2.1.9", + "@chakra-ui/alert": "2.0.17", + "@chakra-ui/avatar": "2.2.5", + "@chakra-ui/breadcrumb": "2.1.4", + "@chakra-ui/button": "2.0.16", + "@chakra-ui/card": "2.1.6", + "@chakra-ui/checkbox": "2.2.10", + "@chakra-ui/close-button": "2.0.17", + "@chakra-ui/control-box": "2.0.13", + "@chakra-ui/counter": "2.0.14", + "@chakra-ui/css-reset": "2.0.12", + "@chakra-ui/editable": "2.0.19", + "@chakra-ui/focus-lock": "2.0.16", + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/hooks": "2.1.6", + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/image": "2.0.15", + "@chakra-ui/input": "2.0.20", + "@chakra-ui/layout": "2.1.16", + "@chakra-ui/live-region": "2.0.13", + "@chakra-ui/media-query": "3.2.12", + "@chakra-ui/menu": "2.1.9", + "@chakra-ui/modal": "2.2.9", + "@chakra-ui/number-input": "2.0.18", + "@chakra-ui/pin-input": "2.0.19", + "@chakra-ui/popover": "2.1.8", + "@chakra-ui/popper": "3.0.13", + "@chakra-ui/portal": "2.0.15", + "@chakra-ui/progress": "2.1.5", + "@chakra-ui/provider": "2.1.2", + "@chakra-ui/radio": "2.0.19", + "@chakra-ui/react-env": "3.0.0", + "@chakra-ui/select": "2.0.18", + "@chakra-ui/skeleton": "2.0.24", + "@chakra-ui/slider": "2.0.21", + "@chakra-ui/spinner": "2.0.13", + "@chakra-ui/stat": "2.0.17", + "@chakra-ui/styled-system": "2.6.1", + "@chakra-ui/switch": "2.0.22", + "@chakra-ui/system": "2.5.1", + "@chakra-ui/table": "2.0.16", + "@chakra-ui/tabs": "2.1.8", + "@chakra-ui/tag": "2.0.17", + "@chakra-ui/textarea": "2.0.18", + "@chakra-ui/theme": "2.2.5", + "@chakra-ui/theme-utils": "2.0.11", + "@chakra-ui/toast": "6.0.1", + "@chakra-ui/tooltip": "2.2.6", + "@chakra-ui/transition": "2.0.15", + "@chakra-ui/utils": "2.0.15", + "@chakra-ui/visually-hidden": "2.0.15" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0", + "@emotion/styled": "^11.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/react-children-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-children-utils/-/react-children-utils-2.0.6.tgz", + "integrity": "sha512-QVR2RC7QsOsbWwEnq9YduhpqSFnZGvjjGREV8ygKi8ADhXh93C8azLECCUVgRJF2Wc+So1fgxmjLcbZfY2VmBA==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-context": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-context/-/react-context-2.0.7.tgz", + "integrity": "sha512-i7EGmSU+h2GB30cwrKB4t1R5BMHyGoJM5L2Zz7b+ZUX4aAqyPcfe97wPiQB6Rgr1ImGXrUeov4CDVrRZ2FPgLQ==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-env": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-env/-/react-env-3.0.0.tgz", + "integrity": "sha512-tfMRO2v508HQWAqSADFrwZgR9oU10qC97oV6zGbjHh9ALP0/IcFR+Bi71KRTveDTm85fMeAzZYGj57P3Dsipkw==", + "dependencies": { + "@chakra-ui/react-use-safe-layout-effect": "2.0.5" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-types/-/react-types-2.0.7.tgz", + "integrity": "sha512-12zv2qIZ8EHwiytggtGvo4iLT0APris7T0qaAWqzpUGS0cdUtR8W+V1BJ5Ocq+7tA6dzQ/7+w5hmXih61TuhWQ==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-animation-state": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-animation-state/-/react-use-animation-state-2.0.8.tgz", + "integrity": "sha512-xv9zSF2Rd1mHWQ+m5DLBWeh4atF8qrNvsOs3MNrvxKYBS3f79N3pqcQGrWAEvirXWXfiCeje2VAkEggqFRIo+Q==", + "dependencies": { + "@chakra-ui/dom-utils": "2.0.6", + "@chakra-ui/react-use-event-listener": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-callback-ref": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.0.7.tgz", + "integrity": "sha512-YjT76nTpfHAK5NxplAlZsQwNju5KmQExnqsWNPFeOR6vvbC34+iPSTr+r91i1Hdy7gBSbevsOsd5Wm6RN3GuMw==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-controllable-state": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-controllable-state/-/react-use-controllable-state-2.0.8.tgz", + "integrity": "sha512-F7rdCbLEmRjwwODqWZ3y+mKgSSHPcLQxeUygwk1BkZPXbKkJJKymOIjIynil2cbH7ku3hcSIWRvuhpCcfQWJ7Q==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-disclosure": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-disclosure/-/react-use-disclosure-2.0.8.tgz", + "integrity": "sha512-2ir/mHe1YND40e+FyLHnDsnDsBQPwzKDLzfe9GZri7y31oU83JSbHdlAXAhp3bpjohslwavtRCp+S/zRxfO9aQ==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-event-listener": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.0.7.tgz", + "integrity": "sha512-4wvpx4yudIO3B31pOrXuTHDErawmwiXnvAN7gLEOVREi16+YGNcFnRJ5X5nRrmB7j2MDUtsEDpRBFfw5Z9xQ5g==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-focus-effect": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-focus-effect/-/react-use-focus-effect-2.0.9.tgz", + "integrity": "sha512-20nfNkpbVwyb41q9wxp8c4jmVp6TUGAPE3uFTDpiGcIOyPW5aecQtPmTXPMJH+2aa8Nu1wyoT1btxO+UYiQM3g==", + "dependencies": { + "@chakra-ui/dom-utils": "2.0.6", + "@chakra-ui/react-use-event-listener": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/react-use-update-effect": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-focus-on-pointer-down": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-focus-on-pointer-down/-/react-use-focus-on-pointer-down-2.0.6.tgz", + "integrity": "sha512-OigXiLRVySn3tyVqJ/rn57WGuukW8TQe8fJYiLwXbcNyAMuYYounvRxvCy2b53sQ7QIZamza0N0jhirbH5FNoQ==", + "dependencies": { + "@chakra-ui/react-use-event-listener": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-interval": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-interval/-/react-use-interval-2.0.5.tgz", + "integrity": "sha512-1nbdwMi2K87V6p5f5AseOKif2CkldLaJlq1TOqaPRwb7v3aU9rltBtYdf+fIyuHSToNJUV6wd9budCFdLCl3Fg==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-latest-ref": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-latest-ref/-/react-use-latest-ref-2.0.5.tgz", + "integrity": "sha512-3mIuFzMyIo3Ok/D8uhV9voVg7KkrYVO/pwVvNPJOHsDQqCA6DpYE4WDsrIx+fVcwad3Ta7SupexR5PoI+kq6QQ==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-merge-refs": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.0.7.tgz", + "integrity": "sha512-zds4Uhsc+AMzdH8JDDkLVet9baUBgtOjPbhC5r3A0ZXjZvGhCztFAVE3aExYiVoMPoHLKbLcqvCWE6ioFKz1lw==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-outside-click": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-outside-click/-/react-use-outside-click-2.0.7.tgz", + "integrity": "sha512-MsAuGLkwYNxNJ5rb8lYNvXApXxYMnJ3MzqBpQj1kh5qP/+JSla9XMjE/P94ub4fSEttmNSqs43SmPPrmPuihsQ==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-pan-event": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-pan-event/-/react-use-pan-event-2.0.9.tgz", + "integrity": "sha512-xu35QXkiyrgsHUOnctl+SwNcwf9Rl62uYE5y8soKOZdBm8E+FvZIt2hxUzK1EoekbJCMzEZ0Yv1ZQCssVkSLaQ==", + "dependencies": { + "@chakra-ui/event-utils": "2.0.8", + "@chakra-ui/react-use-latest-ref": "2.0.5", + "framesync": "6.1.2" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-previous": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-previous/-/react-use-previous-2.0.5.tgz", + "integrity": "sha512-BIZgjycPE4Xr+MkhKe0h67uHXzQQkBX/u5rYPd65iMGdX1bCkbE0oorZNfOHLKdTmnEb4oVsNvfN6Rfr+Mnbxw==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-safe-layout-effect": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.0.5.tgz", + "integrity": "sha512-MwAQBz3VxoeFLaesaSEN87reVNVbjcQBDex2WGexAg6hUB6n4gc1OWYH/iXp4tzp4kuggBNhEHkk9BMYXWfhJQ==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-size": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-size/-/react-use-size-2.0.9.tgz", + "integrity": "sha512-Jce7QmO1jlQZq+Y77VKckWzroRnajChzUQ8xhLQZO6VbYvrpg3cu+X2QCz3G+MZzB+1/hnvvAqmZ+uJLd8rEJg==", + "dependencies": { + "@zag-js/element-size": "0.3.1" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-timeout": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-timeout/-/react-use-timeout-2.0.5.tgz", + "integrity": "sha512-QqmB+jVphh3h/CS60PieorpY7UqSPkrQCB7f7F+i9vwwIjtP8fxVHMmkb64K7VlzQiMPzv12nlID5dqkzlv0mw==", + "dependencies": { + "@chakra-ui/react-use-callback-ref": "2.0.7" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-use-update-effect": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.0.7.tgz", + "integrity": "sha512-vBM2bmmM83ZdDtasWv3PXPznpTUd+FvqBC8J8rxoRmvdMEfrxTiQRBJhiGHLpS9BPLLPQlosN6KdFU97csB6zg==", + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/react-utils": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@chakra-ui/react-utils/-/react-utils-2.0.12.tgz", + "integrity": "sha512-GbSfVb283+YA3kA8w8xWmzbjNWk14uhNpntnipHCftBibl0lxtQ9YqMFQLwuFOO0U2gYVocszqqDWX+XNKq9hw==", + "dependencies": { + "@chakra-ui/utils": "2.0.15" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@chakra-ui/select": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@chakra-ui/select/-/select-2.0.18.tgz", + "integrity": "sha512-1d2lUT5LM6oOs5x4lzBh4GFDuXX62+lr+sgV7099g951/5UNbb0CS2hSZHsO7yZThLNbr7QTWZvAOAayVcGzdw==", + "dependencies": { + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/shared-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz", + "integrity": "sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q==" + }, + "node_modules/@chakra-ui/skeleton": { + "version": "2.0.24", + "resolved": "https://registry.npmjs.org/@chakra-ui/skeleton/-/skeleton-2.0.24.tgz", + "integrity": "sha512-1jXtVKcl/jpbrJlc/TyMsFyI651GTXY5ma30kWyTXoby2E+cxbV6OR8GB/NMZdGxbQBax8/VdtYVjI0n+OBqWA==", + "dependencies": { + "@chakra-ui/media-query": "3.2.12", + "@chakra-ui/react-use-previous": "2.0.5", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/slider": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@chakra-ui/slider/-/slider-2.0.21.tgz", + "integrity": "sha512-Mm76yJxEqJl21+3waEcKg3tM8Y4elJ7mcViN6Brj35PTfzUJfSJxeBGo1nLPJ+X5jLj7o/L4kfBmUk3lY4QYEQ==", + "dependencies": { + "@chakra-ui/number-utils": "2.0.7", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-callback-ref": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-latest-ref": "2.0.5", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-pan-event": "2.0.9", + "@chakra-ui/react-use-size": "2.0.9", + "@chakra-ui/react-use-update-effect": "2.0.7" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/spinner": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@chakra-ui/spinner/-/spinner-2.0.13.tgz", + "integrity": "sha512-T1/aSkVpUIuiYyrjfn1+LsQEG7Onbi1UE9ccS/evgf61Dzy4GgTXQUnDuWFSgpV58owqirqOu6jn/9eCwDlzlg==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/stat": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/stat/-/stat-2.0.17.tgz", + "integrity": "sha512-PhD+5oVLWjQmGLfeZSmexp3AtLcaggWBwoMZ4z8QMZIQzf/fJJWMk0bMqxlpTv8ORDkfY/4ImuFB/RJHvcqlcA==", + "dependencies": { + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/styled-system": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.6.1.tgz", + "integrity": "sha512-jy/1dVi1LxjoRCm+Eo5mqBgvPy5SCWMlIcz6GbIZBDpkGeKZwtqrZLjekxxLBCy8ORY+kJlUB0FT6AzVR/1tjw==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5", + "csstype": "^3.0.11", + "lodash.mergewith": "4.6.2" + } + }, + "node_modules/@chakra-ui/switch": { + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/@chakra-ui/switch/-/switch-2.0.22.tgz", + "integrity": "sha512-+/Yy6y7VFD91uSPruF8ZvePi3tl5D8UNVATtWEQ+QBI92DLSM+PtgJ2F0Y9GMZ9NzMxpZ80DqwY7/kqcPCfLvw==", + "dependencies": { + "@chakra-ui/checkbox": "2.2.10", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/system": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/system/-/system-2.5.1.tgz", + "integrity": "sha512-4+86OrcSoq7lGkm5fh+sJ3IWXSTzjz+HOllRbCW2Rtnmcg7ritiXVNV2VygEg2DrCcx5+tNqRHDM764zW+AEug==", + "dependencies": { + "@chakra-ui/color-mode": "2.1.12", + "@chakra-ui/object-utils": "2.0.8", + "@chakra-ui/react-utils": "2.0.12", + "@chakra-ui/styled-system": "2.6.1", + "@chakra-ui/theme-utils": "2.0.11", + "@chakra-ui/utils": "2.0.15", + "react-fast-compare": "3.2.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0", + "@emotion/styled": "^11.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/table": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@chakra-ui/table/-/table-2.0.16.tgz", + "integrity": "sha512-vWDXZ6Ad3Aj66curp1tZBHvCfQHX2FJ4ijLiqGgQszWFIchfhJ5vMgEBJaFMZ+BN1draAjuRTZqaQefOApzvRg==", + "dependencies": { + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/tabs": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@chakra-ui/tabs/-/tabs-2.1.8.tgz", + "integrity": "sha512-B7LeFN04Ny2jsSy5TFOQxnbZ6ITxGxLxsB2PE0vvQjMSblBrUryOxdjw80HZhfiw6od0ikK9CeKQOIt9QCguSw==", + "dependencies": { + "@chakra-ui/clickable": "2.0.14", + "@chakra-ui/descendant": "3.0.13", + "@chakra-ui/lazy-utils": "2.0.5", + "@chakra-ui/react-children-utils": "2.0.6", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-controllable-state": "2.0.8", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/react-use-safe-layout-effect": "2.0.5", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/tag": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/tag/-/tag-2.0.17.tgz", + "integrity": "sha512-A47zE9Ft9qxOJ+5r1cUseKRCoEdqCRzFm0pOtZgRcckqavglk75Xjgz8HbBpUO2zqqd49MlqdOwR8o87fXS1vg==", + "dependencies": { + "@chakra-ui/icon": "3.0.16", + "@chakra-ui/react-context": "2.0.7" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/textarea": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@chakra-ui/textarea/-/textarea-2.0.18.tgz", + "integrity": "sha512-aGHHb29vVifO0OtcK/k8cMykzjOKo/coDTU0NJqz7OOLAWIMNV2eGenvmO1n9tTZbmbqHiX+Sa1nPRX+pd14lg==", + "dependencies": { + "@chakra-ui/form-control": "2.0.17", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/theme": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-2.2.5.tgz", + "integrity": "sha512-hYASZMwu0NqEv6PPydu+F3I+kMNd44yR4TwjR/lXBz/LEh64L6UPY6kQjebCfgdVtsGdl3HKg+eLlfa7SvfRgw==", + "dependencies": { + "@chakra-ui/anatomy": "2.1.2", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/theme-tools": "2.0.17" + }, + "peerDependencies": { + "@chakra-ui/styled-system": ">=2.0.0" + } + }, + "node_modules/@chakra-ui/theme-tools": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.0.17.tgz", + "integrity": "sha512-Auu38hnihlJZQcPok6itRDBbwof3TpXGYtDPnOvrq4Xp7jnab36HLt7KEXSDPXbtOk3ZqU99pvI1en5LbDrdjg==", + "dependencies": { + "@chakra-ui/anatomy": "2.1.2", + "@chakra-ui/shared-utils": "2.0.5", + "color2k": "^2.0.0" + }, + "peerDependencies": { + "@chakra-ui/styled-system": ">=2.0.0" + } + }, + "node_modules/@chakra-ui/theme-utils": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@chakra-ui/theme-utils/-/theme-utils-2.0.11.tgz", + "integrity": "sha512-lBAay6Sq3/fl7exd3mFxWAbzgdQowytor0fnlHrpNStn1HgFjXukwsf6356XQOie2Vd8qaMM7qZtMh4AiC0dcg==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/styled-system": "2.6.1", + "@chakra-ui/theme": "2.2.5", + "lodash.mergewith": "4.6.2" + } + }, + "node_modules/@chakra-ui/toast": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@chakra-ui/toast/-/toast-6.0.1.tgz", + "integrity": "sha512-ej2kJXvu/d2h6qnXU5D8XTyw0qpsfmbiU7hUffo/sPxkz89AUOQ08RUuUmB1ssW/FZcQvNMJ5WgzCTKHGBxtxw==", + "dependencies": { + "@chakra-ui/alert": "2.0.17", + "@chakra-ui/close-button": "2.0.17", + "@chakra-ui/portal": "2.0.15", + "@chakra-ui/react-context": "2.0.7", + "@chakra-ui/react-use-timeout": "2.0.5", + "@chakra-ui/react-use-update-effect": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5", + "@chakra-ui/styled-system": "2.6.1", + "@chakra-ui/theme": "2.2.5" + }, + "peerDependencies": { + "@chakra-ui/system": "2.5.1", + "framer-motion": ">=4.0.0", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/tooltip": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@chakra-ui/tooltip/-/tooltip-2.2.6.tgz", + "integrity": "sha512-4cbneidZ5+HCWge3OZzewRQieIvhDjSsl+scrl4Scx7E0z3OmqlTIESU5nGIZDBLYqKn/UirEZhqaQ33FOS2fw==", + "dependencies": { + "@chakra-ui/popper": "3.0.13", + "@chakra-ui/portal": "2.0.15", + "@chakra-ui/react-types": "2.0.7", + "@chakra-ui/react-use-disclosure": "2.0.8", + "@chakra-ui/react-use-event-listener": "2.0.7", + "@chakra-ui/react-use-merge-refs": "2.0.7", + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "framer-motion": ">=4.0.0", + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/@chakra-ui/transition": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@chakra-ui/transition/-/transition-2.0.15.tgz", + "integrity": "sha512-o9LBK/llQfUDHF/Ty3cQ6nShpekKTqHUoJlUOzNKhoTsNpoRerr9v0jwojrX1YI02KtVjfhFU6PiqXlDfREoNw==", + "dependencies": { + "@chakra-ui/shared-utils": "2.0.5" + }, + "peerDependencies": { + "framer-motion": ">=4.0.0", + "react": ">=18" + } + }, + "node_modules/@chakra-ui/utils": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.0.15.tgz", + "integrity": "sha512-El4+jL0WSaYYs+rJbuYFDbjmfCcfGDmRY95GO4xwzit6YAPZBLcR65rOEwLps+XWluZTy1xdMrusg/hW0c1aAA==", + "dependencies": { + "@types/lodash.mergewith": "4.6.7", + "css-box-model": "1.2.1", + "framesync": "6.1.2", + "lodash.mergewith": "4.6.2" + } + }, + "node_modules/@chakra-ui/visually-hidden": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@chakra-ui/visually-hidden/-/visually-hidden-2.0.15.tgz", + "integrity": "sha512-WWULIiucYRBIewHKFA7BssQ2ABLHLVd9lrUo3N3SZgR0u4ZRDDVEUNOy+r+9ruDze8+36dGbN9wsN1IdELtdOw==", + "peerDependencies": { + "@chakra-ui/system": ">=2.0.0", + "react": ">=18" + } + }, + "node_modules/@csstools/normalize.css": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", + "integrity": "sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==" + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", + "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4", + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "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.1.3" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.10.5", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz", + "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==", + "dependencies": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "node_modules/@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/console/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/core/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", + "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", + "dependencies": { + "jest-get-type": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/reporters/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/transform/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@jest/types/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "dependencies": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "dependencies": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "dependencies": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "dependencies": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "node_modules/@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "dependencies": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", + "integrity": "sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==", + "dependencies": { + "ansi-html-community": "^0.0.8", + "common-path-prefix": "^3.0.0", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "find-up": "^5.0.0", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^3.0.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <4.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@remix-run/router": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", + "integrity": "sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==", + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "dependencies": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "dependencies": { + "@babel/types": "^7.12.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@testing-library/dom": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.0.0.tgz", + "integrity": "sha512-+/TLgKNFsYUshOY/zXsQOk+PlFQK+eyJ9T13IDVNJEi+M+Un7xlJK+FZKkbGSnf0+7E1G6PlDhkSYQ/GFiruBQ==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "peer": true + }, + "node_modules/@testing-library/dom/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==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz", + "integrity": "sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@testing-library/jest-dom/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", + "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@testing-library/react/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@testing-library/react/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.4.3", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.4.3.tgz", + "integrity": "sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz", + "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", + "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.1.tgz", + "integrity": "sha512-rc9K8ZpVjNcLs8Fp0dkozd5Pt2Apk1glO4Vgz8ix1u6yFByxfqo5Yavpy65o+93TAe24jr7v+eSBtFLvOQtCRQ==", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.10", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz", + "integrity": "sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.4.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", + "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jest/node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/@jest/types": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", + "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", + "dependencies": { + "@jest/schemas": "^29.4.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==" + }, + "node_modules/@types/jest/node_modules/@types/yargs": { + "version": "17.0.22", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", + "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@types/jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/@types/jest/node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/expect": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", + "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", + "dependencies": { + "@jest/expect-utils": "^29.4.3", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.4.3", + "jest-message-util": "^29.4.3", + "jest-util": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/jest/node_modules/jest-diff": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", + "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-matcher-utils": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", + "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-message-util": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", + "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.4.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.4.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/jest-util": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", + "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", + "dependencies": { + "@jest/types": "^29.4.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", + "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/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==" + }, + "node_modules/@types/jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@types/lodash": { + "version": "4.14.191", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", + "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + }, + "node_modules/@types/lodash.mergewith": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz", + "integrity": "sha512-3m+lkO5CLRRYU0fhGRp7zbsGi6+BZj0uTVSwvcKU+nSlhjA9/QRNfuSGnD2mX6hQA7ZbmcCkzk5h4ZYGOtk14A==", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "node_modules/@types/node": { + "version": "18.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz", + "integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "node_modules/@types/prettier": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", + "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "node_modules/@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/react": { + "version": "18.0.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.28.tgz", + "integrity": "sha512-RD0ivG1kEztNBdoAK7lekI9M+azSnitIn85h4iOiaLjaTrMjzslhaqCGaI4IyCJ1RljWiLCEu4jyrLLgqxBTew==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", + "integrity": "sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==" + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.5", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", + "integrity": "sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ==", + "dependencies": { + "@types/jest": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz", + "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==" + }, + "node_modules/@types/ws": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.53.0.tgz", + "integrity": "sha512-alFpFWNucPLdUOySmXCJpzr6HKC3bu7XooShWM+3w/EL6J2HIoB2PFxpLnq4JauWVk6DiVeNKzQlFEaE+X9sGw==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/type-utils": "5.53.0", + "@typescript-eslint/utils": "5.53.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.53.0.tgz", + "integrity": "sha512-4SklZEwRn0jqkhtW+pPZpbKFXprwGneBndRM0TGzJu/LWdb9QV2hBgFIVU9AREo02BzqFvyG/ypd+xAW5YGhXw==", + "dependencies": { + "@typescript-eslint/utils": "5.53.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", + "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", + "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "dependencies": { + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.53.0.tgz", + "integrity": "sha512-HO2hh0fmtqNLzTAme/KnND5uFNwbsdYhCZghK2SoxGp3Ifn2emv+hi0PBUjzzSh0dstUIFqOj3bp0AwQlK4OWw==", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/utils": "5.53.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", + "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", + "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "dependencies": { + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/visitor-keys": "5.53.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.53.0.tgz", + "integrity": "sha512-VUOOtPv27UNWLxFwQK/8+7kvxVC+hPHNsJjzlJyotlaHjLSIgOCKj9I0DBUjwOOA64qjBwx5afAPjksqOxMO0g==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.53.0", + "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/typescript-estree": "5.53.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.53.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", + "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", + "dependencies": { + "@typescript-eslint/types": "5.53.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "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==" + }, + "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==" + }, + "node_modules/@zag-js/element-size": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@zag-js/element-size/-/element-size-0.3.1.tgz", + "integrity": "sha512-jR5j4G//bRzcxwAACWi9EfITnwjNmn10LxF4NmALrdZU7/PNWP3uUCdhCxd/0SCyeiJXUl0yvD57rWAbKPs1nw==" + }, + "node_modules/@zag-js/focus-visible": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-0.2.1.tgz", + "integrity": "sha512-19uTjoZGP4/Ax7kSNhhay9JA83BirKzpqLkeEAilrpdI1hE5xuq6q+tzJOsrMOOqJrm7LkmZp5lbsTQzvK2pYg==" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-hidden": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.2.tgz", + "integrity": "sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.9.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "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.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.13", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", + "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001426", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", + "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz", + "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/babel-jest/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "peerDependencies": { + "@babel/core": "^7.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", + "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", + "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", + "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "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", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/bfj": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", + "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", + "dependencies": { + "bluebird": "^3.5.5", + "check-types": "^11.1.1", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.0.tgz", + "integrity": "sha512-LVRinRB3k1/K0XzZ2p58COnWvkQknIY6sf0zF2rpErvcJXpMBttEPQSxK+HEXSS9VmpZlDoDnQWv8ftJT20B0Q==", + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001457", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz", + "integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/check-types": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.2.tgz", + "integrity": "sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" + }, + "node_modules/clean-css": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "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==" + }, + "node_modules/color2k": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.2.tgz", + "integrity": "sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "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/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.28.0.tgz", + "integrity": "sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz", + "integrity": "sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==", + "dependencies": { + "browserslist": "^4.21.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.28.0.tgz", + "integrity": "sha512-DSOVleA9/v3LNj/vFxAPfUHttKTzrB2RXhAPvR5TPXn4vrra3Z2ssytvRyt8eruJwAfwAiFADEbrjcRdcvPLQQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "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/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", + "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-loader": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", + "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.19", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "node_modules/cssdb": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.4.1.tgz", + "integrity": "sha512-0Q8NOMpXJ3iTDDbUv9grcmQAfdDx4qz+fN/+Md2FGbevT+6+bJNQ2LjB2YIUlLbpBTM32idU1Sb+tb/uGt6/XQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + }, + "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==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/csso/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, + "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==" + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", + "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "node_modules/dns-packet": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.309", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.309.tgz", + "integrity": "sha512-U7DTiKe4h+irqBG6h4EZ0XXaZuJj4md3xIXXaGSYhwiumPZ4BSc6rgf9UD0hVUMaeP/jB0q5pKWCPxvhO8fvZA==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", + "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.1", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", + "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", + "dependencies": { + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "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==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "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==", + "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==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, + "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==", + "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==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-testing-library": { + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz", + "integrity": "sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==", + "dependencies": { + "@typescript-eslint/utils": "^5.43.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/eslint-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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/eslint-webpack-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/eslint-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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/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/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "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", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "node_modules/focus-lock": { + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.11.6.tgz", + "integrity": "sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg==", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", + "dependencies": { + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/framer-motion/node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/framer-motion/node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, + "node_modules/framer-motion/node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/framesync": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz", + "integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==", + "dependencies": { + "tslib": "2.4.0" + } + }, + "node_modules/framesync/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "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", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, + "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/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz", + "integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "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-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + }, + "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==" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "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==", + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "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==", + "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-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "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", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "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==", + "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.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "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==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jake/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-circus/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-cli/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-config/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-diff/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-each/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-jasmine2/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-jasmine2/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-matcher-utils/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-message-util/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-resolve/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-runner/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-runtime/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-snapshot/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-util/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-validate/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { + "version": "17.0.22", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", + "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/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==" + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jest-watcher/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + }, + "engines": { + "node": ">=4.0" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "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==" + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "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==", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "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/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz", + "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==", + "dependencies": { + "fs-monkey": "^1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", + "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "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==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.2.tgz", + "integrity": "sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz", + "integrity": "sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw==", + "dependencies": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, + "node_modules/popmotion/node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "browserslist": ">=4", + "postcss": ">=8" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "peerDependencies": { + "postcss": "^8.1.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "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.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "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==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "dependencies": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "browserslist": ">= 4", + "postcss": ">= 8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/postcss-svgo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "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==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "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", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "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", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "dependencies": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-clientside-effect": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/react-clientside-effect/-/react-clientside-effect-1.2.6.tgz", + "integrity": "sha512-XGGGRQAKY+q25Lz9a/4EPqom7WRjz3z9R2k4jhVKA/puQFH/5Nt27vFZYql4m4NVNdUvX8PS3O7r/Zzm7cjUlg==", + "dependencies": { + "@babel/runtime": "^7.12.13" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/react-dev-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/react-dev-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/react-dev-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/react-dev-utils/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "node_modules/react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, + "node_modules/react-focus-lock": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/react-focus-lock/-/react-focus-lock-2.9.4.tgz", + "integrity": "sha512-7pEdXyMseqm3kVjhdVH18sovparAzLg5h6WvIx7/Ck3ekjhrrDMEegHSa3swwC8wgfdd7DIdUVRGeiHT9/7Sgg==", + "dependencies": { + "@babel/runtime": "^7.0.0", + "focus-lock": "^0.11.6", + "prop-types": "^15.6.2", + "react-clientside-effect": "^1.2.6", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-icons": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-3.11.0.tgz", + "integrity": "sha512-JRgiI/vdF6uyBgyZhVyYJUZAop95Sy4XDe/jmT3R/bKliFWpO/uZBwvSjWEdxwzec7SYbEPNPck0Kff2tUGM2Q==", + "dependencies": { + "camelcase": "^5.0.0" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-icons/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz", + "integrity": "sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.10.0.tgz", + "integrity": "sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==", + "peer": true, + "dependencies": { + "@remix-run/router": "1.5.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.10.0.tgz", + "integrity": "sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==", + "peer": true, + "dependencies": { + "@remix-run/router": "1.5.0", + "react-router": "6.10.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-router-hash-link": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/react-router-hash-link/-/react-router-hash-link-2.4.3.tgz", + "integrity": "sha512-NU7GWc265m92xh/aYD79Vr1W+zAIXDWp3L2YZOYP4rCqPnJ6LI6vh3+rKgkidtYijozHclaEQTAHaAaMWPVI4A==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router-dom": ">=4" + } + }, + "node_modules/react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "dependencies": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "bin": { + "react-scripts": "bin/react-scripts.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": ">= 16", + "typescript": "^3.2.1 || ^4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", + "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.1.tgz", + "integrity": "sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "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/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/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==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", + "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "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==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, + "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-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "node_modules/tailwindcss": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", + "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.0.9", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.16.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz", + "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==", + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "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.6", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", + "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + }, + "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/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==" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "node_modules/to-fast-properties": { + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "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==", + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "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==", + "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/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", + "integrity": "sha512-3FT9PRuRdbB9HfXhEq35u4oZkvpJ5kuYbpqhCfmiZyReuRgpnhDlbr2ZEnnuS0RrJAPn6l23xjFg9kpDM+Ms7w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-vitals": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.4.tgz", + "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==" + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.75.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", + "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "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.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "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-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", + "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.1", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz", + "integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^4.44.2 || ^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.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==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + }, + "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==", + "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==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "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-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" + }, + "node_modules/workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dependencies": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dependencies": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "node_modules/workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==" + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.4.tgz", + "integrity": "sha512-LmWm/zoaahe0EGmMTrSLUi+BjyR3cdGEfU3fS6PN1zKFYbqAKuQ+Oy/27e4VSXsyIwAw8+QDfk1XHNGtZu9nQg==", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "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": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/client/my-app/package.json b/client/my-app/package.json new file mode 100644 index 00000000..94b91264 --- /dev/null +++ b/client/my-app/package.json @@ -0,0 +1,43 @@ +{ + "name": "my-app", + "version": "0.1.0", + "private": true, + "dependencies": { + "@chakra-ui/react": "^2.5.1", + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^14.4.3", + "axios": "^1.3.5", + "cors": "^2.8.5", + "framer-motion": "^6.5.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-icons": "^3.11.0", + "react-router-hash-link": "^2.4.3", + "react-scripts": "5.0.1", + "web-vitals": "^2.1.4" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/client/my-app/public/favicon.ico b/client/my-app/public/favicon.ico new file mode 100644 index 00000000..a11777cc Binary files /dev/null and b/client/my-app/public/favicon.ico differ diff --git a/client/my-app/public/index.html b/client/my-app/public/index.html new file mode 100644 index 00000000..aa069f27 --- /dev/null +++ b/client/my-app/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + React App + + + +
+ + + diff --git a/client/my-app/public/logo192.png b/client/my-app/public/logo192.png new file mode 100644 index 00000000..fc44b0a3 Binary files /dev/null and b/client/my-app/public/logo192.png differ diff --git a/client/my-app/public/logo512.png b/client/my-app/public/logo512.png new file mode 100644 index 00000000..a4e47a65 Binary files /dev/null and b/client/my-app/public/logo512.png differ diff --git a/client/my-app/public/manifest.json b/client/my-app/public/manifest.json new file mode 100644 index 00000000..080d6c77 --- /dev/null +++ b/client/my-app/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/client/my-app/public/robots.txt b/client/my-app/public/robots.txt new file mode 100644 index 00000000..e9e57dc4 --- /dev/null +++ b/client/my-app/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/client/my-app/src/App.js b/client/my-app/src/App.js new file mode 100644 index 00000000..d96e1da6 --- /dev/null +++ b/client/my-app/src/App.js @@ -0,0 +1,50 @@ +import React from 'react'; +import { + ChakraProvider, + extendTheme, + Box, + Text, + Link, + VStack, + Code, + Grid, + GridItem, + Image, +} from '@chakra-ui/react'; +//Colors that we will use +import { theme } from './components/themeFile.js'; +import Navbar from './components/navbar.js'; +import Home from './pages/homePage.js'; +import AboutUsPage from './pages/ourTeam.js'; +import AboutOurModel from './pages/aboutOurModelPage.js'; +import OurMissionPage from './pages/ourMissionPage.js'; +// import { HashLink as HLink } from 'react-router-hash-link'; +import { + BrowserRouter as Router, + Routes, + Route, + BrowserRouter, +} from 'react-router-dom'; + +function App() { + return ( + + + + + + + + + + + + + + + + + ); +} + +export default App; diff --git a/client/my-app/src/App.test.js b/client/my-app/src/App.test.js new file mode 100644 index 00000000..b3fb3494 --- /dev/null +++ b/client/my-app/src/App.test.js @@ -0,0 +1,10 @@ +import React from 'react'; +import { screen } from '@testing-library/react'; +import { render } from './test-utils'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn chakra/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/client/my-app/src/components/navbar.js b/client/my-app/src/components/navbar.js new file mode 100644 index 00000000..49bded76 --- /dev/null +++ b/client/my-app/src/components/navbar.js @@ -0,0 +1,18 @@ +import { Box, Link, HStack, Center, VStack, Flex } from '@chakra-ui/react'; +import { ChakraProvider } from '@chakra-ui/react'; +import { theme } from './themeFile.js'; +import { HashLink as HLink } from 'react-router-hash-link'; + +export default function Navbar() { + return ( + +
+ + Our Mission + About the Model + Our Team + +
+
+ ); +} diff --git a/client/my-app/src/components/themeFile.js b/client/my-app/src/components/themeFile.js new file mode 100644 index 00000000..6a7258e2 --- /dev/null +++ b/client/my-app/src/components/themeFile.js @@ -0,0 +1,17 @@ +import { + extendTheme, + } from '@chakra-ui/react'; + +export const theme = extendTheme({ + colors: { + brand: { + 100: "#e5e1ee", + 200: "#dffdff", + 300: "#90bede", + 400: "#68edc6", + 500: "#90f3ff", + // ... + 900: "#1a202c", + }, + }, +}) \ No newline at end of file diff --git a/client/my-app/src/index.js b/client/my-app/src/index.js new file mode 100644 index 00000000..1e21a0b7 --- /dev/null +++ b/client/my-app/src/index.js @@ -0,0 +1,26 @@ +import { ColorModeScript } from '@chakra-ui/react'; +import React, { StrictMode } from 'react'; +import * as ReactDOM from 'react-dom/client'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; +import * as serviceWorker from './serviceWorker'; + +const container = document.getElementById('root'); +const root = ReactDOM.createRoot(container); + +root.render( + + + + +); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://cra.link/PWA +serviceWorker.unregister(); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/client/my-app/src/pages/aboutOurModelPage.js b/client/my-app/src/pages/aboutOurModelPage.js new file mode 100644 index 00000000..c5e33ba5 --- /dev/null +++ b/client/my-app/src/pages/aboutOurModelPage.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { screen } from '@testing-library/react'; +import { render } from '../test-utils'; +import App from '../App'; +import { + ChakraProvider, + Box, + Text, + Link, + VStack, + Code, + Grid, + GridItem, + Image, + Flex, + Heading, + Center, + Spacer, + Stack, + extendTheme, + Card, + CardHeader, + CardBody, + CardFooter, +} from '@chakra-ui/react'; +import { theme } from '../components/themeFile.js'; + +const aboutOurModelPage = () => { + return ( +
+ + + + + About Our Model + + + + + +
+ + We start off by iterating through the array of files and + filtering by the .png extension. We then created the images from + the files, resized them to 150 by 150 pixels, and converted them + to grayscale to make them all uniform. Then we flattened the + images to a 1d array and added the respective labels, where 0 + was benign, 1 was malignant, and 2 was normal.For our model, + after testing with multiple models such as CNN, SVM, + Naive-Bayes, and K-Nearest, we found that the Random Forest + model had the highest accuracy and was the best fit for our + data. We also experimented with using a combination of CNN, + LSTM, and Random Forest, where the Random Forest classifier was + used for the output layer of the CNN that extracted the + features, which used the ReLU activation function. However, the + Random Forest by itself still gave us the best accuracy. + +
+
+
+
+
+ ); +}; + +export default aboutOurModelPage; diff --git a/client/my-app/src/pages/homePage.js b/client/my-app/src/pages/homePage.js new file mode 100644 index 00000000..9b6b5944 --- /dev/null +++ b/client/my-app/src/pages/homePage.js @@ -0,0 +1,127 @@ +import React, { useState } from 'react'; +import { screen } from '@testing-library/react'; +import { render } from '../test-utils'; +import App from '../App'; +import axios from 'axios'; + +import { + ChakraProvider, + Box, + Text, + Link, + VStack, + HStack, + Code, + Grid, + GridItem, + Image, + Input, + Wrap, + Heading, + Button, + systemProps, +} from '@chakra-ui/react'; +import { theme } from '../components/themeFile.js'; + +const Home = () => { + const [image, setImage] = useState(null); + const onImageChange = async (event) => { + if (event.target.files && event.target.files[0]) { + setImage(event.target.files[0]); + } + }; + + //this.state = {_button : }; + + const [showLoader, setShowLoader] = useState(false); + const [showPrediction, setShowPrediction] = useState(null); + + const onPrediction = async () => { + setShowLoader(true); + const data = new FormData(); + data.append('file', image); + const response = await fetch('http://localhost:5000/predict', { + method: 'POST', + body: data, + }) + const body = await response.json(); + console.log(body); + + if (body == ('0')) { + setShowPrediction("Benign"); + } else if (body == ('1')) { + setShowPrediction("Malignant"); + } else { + setShowPrediction("Normal") + } + setShowLoader(false) + }; + + + return ( + + + + + Introducing our + + + Cancer Detection Algorithm + + + + + + + Please Insert Image + + + {image && preview image} + + + + + + Prediction Output + + + {showPrediction} + + + + + ); +}; + +export default Home; + +// var state = { +// selectedFiled: null, +// }; + +// const fileSelectedHandler = event => { +// if (!event.target.files || event.target.files.length === 0) { +// } +// this.setState({ +// selectedFiled: event.target.files[0], +// }); +// }; + +//UPLOAD INFO HERE: https://www.youtube.com/watch?v=XeiOnkEI7XI https://academind.com/tutorials/reactjs-image-upload +// const fileUploadHandler = () => { +// axios.post('my', this.state.selectedFiled.name); +// }; diff --git a/client/my-app/src/pages/ourMissionPage.js b/client/my-app/src/pages/ourMissionPage.js new file mode 100644 index 00000000..2364a353 --- /dev/null +++ b/client/my-app/src/pages/ourMissionPage.js @@ -0,0 +1,64 @@ +import React from 'react'; +import { + ChakraProvider, + Box, + Text, + VStack, + Flex, + Heading, + Center, +} from '@chakra-ui/react'; +import { theme } from '../components/themeFile.js'; + +const AboutUsPage = () => { + return ( +
+ + + + + Our Mission + + + + + +
+ + Unfortunately, as everyone knows, cancer continues to plague our + world and change the lives of our loved ones. It is imperative + that we strive to help those affected by cancer. A prediction + from the American Cancer Society shows that in 2022, about + 287,850 women were diagnosed with a form of invasive breast + cancer. Although the number of cases is declining each year, + there is clearly still a large number of people affected by + cancer, and we want to help people through that process. Our + main goal will be to create a system that can help entry-level + doctors or doctors with less experience/resources make more + informed decisions. Our system will determine the stage and + severity of a tumor, and further provide resources to help users + understand the diagnosis and formulate appropriate next steps. + Equipped with support from an ML system, doctors can feel more + comfortable in their diagnoses and treatment plans which means + that more people can get the proper care they need. + +
+
+
+
+
+ ); +}; + +export default AboutUsPage; diff --git a/client/my-app/src/pages/ourTeam.js b/client/my-app/src/pages/ourTeam.js new file mode 100644 index 00000000..10cc5e69 --- /dev/null +++ b/client/my-app/src/pages/ourTeam.js @@ -0,0 +1,385 @@ +import React from 'react'; +import { + ChakraProvider, + Box, + Text, + Link, + Grid, + GridItem, + Image, + Heading, + Stack, + Card, + CardBody, +} from '@chakra-ui/react'; +import { theme } from '../components/themeFile.js'; + +const AboutUsPage = () => { + return ( +
+ + + + + Meet The Team + + + + + + + + eshani google drive image + + Eshani Chauk + + Team Lead + + www.linkedin.com/in/eshani-chauk/ + + + + + + + + ronak google drive image + + Ronak Agarwal + + Analysis + + www.linkedin.com/in/ronak-agarwal9/ + + + + + + + + harshika google drive image + + Harshika Gelivi + + Analysis + + www.linkedin.com/in/harshika-gelivi/ + + + + + + + + aryan google drive image + + Aryan Shah + + Analysis + + www.linkedin.com/in/aryan-shah7/ + + + + + + + + harinishree google drive image + + Harinishree Sathu + + Analysis + + www.linkedin.com/in/harinishreesathu/ + + + + + + + + athanasios google drive image + + Athanasios Taprantzis + + Analysis + + + www.linkedin.com/in/athanasios-taprantzis-7227811b8/ + + + + + + + + + saksham google drive image + + Saksham Purbey + + Analysis + + www.linkedin.com/in/saksham-purbey-17b69516b/ + + + + + + + + zeyad google drive image + + Zeyad Al Sakhi + + Platform + + www.linkedin.com/in/zeyadalsakhi/ + + + + + + + + divya sharma google drive image + + Divya Sharma + + Platform + + www.linkedin.com/in/divyaasharmaa/ + + + + + + + + william google drive image + + William Shutt + + Platform + + www.linkedin.com/in/william-shutt2/ + + + + + + + + jamez google drive image + + Jamez De Ocampo + + Platform + + www.linkedin.com/in/jamez-de-ocampo-75a467256/ + + + + + + + + rama google drive image + + Rama Khabbaz + + Data Viz + + www.linkedin.com/in/rama-khabbaz-88504a20b/ + + + + + + + + tony google drive image + + Anthony Nguyen + + Data Viz + + www.linkedin.com/in/anthonynguyenv/ + + + + + + + + tae google drive image + + Taesung Uhm + + Data Viz + + www.linkedin.com/in/taesung-uhm-88577b76/ + + + + + + + + simona google drive image + + Simona Ivanov + + Data Viz + + www.linkedin.com/in/simone-ivanov/ + + + + + + + + arrington google drive image + + Arrington Goss + + Data Viz + + www.linkedin.com/in/arrington-goss/ + + + + + + +
+ ); +}; + +export default AboutUsPage; diff --git a/client/my-app/src/reportWebVitals.js b/client/my-app/src/reportWebVitals.js new file mode 100644 index 00000000..5253d3ad --- /dev/null +++ b/client/my-app/src/reportWebVitals.js @@ -0,0 +1,13 @@ +const reportWebVitals = onPerfEntry => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + getCLS(onPerfEntry); + getFID(onPerfEntry); + getFCP(onPerfEntry); + getLCP(onPerfEntry); + getTTFB(onPerfEntry); + }); + } +}; + +export default reportWebVitals; diff --git a/client/my-app/src/serviceWorker.js b/client/my-app/src/serviceWorker.js new file mode 100644 index 00000000..7574e589 --- /dev/null +++ b/client/my-app/src/serviceWorker.js @@ -0,0 +1,141 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://cra.link/PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 are considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) +); + +export function register(config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return; + } + + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config); + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://cra.link/PWA' + ); + }); + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config); + } + }); + } +} + +function registerValidSW(swUrl, config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + if (installingWorker == null) { + return; + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the updated precached content has been fetched, + // but the previous service worker will still serve the older + // content until all client tabs are closed. + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://cra.link/PWA.' + ); + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration); + } + } else { + // At this point, everything has been precached. + // It is the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration); + } + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); +} + +function checkValidServiceWorker(swUrl, config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { 'Service-Worker': 'script' }, + }) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type'); + if ( + response.status === 404 || + (contentType != null && contentType.indexOf('javascript') === -1) + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready + .then(registration => { + registration.unregister(); + }) + .catch(error => { + console.error(error.message); + }); + } +} diff --git a/client/my-app/src/setupTests.js b/client/my-app/src/setupTests.js new file mode 100644 index 00000000..8f2609b7 --- /dev/null +++ b/client/my-app/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom'; diff --git a/client/my-app/src/test-utils.js b/client/my-app/src/test-utils.js new file mode 100644 index 00000000..c1253847 --- /dev/null +++ b/client/my-app/src/test-utils.js @@ -0,0 +1,12 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import { ChakraProvider, theme } from '@chakra-ui/react'; + +const AllProviders = ({ children }) => ( + {children} +); + +const customRender = (ui, options) => + render(ui, { wrapper: AllProviders, ...options }); + +export { customRender as render }; diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 00000000..ac6f59a2 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "client", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/flask-server/model_joblib.pkl b/flask-server/model_joblib.pkl new file mode 100644 index 00000000..25c0a53f Binary files /dev/null and b/flask-server/model_joblib.pkl differ diff --git a/flask-server/requirements.txt b/flask-server/requirements.txt new file mode 100644 index 00000000..61351887 --- /dev/null +++ b/flask-server/requirements.txt @@ -0,0 +1,30 @@ +certifi==2022.12.7 +charset-normalizer==3.1.0 +click==8.1.3 +docopt==0.6.2 +filelock==3.12.0 +Flask==2.2.3 +Flask-Cors==3.0.10 +idna==3.4 +itsdangerous==2.1.2 +Jinja2==3.1.2 +joblib==1.2.0 +MarkupSafe==2.1.2 +mpmath==1.3.0 +networkx==3.1 +numpy==1.24.2 +Pillow==9.5.0 +pipreqs==0.4.13 +requests==2.28.2 +scikit-learn==1.2.2 +scipy==1.10.1 +six==1.16.0 +sklearn==0.0.post4 +sympy==1.11.1 +threadpoolctl==3.1.0 +torch==2.0.0 +torchvision==0.15.1 +typing_extensions==4.5.0 +urllib3==1.26.15 +Werkzeug==2.2.3 +yarg==0.1.9 diff --git a/flask-server/rfModel.py b/flask-server/rfModel.py new file mode 100644 index 00000000..e5a02611 Binary files /dev/null and b/flask-server/rfModel.py differ diff --git a/flask-server/server.py b/flask-server/server.py new file mode 100644 index 00000000..81b850d3 --- /dev/null +++ b/flask-server/server.py @@ -0,0 +1,85 @@ +# from flask import Flask, jsonify + +from flask import Flask, request, Response, jsonify +from flask_cors import CORS + +import torch +from torch import nn +import torchvision.transforms as transforms +import torch.nn.functional as F +import numpy as np +import joblib +import PIL +from PIL import Image, ImageOps +from flask_cors import CORS, cross_origin +from io import BytesIO +import pickle +app = Flask(__name__) +CORS(app) + +@app.route("/testing") +def testing(): + return "hi" + +@app.route("/predict", methods=['POST'], strict_slashes=False) +def predict(): + if request.method == 'POST': + # we will get the file from the request + loadedRf = joblib.load("./model_joblib.pkl") + img = Image.open((request.files['file'])) + img = img.resize((150,150)) + img = img.convert('L') #greyscale + img = img.getdata() + # grayImg = ImageOps.grayscale(img) + # print(type(grayImg)) + # finalImg = img.flatten()/255 + new = np.expand_dims(img, axis =0) + print(type(loadedRf.predict(new))) + num = loadedRf.predict(new)[0] + res = str(num) + return jsonify(res) + # return jsonify({'prediction': loadedRf.predict(new)}); + # return jsonify({'class_id': class_id, 'class_name': class_name}) + + +# def clean(): +# #data processing +# rootdir = Path('/content/cancer-detection/Dataset_BUSI_with_GT') +# images = [] +# labels = [] + +# #os.walk to traverse files in python + +# for subdir, dirs, files in os.walk(rootdir): +# #subdirectory, directory, file partition in the root directory +# for file in files: +# #traversing through each file +# if file.endswith(').png'): +# #the parantheses to just get the scans, not the masks +# full_path = os.path.join(subdir, file) + +# #create image from full path, size is 150 by 150 +# img = PILImage.create(full_path) + +# #resize and grayscale +# img = img.resize((150,150)) +# grayImg = ImageOps.grayscale(img) + +# #flatten images to 1d array, add to images array +# images.append(np.array(grayImg).flatten()/255) + +# #add respective label + +# if 'benign' in full_path: +# labels.append(0) +# elif 'malignant' in full_path: +# labels.append(1) +# elif 'normal' in full_path: +# labels.append(2) + +# cancerImages = np.array(images) +# return cancerImages +if __name__ == "__main__": + app.run(debug=True) + + diff --git a/flask-server/venv/bin/Activate.ps1 b/flask-server/venv/bin/Activate.ps1 new file mode 100644 index 00000000..b49d77ba --- /dev/null +++ b/flask-server/venv/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/flask-server/venv/bin/activate b/flask-server/venv/bin/activate new file mode 100644 index 00000000..c49226b2 --- /dev/null +++ b/flask-server/venv/bin/activate @@ -0,0 +1,69 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(venv) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(venv) " + export VIRTUAL_ENV_PROMPT +fi + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/flask-server/venv/bin/activate.csh b/flask-server/venv/bin/activate.csh new file mode 100644 index 00000000..baa5728f --- /dev/null +++ b/flask-server/venv/bin/activate.csh @@ -0,0 +1,26 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(venv) $prompt" + setenv VIRTUAL_ENV_PROMPT "(venv) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/flask-server/venv/bin/activate.fish b/flask-server/venv/bin/activate.fish new file mode 100644 index 00000000..12eb5a64 --- /dev/null +++ b/flask-server/venv/bin/activate.fish @@ -0,0 +1,66 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/); you cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + functions -e fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(venv) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(venv) " +end diff --git a/flask-server/venv/bin/flask b/flask-server/venv/bin/flask new file mode 100755 index 00000000..d9c2a73a --- /dev/null +++ b/flask-server/venv/bin/flask @@ -0,0 +1,8 @@ +#!/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from flask.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flask-server/venv/bin/pip b/flask-server/venv/bin/pip new file mode 100755 index 00000000..0724877c --- /dev/null +++ b/flask-server/venv/bin/pip @@ -0,0 +1,8 @@ +#!/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flask-server/venv/bin/pip3 b/flask-server/venv/bin/pip3 new file mode 100755 index 00000000..0724877c --- /dev/null +++ b/flask-server/venv/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flask-server/venv/bin/pip3.10 b/flask-server/venv/bin/pip3.10 new file mode 100755 index 00000000..0724877c --- /dev/null +++ b/flask-server/venv/bin/pip3.10 @@ -0,0 +1,8 @@ +#!/Users/taesunguhm/Documents/GitHub/cancer-detection/flask-server/venv/bin/python3 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/flask-server/venv/bin/python b/flask-server/venv/bin/python new file mode 120000 index 00000000..b8a0adbb --- /dev/null +++ b/flask-server/venv/bin/python @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/flask-server/venv/bin/python3 b/flask-server/venv/bin/python3 new file mode 120000 index 00000000..1ec499c5 --- /dev/null +++ b/flask-server/venv/bin/python3 @@ -0,0 +1 @@ +/Library/Frameworks/Python.framework/Versions/3.10/bin/python3 \ No newline at end of file diff --git a/flask-server/venv/bin/python3.10 b/flask-server/venv/bin/python3.10 new file mode 120000 index 00000000..b8a0adbb --- /dev/null +++ b/flask-server/venv/bin/python3.10 @@ -0,0 +1 @@ +python3 \ No newline at end of file diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/INSTALLER b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/LICENSE.rst b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/LICENSE.rst new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/METADATA b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/METADATA new file mode 100644 index 00000000..4edd3370 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/METADATA @@ -0,0 +1,123 @@ +Metadata-Version: 2.1 +Name: Flask +Version: 2.2.3 +Summary: A simple framework for building complex web applications. +Home-page: https://palletsprojects.com/p/flask +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://flask.palletsprojects.com/ +Project-URL: Changes, https://flask.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/flask/ +Project-URL: Issue Tracker, https://github.com/pallets/flask/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Framework :: Flask +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: Werkzeug (>=2.2.2) +Requires-Dist: Jinja2 (>=3.0) +Requires-Dist: itsdangerous (>=2.0) +Requires-Dist: click (>=8.0) +Requires-Dist: importlib-metadata (>=3.6.0) ; python_version < "3.10" +Provides-Extra: async +Requires-Dist: asgiref (>=3.2) ; extra == 'async' +Provides-Extra: dotenv +Requires-Dist: python-dotenv ; extra == 'dotenv' + +Flask +===== + +Flask is a lightweight `WSGI`_ web application framework. It is designed +to make getting started quick and easy, with the ability to scale up to +complex applications. It began as a simple wrapper around `Werkzeug`_ +and `Jinja`_ and has become one of the most popular Python web +application frameworks. + +Flask offers suggestions, but doesn't enforce any dependencies or +project layout. It is up to the developer to choose the tools and +libraries they want to use. There are many extensions provided by the +community that make adding new functionality easy. + +.. _WSGI: https://wsgi.readthedocs.io/ +.. _Werkzeug: https://werkzeug.palletsprojects.com/ +.. _Jinja: https://jinja.palletsprojects.com/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Flask + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + # save this as app.py + from flask import Flask + + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello, World!" + +.. code-block:: text + + $ flask run + * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) + + +Contributing +------------ + +For guidance on setting up a development environment and how to make a +contribution to Flask, see the `contributing guidelines`_. + +.. _contributing guidelines: https://github.com/pallets/flask/blob/main/CONTRIBUTING.rst + + +Donate +------ + +The Pallets organization develops and supports Flask and the libraries +it uses. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://flask.palletsprojects.com/ +- Changes: https://flask.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Flask/ +- Source Code: https://github.com/pallets/flask/ +- Issue Tracker: https://github.com/pallets/flask/issues/ +- Website: https://palletsprojects.com/p/flask/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/RECORD b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/RECORD new file mode 100644 index 00000000..e6d99887 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/RECORD @@ -0,0 +1,54 @@ +../../../bin/flask,sha256=LAlZF4eOLnVb4qecrooVxlQk8AY0EuaOewTAcrxZkyE,273 +Flask-2.2.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Flask-2.2.3.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +Flask-2.2.3.dist-info/METADATA,sha256=gPKNo3B3jmC70HbbmEUzCP5Wq2w64PETRJ52VzANYAI,3889 +Flask-2.2.3.dist-info/RECORD,, +Flask-2.2.3.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +Flask-2.2.3.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92 +Flask-2.2.3.dist-info/entry_points.txt,sha256=s3MqQpduU25y4dq3ftBYD6bMVdVnbMpZP-sUNw0zw0k,41 +Flask-2.2.3.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=3FB-z8gjiwx9Eb6x_OaCdfW9LTyb7ZTIciovc0Ovrm0,2890 +flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30 +flask/__pycache__/__init__.cpython-310.pyc,, +flask/__pycache__/__main__.cpython-310.pyc,, +flask/__pycache__/app.cpython-310.pyc,, +flask/__pycache__/blueprints.cpython-310.pyc,, +flask/__pycache__/cli.cpython-310.pyc,, +flask/__pycache__/config.cpython-310.pyc,, +flask/__pycache__/ctx.cpython-310.pyc,, +flask/__pycache__/debughelpers.cpython-310.pyc,, +flask/__pycache__/globals.cpython-310.pyc,, +flask/__pycache__/helpers.cpython-310.pyc,, +flask/__pycache__/logging.cpython-310.pyc,, +flask/__pycache__/scaffold.cpython-310.pyc,, +flask/__pycache__/sessions.cpython-310.pyc,, +flask/__pycache__/signals.cpython-310.pyc,, +flask/__pycache__/templating.cpython-310.pyc,, +flask/__pycache__/testing.cpython-310.pyc,, +flask/__pycache__/typing.cpython-310.pyc,, +flask/__pycache__/views.cpython-310.pyc,, +flask/__pycache__/wrappers.cpython-310.pyc,, +flask/app.py,sha256=PFYDzGJ4ts7mdmlDurbvfXvMyo2KrO8aVkvspRwiRB0,99107 +flask/blueprints.py,sha256=fenhKP_Sh5eU6qtWeHacg1GVeun4pQzK2vq8sNDd1hY,27266 +flask/cli.py,sha256=pLmnWObe_G4_ZAFQdh7kgwqPMxRXm4oUhaUSBpJMeq4,33532 +flask/config.py,sha256=Ubo_juzSYsAKqD2vD3vm6mjsPo3EOJDdSEzYq8lKTJI,12585 +flask/ctx.py,sha256=bGEQQuF2_cHqZ3ZNMeMeEG8HOLJkDlL88u2BBxCrRao,14829 +flask/debughelpers.py,sha256=_RvAL3TW5lqMJeCVWtTU6rSDJC7jnRaBL6OEkVmooyU,5511 +flask/globals.py,sha256=EX0XdX73BTWdVF0UHDSNet2ER3kI6sKveo3_o5IOs98,3187 +flask/helpers.py,sha256=XTHRgLlyxeEzR988q63-4OY8RswTscR-5exFxK10CLU,25280 +flask/json/__init__.py,sha256=TOwldHT3_kFaXHlORKi9yCWt7dbPNB0ovdHHQWlSRzY,11175 +flask/json/__pycache__/__init__.cpython-310.pyc,, +flask/json/__pycache__/provider.cpython-310.pyc,, +flask/json/__pycache__/tag.cpython-310.pyc,, +flask/json/provider.py,sha256=jXCNypf11PN4ngQjEt6LnSdCWQ1yHIAkNLHlXQlCB-A,10674 +flask/json/tag.py,sha256=fys3HBLssWHuMAIJuTcf2K0bCtosePBKXIWASZEEjnU,8857 +flask/logging.py,sha256=WYng0bLTRS_CJrocGcCLJpibHf1lygHE_pg-KoUIQ4w,2293 +flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/scaffold.py,sha256=EKx-Tr5BXLzeKKvq3ZAi_2oUQVZuC4OJSJTocyDXsSo,35958 +flask/sessions.py,sha256=66oGlE-v9iac-eb54tFN3ILAjJ1FeeuHHWw98UVaoxc,15847 +flask/signals.py,sha256=H7QwDciK-dtBxinjKpexpglP0E6k0MJILiFWTItfmqU,2136 +flask/templating.py,sha256=1P4OzvSnA2fsJTYgQT3G4owVKsuOz8XddCiR6jMHGJ0,7419 +flask/testing.py,sha256=qoMU5L9iMipvNVQ_84MadJx3gsKoSMHD0cQaZDP23rE,10602 +flask/typing.py,sha256=KgxegTF9v9WvuongeF8LooIvpZPauzGrq9ZXf3gBlYc,2969 +flask/views.py,sha256=LulttWL4owVFlgwrJi8GCNM4inC3xbs2IBlY31bdCS4,6765 +flask/wrappers.py,sha256=el3tn1LgSUV0eNGgYMjKICT5I7qGJgbpIhvci4nrwQ8,5702 diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/REQUESTED b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/REQUESTED new file mode 100644 index 00000000..e69de29b diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/WHEEL b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/WHEEL new file mode 100644 index 00000000..57e3d840 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.38.4) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/entry_points.txt b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/entry_points.txt new file mode 100644 index 00000000..137232d7 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +flask = flask.cli:main diff --git a/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/top_level.txt b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/top_level.txt new file mode 100644 index 00000000..7e106024 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Flask-2.2.3.dist-info/top_level.txt @@ -0,0 +1 @@ +flask diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA new file mode 100644 index 00000000..f54bb5ca --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/METADATA @@ -0,0 +1,113 @@ +Metadata-Version: 2.1 +Name: Jinja2 +Version: 3.1.2 +Summary: A very fast and expressive template engine. +Home-page: https://palletsprojects.com/p/jinja/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://jinja.palletsprojects.com/ +Project-URL: Changes, https://jinja.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/jinja/ +Project-URL: Issue Tracker, https://github.com/pallets/jinja/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: MarkupSafe (>=2.0) +Provides-Extra: i18n +Requires-Dist: Babel (>=2.7) ; extra == 'i18n' + +Jinja +===== + +Jinja is a fast, expressive, extensible templating engine. Special +placeholders in the template allow writing code similar to Python +syntax. Then the template is passed data to render the final document. + +It includes: + +- Template inheritance and inclusion. +- Define and import macros within templates. +- HTML templates can use autoescaping to prevent XSS from untrusted + user input. +- A sandboxed environment can safely render untrusted templates. +- AsyncIO support for generating templates and calling async + functions. +- I18N support with Babel. +- Templates are compiled to optimized Python code just-in-time and + cached, or can be compiled ahead-of-time. +- Exceptions point to the correct line in templates to make debugging + easier. +- Extensible filters, tests, functions, and even syntax. + +Jinja's philosophy is that while application logic belongs in Python if +possible, it shouldn't make the template designer's job difficult by +restricting functionality too much. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U Jinja2 + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +In A Nutshell +------------- + +.. code-block:: jinja + + {% extends "base.html" %} + {% block title %}Members{% endblock %} + {% block content %} + + {% endblock %} + + +Donate +------ + +The Pallets organization develops and supports Jinja and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://jinja.palletsprojects.com/ +- Changes: https://jinja.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Jinja2/ +- Source Code: https://github.com/pallets/jinja/ +- Issue Tracker: https://github.com/pallets/jinja/issues/ +- Website: https://palletsprojects.com/p/jinja/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD new file mode 100644 index 00000000..b821b4fa --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/RECORD @@ -0,0 +1,58 @@ +Jinja2-3.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Jinja2-3.1.2.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Jinja2-3.1.2.dist-info/METADATA,sha256=PZ6v2SIidMNixR7MRUX9f7ZWsPwtXanknqiZUmRbh4U,3539 +Jinja2-3.1.2.dist-info/RECORD,, +Jinja2-3.1.2.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +Jinja2-3.1.2.dist-info/entry_points.txt,sha256=zRd62fbqIyfUpsRtU7EVIFyiu1tPwfgO7EvPErnxgTE,59 +Jinja2-3.1.2.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +jinja2/__init__.py,sha256=8vGduD8ytwgD6GDSqpYc2m3aU-T7PKOAddvVXgGr_Fs,1927 +jinja2/__pycache__/__init__.cpython-310.pyc,, +jinja2/__pycache__/_identifier.cpython-310.pyc,, +jinja2/__pycache__/async_utils.cpython-310.pyc,, +jinja2/__pycache__/bccache.cpython-310.pyc,, +jinja2/__pycache__/compiler.cpython-310.pyc,, +jinja2/__pycache__/constants.cpython-310.pyc,, +jinja2/__pycache__/debug.cpython-310.pyc,, +jinja2/__pycache__/defaults.cpython-310.pyc,, +jinja2/__pycache__/environment.cpython-310.pyc,, +jinja2/__pycache__/exceptions.cpython-310.pyc,, +jinja2/__pycache__/ext.cpython-310.pyc,, +jinja2/__pycache__/filters.cpython-310.pyc,, +jinja2/__pycache__/idtracking.cpython-310.pyc,, +jinja2/__pycache__/lexer.cpython-310.pyc,, +jinja2/__pycache__/loaders.cpython-310.pyc,, +jinja2/__pycache__/meta.cpython-310.pyc,, +jinja2/__pycache__/nativetypes.cpython-310.pyc,, +jinja2/__pycache__/nodes.cpython-310.pyc,, +jinja2/__pycache__/optimizer.cpython-310.pyc,, +jinja2/__pycache__/parser.cpython-310.pyc,, +jinja2/__pycache__/runtime.cpython-310.pyc,, +jinja2/__pycache__/sandbox.cpython-310.pyc,, +jinja2/__pycache__/tests.cpython-310.pyc,, +jinja2/__pycache__/utils.cpython-310.pyc,, +jinja2/__pycache__/visitor.cpython-310.pyc,, +jinja2/_identifier.py,sha256=_zYctNKzRqlk_murTNlzrju1FFJL7Va_Ijqqd7ii2lU,1958 +jinja2/async_utils.py,sha256=dHlbTeaxFPtAOQEYOGYh_PHcDT0rsDaUJAFDl_0XtTg,2472 +jinja2/bccache.py,sha256=mhz5xtLxCcHRAa56azOhphIAe19u1we0ojifNMClDio,14061 +jinja2/compiler.py,sha256=Gs-N8ThJ7OWK4-reKoO8Wh1ZXz95MVphBKNVf75qBr8,72172 +jinja2/constants.py,sha256=GMoFydBF_kdpaRKPoM5cl5MviquVRLVyZtfp5-16jg0,1433 +jinja2/debug.py,sha256=iWJ432RadxJNnaMOPrjIDInz50UEgni3_HKuFXi2vuQ,6299 +jinja2/defaults.py,sha256=boBcSw78h-lp20YbaXSJsqkAI2uN_mD_TtCydpeq5wU,1267 +jinja2/environment.py,sha256=6uHIcc7ZblqOMdx_uYNKqRnnwAF0_nzbyeMP9FFtuh4,61349 +jinja2/exceptions.py,sha256=ioHeHrWwCWNaXX1inHmHVblvc4haO7AXsjCp3GfWvx0,5071 +jinja2/ext.py,sha256=ivr3P7LKbddiXDVez20EflcO3q2aHQwz9P_PgWGHVqE,31502 +jinja2/filters.py,sha256=9js1V-h2RlyW90IhLiBGLM2U-k6SCy2F4BUUMgB3K9Q,53509 +jinja2/idtracking.py,sha256=GfNmadir4oDALVxzn3DL9YInhJDr69ebXeA2ygfuCGA,10704 +jinja2/lexer.py,sha256=DW2nX9zk-6MWp65YR2bqqj0xqCvLtD-u9NWT8AnFRxQ,29726 +jinja2/loaders.py,sha256=BfptfvTVpClUd-leMkHczdyPNYFzp_n7PKOJ98iyHOg,23207 +jinja2/meta.py,sha256=GNPEvifmSaU3CMxlbheBOZjeZ277HThOPUTf1RkppKQ,4396 +jinja2/nativetypes.py,sha256=DXgORDPRmVWgy034H0xL8eF7qYoK3DrMxs-935d0Fzk,4226 +jinja2/nodes.py,sha256=i34GPRAZexXMT6bwuf5SEyvdmS-bRCy9KMjwN5O6pjk,34550 +jinja2/optimizer.py,sha256=tHkMwXxfZkbfA1KmLcqmBMSaz7RLIvvItrJcPoXTyD8,1650 +jinja2/parser.py,sha256=nHd-DFHbiygvfaPtm9rcQXJChZG7DPsWfiEsqfwKerY,39595 +jinja2/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +jinja2/runtime.py,sha256=5CmD5BjbEJxSiDNTFBeKCaq8qU4aYD2v6q2EluyExms,33476 +jinja2/sandbox.py,sha256=Y0xZeXQnH6EX5VjaV2YixESxoepnRbW_3UeQosaBU3M,14584 +jinja2/tests.py,sha256=Am5Z6Lmfr2XaH_npIfJJ8MdXtWsbLjMULZJulTAj30E,5905 +jinja2/utils.py,sha256=u9jXESxGn8ATZNVolwmkjUVu4SA-tLgV0W7PcSfPfdQ,23965 +jinja2/visitor.py,sha256=MH14C6yq24G_KVtWzjwaI7Wg14PCJIYlWW1kpkxYak0,3568 diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt new file mode 100644 index 00000000..7b9666c8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[babel.extractors] +jinja2 = jinja2.ext:babel_extract[i18n] diff --git a/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt new file mode 100644 index 00000000..7f7afbf3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Jinja2-3.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/INSTALLER b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/LICENSE.rst b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/LICENSE.rst new file mode 100644 index 00000000..9d227a0c --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2010 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/METADATA b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/METADATA new file mode 100644 index 00000000..4a349997 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/METADATA @@ -0,0 +1,98 @@ +Metadata-Version: 2.1 +Name: MarkupSafe +Version: 2.1.2 +Summary: Safely add untrusted strings to HTML/XML markup. +Home-page: https://palletsprojects.com/p/markupsafe/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://markupsafe.palletsprojects.com/ +Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/markupsafe/ +Project-URL: Issue Tracker, https://github.com/pallets/markupsafe/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst + +MarkupSafe +========== + +MarkupSafe implements a text object that escapes characters so it is +safe to use in HTML and XML. Characters that have special meanings are +replaced so that they display as the actual characters. This mitigates +injection attacks, meaning untrusted user input can safely be displayed +on a page. + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U MarkupSafe + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +Examples +-------- + +.. code-block:: pycon + + >>> from markupsafe import Markup, escape + + >>> # escape replaces special characters and wraps in Markup + >>> escape("") + Markup('<script>alert(document.cookie);</script>') + + >>> # wrap in Markup to mark text "safe" and prevent escaping + >>> Markup("Hello") + Markup('hello') + + >>> escape(Markup("Hello")) + Markup('hello') + + >>> # Markup is a str subclass + >>> # methods and operators escape their arguments + >>> template = Markup("Hello {name}") + >>> template.format(name='"World"') + Markup('Hello "World"') + + +Donate +------ + +The Pallets organization develops and supports MarkupSafe and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://markupsafe.palletsprojects.com/ +- Changes: https://markupsafe.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/MarkupSafe/ +- Source Code: https://github.com/pallets/markupsafe/ +- Issue Tracker: https://github.com/pallets/markupsafe/issues/ +- Website: https://palletsprojects.com/p/markupsafe/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/RECORD b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/RECORD new file mode 100644 index 00000000..4a3ea89b --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/RECORD @@ -0,0 +1,14 @@ +MarkupSafe-2.1.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +MarkupSafe-2.1.2.dist-info/LICENSE.rst,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475 +MarkupSafe-2.1.2.dist-info/METADATA,sha256=jPw4iOiZg6adxZ5bdvjZapeNmPMINMGG2q2v2rI4SqA,3222 +MarkupSafe-2.1.2.dist-info/RECORD,, +MarkupSafe-2.1.2.dist-info/WHEEL,sha256=85XxqUmZLCpAUbyN5ViL3rgA5Dw0b1knnC4gtrrtDjE,111 +MarkupSafe-2.1.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=LtjnhQ6AHmAgHl37cev2oQBXjr4xOF-QhdXgsCAL3-0,9306 +markupsafe/__pycache__/__init__.cpython-310.pyc,, +markupsafe/__pycache__/_native.cpython-310.pyc,, +markupsafe/_native.py,sha256=GR86Qvo_GcgKmKreA1WmYN9ud17OFwkww8E-fiW-57s,1713 +markupsafe/_speedups.c,sha256=X2XvQVtIdcK4Usz70BvkzoOfjTCmQlDkkjYSn-swE0g,7083 +markupsafe/_speedups.cpython-310-darwin.so,sha256=zX-PxY7pi-BsVqFS5Hs6h6xJazXEiW3oye3IJzYwHkk,35160 +markupsafe/_speedups.pyi,sha256=vfMCsOgbAXRNLUXkyuyonG8uEWKYU4PDqNuMaDELAYw,229 +markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/WHEEL b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/WHEEL new file mode 100644 index 00000000..b019ad0f --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.38.4) +Root-Is-Purelib: false +Tag: cp310-cp310-macosx_10_9_x86_64 + diff --git a/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/top_level.txt b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/top_level.txt new file mode 100644 index 00000000..75bf7292 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/MarkupSafe-2.1.2.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/INSTALLER b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/LICENSE.rst b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/LICENSE.rst new file mode 100644 index 00000000..c37cae49 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2007 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/METADATA b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/METADATA new file mode 100644 index 00000000..647bfc80 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/METADATA @@ -0,0 +1,126 @@ +Metadata-Version: 2.1 +Name: Werkzeug +Version: 2.2.3 +Summary: The comprehensive WSGI web application library. +Home-page: https://palletsprojects.com/p/werkzeug/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://werkzeug.palletsprojects.com/ +Project-URL: Changes, https://werkzeug.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/werkzeug/ +Project-URL: Issue Tracker, https://github.com/pallets/werkzeug/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware +Classifier: Topic :: Software Development :: Libraries :: Application Frameworks +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: MarkupSafe (>=2.1.1) +Provides-Extra: watchdog +Requires-Dist: watchdog ; extra == 'watchdog' + +Werkzeug +======== + +*werkzeug* German noun: "tool". Etymology: *werk* ("work"), *zeug* ("stuff") + +Werkzeug is a comprehensive `WSGI`_ web application library. It began as +a simple collection of various utilities for WSGI applications and has +become one of the most advanced WSGI utility libraries. + +It includes: + +- An interactive debugger that allows inspecting stack traces and + source code in the browser with an interactive interpreter for any + frame in the stack. +- A full-featured request object with objects to interact with + headers, query args, form data, files, and cookies. +- A response object that can wrap other WSGI applications and handle + streaming data. +- A routing system for matching URLs to endpoints and generating URLs + for endpoints, with an extensible system for capturing variables + from URLs. +- HTTP utilities to handle entity tags, cache control, dates, user + agents, cookies, files, and more. +- A threaded WSGI server for use while developing applications + locally. +- A test client for simulating HTTP requests during testing without + requiring running a server. + +Werkzeug doesn't enforce any dependencies. It is up to the developer to +choose a template engine, database adapter, and even how to handle +requests. It can be used to build all sorts of end user applications +such as blogs, wikis, or bulletin boards. + +`Flask`_ wraps Werkzeug, using it to handle the details of WSGI while +providing more structure and patterns for defining powerful +applications. + +.. _WSGI: https://wsgi.readthedocs.io/en/latest/ +.. _Flask: https://www.palletsprojects.com/p/flask/ + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + pip install -U Werkzeug + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + from werkzeug.wrappers import Request, Response + + @Request.application + def application(request): + return Response('Hello, World!') + + if __name__ == '__main__': + from werkzeug.serving import run_simple + run_simple('localhost', 4000, application) + + +Donate +------ + +The Pallets organization develops and supports Werkzeug and other +popular packages. In order to grow the community of contributors and +users, and allow the maintainers to devote more time to the projects, +`please donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://werkzeug.palletsprojects.com/ +- Changes: https://werkzeug.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/Werkzeug/ +- Source Code: https://github.com/pallets/werkzeug/ +- Issue Tracker: https://github.com/pallets/werkzeug/issues/ +- Website: https://palletsprojects.com/p/werkzeug/ +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/RECORD b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/RECORD new file mode 100644 index 00000000..19ecb6d6 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/RECORD @@ -0,0 +1,98 @@ +Werkzeug-2.2.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +Werkzeug-2.2.3.dist-info/LICENSE.rst,sha256=O0nc7kEF6ze6wQ-vG-JgQI_oXSUrjp3y4JefweCUQ3s,1475 +Werkzeug-2.2.3.dist-info/METADATA,sha256=TIyameVEp5p52N9E1mTWWabY6g1sB0Dm25vznZQeXPQ,4416 +Werkzeug-2.2.3.dist-info/RECORD,, +Werkzeug-2.2.3.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92 +Werkzeug-2.2.3.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 +werkzeug/__init__.py,sha256=Hr0lQweC21HXPVBemSpBJUIzrbq2mn8h70J1h30QcqY,188 +werkzeug/__pycache__/__init__.cpython-310.pyc,, +werkzeug/__pycache__/_internal.cpython-310.pyc,, +werkzeug/__pycache__/_reloader.cpython-310.pyc,, +werkzeug/__pycache__/datastructures.cpython-310.pyc,, +werkzeug/__pycache__/exceptions.cpython-310.pyc,, +werkzeug/__pycache__/formparser.cpython-310.pyc,, +werkzeug/__pycache__/http.cpython-310.pyc,, +werkzeug/__pycache__/local.cpython-310.pyc,, +werkzeug/__pycache__/security.cpython-310.pyc,, +werkzeug/__pycache__/serving.cpython-310.pyc,, +werkzeug/__pycache__/test.cpython-310.pyc,, +werkzeug/__pycache__/testapp.cpython-310.pyc,, +werkzeug/__pycache__/urls.cpython-310.pyc,, +werkzeug/__pycache__/user_agent.cpython-310.pyc,, +werkzeug/__pycache__/utils.cpython-310.pyc,, +werkzeug/__pycache__/wsgi.cpython-310.pyc,, +werkzeug/_internal.py,sha256=4lwshe63pFlCo0h2IMcmvhbugA50QXQvfLD5VoY5c4Q,16271 +werkzeug/_reloader.py,sha256=hiP0z4bi6p_8UIJOtq7K0BV2dqCik5yztWLsDXeI_WE,14285 +werkzeug/datastructures.py,sha256=v2WYfs1rb1OuQgXyLripHQFwgodrfTNCd5P5f8n3ueA,97081 +werkzeug/datastructures.pyi,sha256=HRzDLc7A6qnwluhNqn6AT76CsLZIkAbVVqxn0AbfV-s,34506 +werkzeug/debug/__init__.py,sha256=wfJ2OmljsO5C0e0sXJpTUiG6bwGU6uHtFDDDMfJfQJk,18877 +werkzeug/debug/__pycache__/__init__.cpython-310.pyc,, +werkzeug/debug/__pycache__/console.cpython-310.pyc,, +werkzeug/debug/__pycache__/repr.cpython-310.pyc,, +werkzeug/debug/__pycache__/tbtools.cpython-310.pyc,, +werkzeug/debug/console.py,sha256=dechqiCtHfs0AQZWZofUC1S97tCuvwDgT0gdha5KwWM,6208 +werkzeug/debug/repr.py,sha256=vF3TLnYBohYr8V6Gz13PTJspQs42uv3gUJSzSbmHJBo,9472 +werkzeug/debug/shared/ICON_LICENSE.md,sha256=DhA6Y1gUl5Jwfg0NFN9Rj4VWITt8tUx0IvdGf0ux9-s,222 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/debugger.js,sha256=tg42SZs1SVmYWZ-_Fj5ELK5-FLHnGNQrei0K2By8Bw8,10521 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +werkzeug/debug/shared/style.css,sha256=-xSxzUEZGw_IqlDR5iZxitNl8LQUjBM-_Y4UAvXVH8g,6078 +werkzeug/debug/tbtools.py,sha256=6iohJovtBSFRAcgX7_aRY4r3e19PLj3FavYB3RM4CmA,13263 +werkzeug/exceptions.py,sha256=8-KOXguQkOLoBUdN-7x_WyHT92TcAmjTWNwG4t8QYIg,26527 +werkzeug/formparser.py,sha256=DBRbbAnzspYUBzgfxPaZC7MjGAK_m5QTvdWoyvrhw4o,16516 +werkzeug/http.py,sha256=NqJjYCt8tKn2XOEKPApq4L3q8zb8YFq3GFOe5gsonI4,42776 +werkzeug/local.py,sha256=v-HEqr4bLpLHl4upCj97MOfUyCjW10Tp6mcNaFRFyew,22288 +werkzeug/middleware/__init__.py,sha256=qfqgdT5npwG9ses3-FXQJf3aB95JYP1zchetH_T3PUw,500 +werkzeug/middleware/__pycache__/__init__.cpython-310.pyc,, +werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc,, +werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc,, +werkzeug/middleware/__pycache__/lint.cpython-310.pyc,, +werkzeug/middleware/__pycache__/profiler.cpython-310.pyc,, +werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc,, +werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc,, +werkzeug/middleware/dispatcher.py,sha256=Fh_w-KyWnTSYF-Lfv5dimQ7THSS7afPAZMmvc4zF1gg,2580 +werkzeug/middleware/http_proxy.py,sha256=HE8VyhS7CR-E1O6_9b68huv8FLgGGR1DLYqkS3Xcp3Q,7558 +werkzeug/middleware/lint.py,sha256=1w_UVKkAwq5wjjtCcDCDZwhAhWzPSZ0aDyUmbjAEeXw,13952 +werkzeug/middleware/profiler.py,sha256=7pWYDYPC774S0-HYLkG3Uge58PGUMX7tWp_Cor3etvo,4883 +werkzeug/middleware/proxy_fix.py,sha256=l7LC_LDu0Yd4SvUxS5SFigAJMzcIOGm6LNKl9IXJBSU,6974 +werkzeug/middleware/shared_data.py,sha256=fXjrEkuqxUVLG1DLrOdQLc96QQdjftCBZ1oM5oK89h4,9528 +werkzeug/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/routing/__init__.py,sha256=HpvahY7WwkLdV4Cq3Bsc3GrqNon4u6t8-vhbb9E5o00,4819 +werkzeug/routing/__pycache__/__init__.cpython-310.pyc,, +werkzeug/routing/__pycache__/converters.cpython-310.pyc,, +werkzeug/routing/__pycache__/exceptions.cpython-310.pyc,, +werkzeug/routing/__pycache__/map.cpython-310.pyc,, +werkzeug/routing/__pycache__/matcher.cpython-310.pyc,, +werkzeug/routing/__pycache__/rules.cpython-310.pyc,, +werkzeug/routing/converters.py,sha256=05bkekg64vLC6mqqK4ddBh589WH9yBsjtW8IJhdUBvw,6968 +werkzeug/routing/exceptions.py,sha256=RklUDL9ajOv2fTcRNj4pb18Bs4Y-GKk4rIeTSfsqkks,4737 +werkzeug/routing/map.py,sha256=XN4ZjzEF1SfMxtdov89SDE-1_U78KVnnobTfnHzqbmE,36757 +werkzeug/routing/matcher.py,sha256=6VvQYCCOjyj1JKUZKuAiVA_U1nXtvvJ70pSbBUdL_1k,7509 +werkzeug/routing/rules.py,sha256=3YsPpI9ZGcNmFiV2Go2Td1DvZ9ZdaMMnvGP1o17aMfc,31836 +werkzeug/sansio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +werkzeug/sansio/__pycache__/__init__.cpython-310.pyc,, +werkzeug/sansio/__pycache__/http.cpython-310.pyc,, +werkzeug/sansio/__pycache__/multipart.cpython-310.pyc,, +werkzeug/sansio/__pycache__/request.cpython-310.pyc,, +werkzeug/sansio/__pycache__/response.cpython-310.pyc,, +werkzeug/sansio/__pycache__/utils.cpython-310.pyc,, +werkzeug/sansio/http.py,sha256=k3nREBfU-r8fXCfSTKQenys25q9bzUOvdY-OVGrqztA,5107 +werkzeug/sansio/multipart.py,sha256=vMZ85cvLD55clUTcTin2DtBv2GQRGh0_fExklnXKHoI,10055 +werkzeug/sansio/request.py,sha256=SiGcx2cz-l81TlCCrKrT2fePqC64hN8fSg5Ig6J6vRs,20175 +werkzeug/sansio/response.py,sha256=UTl-teQDDjovrZMkjj3ZQsHw-JtiFak5JfKEk1_vBYU,26026 +werkzeug/sansio/utils.py,sha256=EjbqdHdT-JZWgjUQaaWSgBUIRprXUkrsMQQqJlJHpVU,4847 +werkzeug/security.py,sha256=7TVI0L62emBHAh-1RHB_KlwGYcE08pPCyU674Ho4aNE,4653 +werkzeug/serving.py,sha256=XCiHFbMCFCgecKycgajhF4rFsGoemeN0xW1eTQqNt-g,37558 +werkzeug/test.py,sha256=uMahfM81RqEN3d3Sp4SkN36Pi8oZpV6dTgFY0cW1_2c,48126 +werkzeug/testapp.py,sha256=RJhT_2JweNiMKe304N3bF1zaIeMpRx-CIMERdeydfTY,9404 +werkzeug/urls.py,sha256=Q9Si-eVh7yxk3rwkzrwGRm146FXVXgg9lBP3k0HUfVM,36600 +werkzeug/user_agent.py,sha256=WclZhpvgLurMF45hsioSbS75H1Zb4iMQGKN3_yZ2oKo,1420 +werkzeug/utils.py,sha256=BDX5_7OCMVgl-ib84bCEdBG5MVvrxaSlfdg7Cxh4ND0,25174 +werkzeug/wrappers/__init__.py,sha256=kGyK7rOud3qCxll_jFyW15YarJhj1xtdf3ocx9ZheB8,120 +werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc,, +werkzeug/wrappers/__pycache__/request.cpython-310.pyc,, +werkzeug/wrappers/__pycache__/response.cpython-310.pyc,, +werkzeug/wrappers/request.py,sha256=XmpTThXytTdznbPJnIsfdoIAvdi-THzTJQ9DsvARhn4,24026 +werkzeug/wrappers/response.py,sha256=ii1IaN2eUfoB-tBqbn_46fCB_SVVL8Fu4qd6cu0AlEY,34963 +werkzeug/wsgi.py,sha256=-VKI2iwCgLb-VToIZeBpdutkTETxy9HkIwgcFC5orkU,36060 diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/WHEEL b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/WHEEL new file mode 100644 index 00000000..57e3d840 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.38.4) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/top_level.txt b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/top_level.txt new file mode 100644 index 00000000..6fe8da84 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/Werkzeug-2.2.3.dist-info/top_level.txt @@ -0,0 +1 @@ +werkzeug diff --git a/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__init__.py b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__init__.py new file mode 100644 index 00000000..f987a536 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__init__.py @@ -0,0 +1,222 @@ +# don't import any costly modules +import sys +import os + + +is_pypy = '__pypy__' in sys.builtin_module_names + + +def warn_distutils_present(): + if 'distutils' not in sys.modules: + return + if is_pypy and sys.version_info < (3, 7): + # PyPy for 3.6 unconditionally imports distutils, so bypass the warning + # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 + return + import warnings + + warnings.warn( + "Distutils was imported before Setuptools, but importing Setuptools " + "also replaces the `distutils` module in `sys.modules`. This may lead " + "to undesirable behaviors or errors. To avoid these issues, avoid " + "using distutils directly, ensure that setuptools is installed in the " + "traditional way (e.g. not an editable install), and/or make sure " + "that setuptools is always imported before distutils." + ) + + +def clear_distutils(): + if 'distutils' not in sys.modules: + return + import warnings + + warnings.warn("Setuptools is replacing distutils.") + mods = [ + name + for name in sys.modules + if name == "distutils" or name.startswith("distutils.") + ] + for name in mods: + del sys.modules[name] + + +def enabled(): + """ + Allow selection of distutils by environment variable. + """ + which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local') + return which == 'local' + + +def ensure_local_distutils(): + import importlib + + clear_distutils() + + # With the DistutilsMetaFinder in place, + # perform an import to cause distutils to be + # loaded from setuptools._distutils. Ref #2906. + with shim(): + importlib.import_module('distutils') + + # check that submodules load as expected + core = importlib.import_module('distutils.core') + assert '_distutils' in core.__file__, core.__file__ + assert 'setuptools._distutils.log' not in sys.modules + + +def do_override(): + """ + Ensure that the local copy of distutils is preferred over stdlib. + + See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 + for more motivation. + """ + if enabled(): + warn_distutils_present() + ensure_local_distutils() + + +class _TrivialRe: + def __init__(self, *patterns): + self._patterns = patterns + + def match(self, string): + return all(pat in string for pat in self._patterns) + + +class DistutilsMetaFinder: + def find_spec(self, fullname, path, target=None): + # optimization: only consider top level modules and those + # found in the CPython test suite. + if path is not None and not fullname.startswith('test.'): + return + + method_name = 'spec_for_{fullname}'.format(**locals()) + method = getattr(self, method_name, lambda: None) + return method() + + def spec_for_distutils(self): + if self.is_cpython(): + return + + import importlib + import importlib.abc + import importlib.util + + try: + mod = importlib.import_module('setuptools._distutils') + except Exception: + # There are a couple of cases where setuptools._distutils + # may not be present: + # - An older Setuptools without a local distutils is + # taking precedence. Ref #2957. + # - Path manipulation during sitecustomize removes + # setuptools from the path but only after the hook + # has been loaded. Ref #2980. + # In either case, fall back to stdlib behavior. + return + + class DistutilsLoader(importlib.abc.Loader): + def create_module(self, spec): + mod.__name__ = 'distutils' + return mod + + def exec_module(self, module): + pass + + return importlib.util.spec_from_loader( + 'distutils', DistutilsLoader(), origin=mod.__file__ + ) + + @staticmethod + def is_cpython(): + """ + Suppress supplying distutils for CPython (build and tests). + Ref #2965 and #3007. + """ + return os.path.isfile('pybuilddir.txt') + + def spec_for_pip(self): + """ + Ensure stdlib distutils when running under pip. + See pypa/pip#8761 for rationale. + """ + if self.pip_imported_during_build(): + return + clear_distutils() + self.spec_for_distutils = lambda: None + + @classmethod + def pip_imported_during_build(cls): + """ + Detect if pip is being imported in a build script. Ref #2355. + """ + import traceback + + return any( + cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None) + ) + + @staticmethod + def frame_file_is_setup(frame): + """ + Return True if the indicated frame suggests a setup.py file. + """ + # some frames may not have __file__ (#2940) + return frame.f_globals.get('__file__', '').endswith('setup.py') + + def spec_for_sensitive_tests(self): + """ + Ensure stdlib distutils when running select tests under CPython. + + python/cpython#91169 + """ + clear_distutils() + self.spec_for_distutils = lambda: None + + sensitive_tests = ( + [ + 'test.test_distutils', + 'test.test_peg_generator', + 'test.test_importlib', + ] + if sys.version_info < (3, 10) + else [ + 'test.test_distutils', + ] + ) + + +for name in DistutilsMetaFinder.sensitive_tests: + setattr( + DistutilsMetaFinder, + f'spec_for_{name}', + DistutilsMetaFinder.spec_for_sensitive_tests, + ) + + +DISTUTILS_FINDER = DistutilsMetaFinder() + + +def add_shim(): + DISTUTILS_FINDER in sys.meta_path or insert_shim() + + +class shim: + def __enter__(self): + insert_shim() + + def __exit__(self, exc, value, tb): + remove_shim() + + +def insert_shim(): + sys.meta_path.insert(0, DISTUTILS_FINDER) + + +def remove_shim(): + try: + sys.meta_path.remove(DISTUTILS_FINDER) + except ValueError: + pass diff --git a/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..cfd42a0c Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc new file mode 100644 index 00000000..aa811667 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/override.py b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/override.py new file mode 100644 index 00000000..2cc433a4 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/_distutils_hack/override.py @@ -0,0 +1 @@ +__import__('_distutils_hack').do_override() diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst new file mode 100644 index 00000000..d12a8491 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/LICENSE.rst @@ -0,0 +1,28 @@ +Copyright 2014 Pallets + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA new file mode 100644 index 00000000..8e5dc1e0 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/METADATA @@ -0,0 +1,111 @@ +Metadata-Version: 2.1 +Name: click +Version: 8.1.3 +Summary: Composable command line interface toolkit +Home-page: https://palletsprojects.com/p/click/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +Maintainer: Pallets +Maintainer-email: contact@palletsprojects.com +License: BSD-3-Clause +Project-URL: Donate, https://palletsprojects.com/donate +Project-URL: Documentation, https://click.palletsprojects.com/ +Project-URL: Changes, https://click.palletsprojects.com/changes/ +Project-URL: Source Code, https://github.com/pallets/click/ +Project-URL: Issue Tracker, https://github.com/pallets/click/issues/ +Project-URL: Twitter, https://twitter.com/PalletsTeam +Project-URL: Chat, https://discord.gg/pallets +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Requires-Python: >=3.7 +Description-Content-Type: text/x-rst +License-File: LICENSE.rst +Requires-Dist: colorama ; platform_system == "Windows" +Requires-Dist: importlib-metadata ; python_version < "3.8" + +\$ click\_ +========== + +Click is a Python package for creating beautiful command line interfaces +in a composable way with as little code as necessary. It's the "Command +Line Interface Creation Kit". It's highly configurable but comes with +sensible defaults out of the box. + +It aims to make the process of writing command line tools quick and fun +while also preventing any frustration caused by the inability to +implement an intended CLI API. + +Click in three points: + +- Arbitrary nesting of commands +- Automatic help page generation +- Supports lazy loading of subcommands at runtime + + +Installing +---------- + +Install and update using `pip`_: + +.. code-block:: text + + $ pip install -U click + +.. _pip: https://pip.pypa.io/en/stable/getting-started/ + + +A Simple Example +---------------- + +.. code-block:: python + + import click + + @click.command() + @click.option("--count", default=1, help="Number of greetings.") + @click.option("--name", prompt="Your name", help="The person to greet.") + def hello(count, name): + """Simple program that greets NAME for a total of COUNT times.""" + for _ in range(count): + click.echo(f"Hello, {name}!") + + if __name__ == '__main__': + hello() + +.. code-block:: text + + $ python hello.py --count=3 + Your name: Click + Hello, Click! + Hello, Click! + Hello, Click! + + +Donate +------ + +The Pallets organization develops and supports Click and other popular +packages. In order to grow the community of contributors and users, and +allow the maintainers to devote more time to the projects, `please +donate today`_. + +.. _please donate today: https://palletsprojects.com/donate + + +Links +----- + +- Documentation: https://click.palletsprojects.com/ +- Changes: https://click.palletsprojects.com/changes/ +- PyPI Releases: https://pypi.org/project/click/ +- Source Code: https://github.com/pallets/click +- Issue Tracker: https://github.com/pallets/click/issues +- Website: https://palletsprojects.com/p/click +- Twitter: https://twitter.com/PalletsTeam +- Chat: https://discord.gg/pallets + + diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD new file mode 100644 index 00000000..67ff862a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/RECORD @@ -0,0 +1,39 @@ +click-8.1.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +click-8.1.3.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 +click-8.1.3.dist-info/METADATA,sha256=tFJIX5lOjx7c5LjZbdTPFVDJSgyv9F74XY0XCPp_gnc,3247 +click-8.1.3.dist-info/RECORD,, +click-8.1.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +click-8.1.3.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6 +click/__init__.py,sha256=rQBLutqg-z6m8nOzivIfigDn_emijB_dKv9BZ2FNi5s,3138 +click/__pycache__/__init__.cpython-310.pyc,, +click/__pycache__/_compat.cpython-310.pyc,, +click/__pycache__/_termui_impl.cpython-310.pyc,, +click/__pycache__/_textwrap.cpython-310.pyc,, +click/__pycache__/_winconsole.cpython-310.pyc,, +click/__pycache__/core.cpython-310.pyc,, +click/__pycache__/decorators.cpython-310.pyc,, +click/__pycache__/exceptions.cpython-310.pyc,, +click/__pycache__/formatting.cpython-310.pyc,, +click/__pycache__/globals.cpython-310.pyc,, +click/__pycache__/parser.cpython-310.pyc,, +click/__pycache__/shell_completion.cpython-310.pyc,, +click/__pycache__/termui.cpython-310.pyc,, +click/__pycache__/testing.cpython-310.pyc,, +click/__pycache__/types.cpython-310.pyc,, +click/__pycache__/utils.cpython-310.pyc,, +click/_compat.py,sha256=JIHLYs7Jzz4KT9t-ds4o4jBzLjnwCiJQKqur-5iwCKI,18810 +click/_termui_impl.py,sha256=qK6Cfy4mRFxvxE8dya8RBhLpSC8HjF-lvBc6aNrPdwg,23451 +click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 +click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 +click/core.py,sha256=mz87bYEKzIoNYEa56BFAiOJnvt1Y0L-i7wD4_ZecieE,112782 +click/decorators.py,sha256=yo3zvzgUm5q7h5CXjyV6q3h_PJAiUaem178zXwdWUFI,16350 +click/exceptions.py,sha256=7gDaLGuFZBeCNwY9ERMsF2-Z3R9Fvq09Zc6IZSKjseo,9167 +click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 +click/globals.py,sha256=TP-qM88STzc7f127h35TD_v920FgfOD2EwzqA0oE8XU,1961 +click/parser.py,sha256=cAEt1uQR8gq3-S9ysqbVU-fdAZNvilxw4ReJ_T1OQMk,19044 +click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +click/shell_completion.py,sha256=qOp_BeC9esEOSZKyu5G7RIxEUaLsXUX-mTb7hB1r4QY,18018 +click/termui.py,sha256=ACBQVOvFCTSqtD5VREeCAdRtlHd-Imla-Lte4wSfMjA,28355 +click/testing.py,sha256=ptpMYgRY7dVfE3UDgkgwayu9ePw98sQI3D7zZXiCpj4,16063 +click/types.py,sha256=rEb1aZSQKq3ciCMmjpG2Uva9vk498XRL7ThrcK2GRss,35805 +click/utils.py,sha256=33D6E7poH_nrKB-xr-UyDEXnxOcCiQqxuRLtrqeVv6o,18682 diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL new file mode 100644 index 00000000..becc9a66 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt new file mode 100644 index 00000000..dca9a909 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click-8.1.3.dist-info/top_level.txt @@ -0,0 +1 @@ +click diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__init__.py b/flask-server/venv/lib/python3.10/site-packages/click/__init__.py new file mode 100644 index 00000000..e3ef423b --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/__init__.py @@ -0,0 +1,73 @@ +""" +Click is a simple Python module inspired by the stdlib optparse to make +writing command line scripts fun. Unlike other modules, it's based +around a simple API that does not come with too much magic and is +composable. +""" +from .core import Argument as Argument +from .core import BaseCommand as BaseCommand +from .core import Command as Command +from .core import CommandCollection as CommandCollection +from .core import Context as Context +from .core import Group as Group +from .core import MultiCommand as MultiCommand +from .core import Option as Option +from .core import Parameter as Parameter +from .decorators import argument as argument +from .decorators import command as command +from .decorators import confirmation_option as confirmation_option +from .decorators import group as group +from .decorators import help_option as help_option +from .decorators import make_pass_decorator as make_pass_decorator +from .decorators import option as option +from .decorators import pass_context as pass_context +from .decorators import pass_obj as pass_obj +from .decorators import password_option as password_option +from .decorators import version_option as version_option +from .exceptions import Abort as Abort +from .exceptions import BadArgumentUsage as BadArgumentUsage +from .exceptions import BadOptionUsage as BadOptionUsage +from .exceptions import BadParameter as BadParameter +from .exceptions import ClickException as ClickException +from .exceptions import FileError as FileError +from .exceptions import MissingParameter as MissingParameter +from .exceptions import NoSuchOption as NoSuchOption +from .exceptions import UsageError as UsageError +from .formatting import HelpFormatter as HelpFormatter +from .formatting import wrap_text as wrap_text +from .globals import get_current_context as get_current_context +from .parser import OptionParser as OptionParser +from .termui import clear as clear +from .termui import confirm as confirm +from .termui import echo_via_pager as echo_via_pager +from .termui import edit as edit +from .termui import getchar as getchar +from .termui import launch as launch +from .termui import pause as pause +from .termui import progressbar as progressbar +from .termui import prompt as prompt +from .termui import secho as secho +from .termui import style as style +from .termui import unstyle as unstyle +from .types import BOOL as BOOL +from .types import Choice as Choice +from .types import DateTime as DateTime +from .types import File as File +from .types import FLOAT as FLOAT +from .types import FloatRange as FloatRange +from .types import INT as INT +from .types import IntRange as IntRange +from .types import ParamType as ParamType +from .types import Path as Path +from .types import STRING as STRING +from .types import Tuple as Tuple +from .types import UNPROCESSED as UNPROCESSED +from .types import UUID as UUID +from .utils import echo as echo +from .utils import format_filename as format_filename +from .utils import get_app_dir as get_app_dir +from .utils import get_binary_stream as get_binary_stream +from .utils import get_text_stream as get_text_stream +from .utils import open_file as open_file + +__version__ = "8.1.3" diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..4d174e40 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc new file mode 100644 index 00000000..cef81002 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_compat.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc new file mode 100644 index 00000000..1e8659a7 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc new file mode 100644 index 00000000..442a5c03 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_textwrap.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc new file mode 100644 index 00000000..3882bb86 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/_winconsole.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc new file mode 100644 index 00000000..777f1853 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/core.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc new file mode 100644 index 00000000..aea18c8e Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/decorators.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc new file mode 100644 index 00000000..ea27cbcb Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/exceptions.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc new file mode 100644 index 00000000..dd21f8ea Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/formatting.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc new file mode 100644 index 00000000..c8c26a17 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/globals.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc new file mode 100644 index 00000000..caebe9e4 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/parser.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/shell_completion.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/shell_completion.cpython-310.pyc new file mode 100644 index 00000000..883d881c Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/shell_completion.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc new file mode 100644 index 00000000..40331016 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/termui.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc new file mode 100644 index 00000000..6a73cc86 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/testing.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc new file mode 100644 index 00000000..418f4099 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/types.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/utils.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/utils.cpython-310.pyc new file mode 100644 index 00000000..14040c3b Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/click/__pycache__/utils.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/click/_compat.py b/flask-server/venv/lib/python3.10/site-packages/click/_compat.py new file mode 100644 index 00000000..766d286b --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/_compat.py @@ -0,0 +1,626 @@ +import codecs +import io +import os +import re +import sys +import typing as t +from weakref import WeakKeyDictionary + +CYGWIN = sys.platform.startswith("cygwin") +MSYS2 = sys.platform.startswith("win") and ("GCC" in sys.version) +# Determine local App Engine environment, per Google's own suggestion +APP_ENGINE = "APPENGINE_RUNTIME" in os.environ and "Development/" in os.environ.get( + "SERVER_SOFTWARE", "" +) +WIN = sys.platform.startswith("win") and not APP_ENGINE and not MSYS2 +auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None +_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") + + +def get_filesystem_encoding() -> str: + return sys.getfilesystemencoding() or sys.getdefaultencoding() + + +def _make_text_stream( + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if encoding is None: + encoding = get_best_encoding(stream) + if errors is None: + errors = "replace" + return _NonClosingTextIOWrapper( + stream, + encoding, + errors, + line_buffering=True, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def is_ascii_encoding(encoding: str) -> bool: + """Checks if a given encoding is ascii.""" + try: + return codecs.lookup(encoding).name == "ascii" + except LookupError: + return False + + +def get_best_encoding(stream: t.IO) -> str: + """Returns the default stream encoding if not found.""" + rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() + if is_ascii_encoding(rv): + return "utf-8" + return rv + + +class _NonClosingTextIOWrapper(io.TextIOWrapper): + def __init__( + self, + stream: t.BinaryIO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, + force_writable: bool = False, + **extra: t.Any, + ) -> None: + self._stream = stream = t.cast( + t.BinaryIO, _FixupStream(stream, force_readable, force_writable) + ) + super().__init__(stream, encoding, errors, **extra) + + def __del__(self) -> None: + try: + self.detach() + except Exception: + pass + + def isatty(self) -> bool: + # https://bitbucket.org/pypy/pypy/issue/1803 + return self._stream.isatty() + + +class _FixupStream: + """The new io interface needs more from streams than streams + traditionally implement. As such, this fix-up code is necessary in + some circumstances. + + The forcing of readable and writable flags are there because some tools + put badly patched objects on sys (one such offender are certain version + of jupyter notebook). + """ + + def __init__( + self, + stream: t.BinaryIO, + force_readable: bool = False, + force_writable: bool = False, + ): + self._stream = stream + self._force_readable = force_readable + self._force_writable = force_writable + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._stream, name) + + def read1(self, size: int) -> bytes: + f = getattr(self._stream, "read1", None) + + if f is not None: + return t.cast(bytes, f(size)) + + return self._stream.read(size) + + def readable(self) -> bool: + if self._force_readable: + return True + x = getattr(self._stream, "readable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.read(0) + except Exception: + return False + return True + + def writable(self) -> bool: + if self._force_writable: + return True + x = getattr(self._stream, "writable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.write("") # type: ignore + except Exception: + try: + self._stream.write(b"") + except Exception: + return False + return True + + def seekable(self) -> bool: + x = getattr(self._stream, "seekable", None) + if x is not None: + return t.cast(bool, x()) + try: + self._stream.seek(self._stream.tell()) + except Exception: + return False + return True + + +def _is_binary_reader(stream: t.IO, default: bool = False) -> bool: + try: + return isinstance(stream.read(0), bytes) + except Exception: + return default + # This happens in some cases where the stream was already + # closed. In this case, we assume the default. + + +def _is_binary_writer(stream: t.IO, default: bool = False) -> bool: + try: + stream.write(b"") + except Exception: + try: + stream.write("") + return False + except Exception: + pass + return default + return True + + +def _find_binary_reader(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_reader(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_reader(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _find_binary_writer(stream: t.IO) -> t.Optional[t.BinaryIO]: + # We need to figure out if the given stream is already binary. + # This can happen because the official docs recommend detaching + # the streams to get binary streams. Some code might do this, so + # we need to deal with this case explicitly. + if _is_binary_writer(stream, False): + return t.cast(t.BinaryIO, stream) + + buf = getattr(stream, "buffer", None) + + # Same situation here; this time we assume that the buffer is + # actually binary in case it's closed. + if buf is not None and _is_binary_writer(buf, True): + return t.cast(t.BinaryIO, buf) + + return None + + +def _stream_is_misconfigured(stream: t.TextIO) -> bool: + """A stream is misconfigured if its encoding is ASCII.""" + # If the stream does not have an encoding set, we assume it's set + # to ASCII. This appears to happen in certain unittest + # environments. It's not quite clear what the correct behavior is + # but this at least will force Click to recover somehow. + return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") + + +def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: + """A stream attribute is compatible if it is equal to the + desired value or the desired value is unset and the attribute + has a value. + """ + stream_value = getattr(stream, attr, None) + return stream_value == value or (value is None and stream_value is not None) + + +def _is_compatible_text_stream( + stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> bool: + """Check if a stream's encoding and errors attributes are + compatible with the desired values. + """ + return _is_compat_stream_attr( + stream, "encoding", encoding + ) and _is_compat_stream_attr(stream, "errors", errors) + + +def _force_correct_text_stream( + text_stream: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + is_binary: t.Callable[[t.IO, bool], bool], + find_binary: t.Callable[[t.IO], t.Optional[t.BinaryIO]], + force_readable: bool = False, + force_writable: bool = False, +) -> t.TextIO: + if is_binary(text_stream, False): + binary_reader = t.cast(t.BinaryIO, text_stream) + else: + text_stream = t.cast(t.TextIO, text_stream) + # If the stream looks compatible, and won't default to a + # misconfigured ascii encoding, return it as-is. + if _is_compatible_text_stream(text_stream, encoding, errors) and not ( + encoding is None and _stream_is_misconfigured(text_stream) + ): + return text_stream + + # Otherwise, get the underlying binary reader. + possible_binary_reader = find_binary(text_stream) + + # If that's not possible, silently use the original reader + # and get mojibake instead of exceptions. + if possible_binary_reader is None: + return text_stream + + binary_reader = possible_binary_reader + + # Default errors to replace instead of strict in order to get + # something that works. + if errors is None: + errors = "replace" + + # Wrap the binary stream in a text stream with the correct + # encoding parameters. + return _make_text_stream( + binary_reader, + encoding, + errors, + force_readable=force_readable, + force_writable=force_writable, + ) + + +def _force_correct_text_reader( + text_reader: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_readable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_reader, + encoding, + errors, + _is_binary_reader, + _find_binary_reader, + force_readable=force_readable, + ) + + +def _force_correct_text_writer( + text_writer: t.IO, + encoding: t.Optional[str], + errors: t.Optional[str], + force_writable: bool = False, +) -> t.TextIO: + return _force_correct_text_stream( + text_writer, + encoding, + errors, + _is_binary_writer, + _find_binary_writer, + force_writable=force_writable, + ) + + +def get_binary_stdin() -> t.BinaryIO: + reader = _find_binary_reader(sys.stdin) + if reader is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdin.") + return reader + + +def get_binary_stdout() -> t.BinaryIO: + writer = _find_binary_writer(sys.stdout) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stdout.") + return writer + + +def get_binary_stderr() -> t.BinaryIO: + writer = _find_binary_writer(sys.stderr) + if writer is None: + raise RuntimeError("Was not able to determine binary stream for sys.stderr.") + return writer + + +def get_text_stdin( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdin, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) + + +def get_text_stdout( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stdout, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) + + +def get_text_stderr( + encoding: t.Optional[str] = None, errors: t.Optional[str] = None +) -> t.TextIO: + rv = _get_windows_console_stream(sys.stderr, encoding, errors) + if rv is not None: + return rv + return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) + + +def _wrap_io_open( + file: t.Union[str, os.PathLike, int], + mode: str, + encoding: t.Optional[str], + errors: t.Optional[str], +) -> t.IO: + """Handles not passing ``encoding`` and ``errors`` in binary mode.""" + if "b" in mode: + return open(file, mode) + + return open(file, mode, encoding=encoding, errors=errors) + + +def open_stream( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, +) -> t.Tuple[t.IO, bool]: + binary = "b" in mode + + # Standard streams first. These are simple because they ignore the + # atomic flag. Use fsdecode to handle Path("-"). + if os.fsdecode(filename) == "-": + if any(m in mode for m in ["w", "a", "x"]): + if binary: + return get_binary_stdout(), False + return get_text_stdout(encoding=encoding, errors=errors), False + if binary: + return get_binary_stdin(), False + return get_text_stdin(encoding=encoding, errors=errors), False + + # Non-atomic writes directly go out through the regular open functions. + if not atomic: + return _wrap_io_open(filename, mode, encoding, errors), True + + # Some usability stuff for atomic writes + if "a" in mode: + raise ValueError( + "Appending to an existing file is not supported, because that" + " would involve an expensive `copy`-operation to a temporary" + " file. Open the file in normal `w`-mode and copy explicitly" + " if that's what you're after." + ) + if "x" in mode: + raise ValueError("Use the `overwrite`-parameter instead.") + if "w" not in mode: + raise ValueError("Atomic writes only make sense with `w`-mode.") + + # Atomic writes are more complicated. They work by opening a file + # as a proxy in the same folder and then using the fdopen + # functionality to wrap it in a Python file. Then we wrap it in an + # atomic file that moves the file over on close. + import errno + import random + + try: + perm: t.Optional[int] = os.stat(filename).st_mode + except OSError: + perm = None + + flags = os.O_RDWR | os.O_CREAT | os.O_EXCL + + if binary: + flags |= getattr(os, "O_BINARY", 0) + + while True: + tmp_filename = os.path.join( + os.path.dirname(filename), + f".__atomic-write{random.randrange(1 << 32):08x}", + ) + try: + fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) + break + except OSError as e: + if e.errno == errno.EEXIST or ( + os.name == "nt" + and e.errno == errno.EACCES + and os.path.isdir(e.filename) + and os.access(e.filename, os.W_OK) + ): + continue + raise + + if perm is not None: + os.chmod(tmp_filename, perm) # in case perm includes bits in umask + + f = _wrap_io_open(fd, mode, encoding, errors) + af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) + return t.cast(t.IO, af), True + + +class _AtomicFile: + def __init__(self, f: t.IO, tmp_filename: str, real_filename: str) -> None: + self._f = f + self._tmp_filename = tmp_filename + self._real_filename = real_filename + self.closed = False + + @property + def name(self) -> str: + return self._real_filename + + def close(self, delete: bool = False) -> None: + if self.closed: + return + self._f.close() + os.replace(self._tmp_filename, self._real_filename) + self.closed = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._f, name) + + def __enter__(self) -> "_AtomicFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close(delete=exc_type is not None) + + def __repr__(self) -> str: + return repr(self._f) + + +def strip_ansi(value: str) -> str: + return _ansi_re.sub("", value) + + +def _is_jupyter_kernel_output(stream: t.IO) -> bool: + while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): + stream = stream._stream + + return stream.__class__.__module__.startswith("ipykernel.") + + +def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None +) -> bool: + if color is None: + if stream is None: + stream = sys.stdin + return not isatty(stream) and not _is_jupyter_kernel_output(stream) + return not color + + +# On Windows, wrap the output streams with colorama to support ANSI +# color codes. +# NOTE: double check is needed so mypy does not analyze this on Linux +if sys.platform.startswith("win") and WIN: + from ._winconsole import _get_windows_console_stream + + def _get_argv_encoding() -> str: + import locale + + return locale.getpreferredencoding() + + _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def auto_wrap_for_ansi( + stream: t.TextIO, color: t.Optional[bool] = None + ) -> t.TextIO: + """Support ANSI color and style codes on Windows by wrapping a + stream with colorama. + """ + try: + cached = _ansi_stream_wrappers.get(stream) + except Exception: + cached = None + + if cached is not None: + return cached + + import colorama + + strip = should_strip_ansi(stream, color) + ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) + rv = t.cast(t.TextIO, ansi_wrapper.stream) + _write = rv.write + + def _safe_write(s): + try: + return _write(s) + except BaseException: + ansi_wrapper.reset_all() + raise + + rv.write = _safe_write + + try: + _ansi_stream_wrappers[stream] = rv + except Exception: + pass + + return rv + +else: + + def _get_argv_encoding() -> str: + return getattr(sys.stdin, "encoding", None) or get_filesystem_encoding() + + def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] + ) -> t.Optional[t.TextIO]: + return None + + +def term_len(x: str) -> int: + return len(strip_ansi(x)) + + +def isatty(stream: t.IO) -> bool: + try: + return stream.isatty() + except Exception: + return False + + +def _make_cached_stream_func( + src_func: t.Callable[[], t.TextIO], wrapper_func: t.Callable[[], t.TextIO] +) -> t.Callable[[], t.TextIO]: + cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() + + def func() -> t.TextIO: + stream = src_func() + try: + rv = cache.get(stream) + except Exception: + rv = None + if rv is not None: + return rv + rv = wrapper_func() + try: + cache[stream] = rv + except Exception: + pass + return rv + + return func + + +_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) +_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) +_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) + + +binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { + "stdin": get_binary_stdin, + "stdout": get_binary_stdout, + "stderr": get_binary_stderr, +} + +text_streams: t.Mapping[ + str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] +] = { + "stdin": get_text_stdin, + "stdout": get_text_stdout, + "stderr": get_text_stderr, +} diff --git a/flask-server/venv/lib/python3.10/site-packages/click/_termui_impl.py b/flask-server/venv/lib/python3.10/site-packages/click/_termui_impl.py new file mode 100644 index 00000000..4b979bcc --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/_termui_impl.py @@ -0,0 +1,717 @@ +""" +This module contains implementations for the termui module. To keep the +import time of Click down, some infrequently used functionality is +placed in this module and only imported as needed. +""" +import contextlib +import math +import os +import sys +import time +import typing as t +from gettext import gettext as _ + +from ._compat import _default_text_stdout +from ._compat import CYGWIN +from ._compat import get_best_encoding +from ._compat import isatty +from ._compat import open_stream +from ._compat import strip_ansi +from ._compat import term_len +from ._compat import WIN +from .exceptions import ClickException +from .utils import echo + +V = t.TypeVar("V") + +if os.name == "nt": + BEFORE_BAR = "\r" + AFTER_BAR = "\n" +else: + BEFORE_BAR = "\r\033[?25l" + AFTER_BAR = "\033[?25h\n" + + +class ProgressBar(t.Generic[V]): + def __init__( + self, + iterable: t.Optional[t.Iterable[V]], + length: t.Optional[int] = None, + fill_char: str = "#", + empty_char: str = " ", + bar_template: str = "%(bar)s", + info_sep: str = " ", + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + label: t.Optional[str] = None, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, + width: int = 30, + ) -> None: + self.fill_char = fill_char + self.empty_char = empty_char + self.bar_template = bar_template + self.info_sep = info_sep + self.show_eta = show_eta + self.show_percent = show_percent + self.show_pos = show_pos + self.item_show_func = item_show_func + self.label = label or "" + if file is None: + file = _default_text_stdout() + self.file = file + self.color = color + self.update_min_steps = update_min_steps + self._completed_intervals = 0 + self.width = width + self.autowidth = width == 0 + + if length is None: + from operator import length_hint + + length = length_hint(iterable, -1) + + if length == -1: + length = None + if iterable is None: + if length is None: + raise TypeError("iterable or length is required") + iterable = t.cast(t.Iterable[V], range(length)) + self.iter = iter(iterable) + self.length = length + self.pos = 0 + self.avg: t.List[float] = [] + self.start = self.last_eta = time.time() + self.eta_known = False + self.finished = False + self.max_width: t.Optional[int] = None + self.entered = False + self.current_item: t.Optional[V] = None + self.is_hidden = not isatty(self.file) + self._last_line: t.Optional[str] = None + + def __enter__(self) -> "ProgressBar": + self.entered = True + self.render_progress() + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.render_finish() + + def __iter__(self) -> t.Iterator[V]: + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + self.render_progress() + return self.generator() + + def __next__(self) -> V: + # Iteration is defined in terms of a generator function, + # returned by iter(self); use that to define next(). This works + # because `self.iter` is an iterable consumed by that generator, + # so it is re-entry safe. Calling `next(self.generator())` + # twice works and does "what you want". + return next(iter(self)) + + def render_finish(self) -> None: + if self.is_hidden: + return + self.file.write(AFTER_BAR) + self.file.flush() + + @property + def pct(self) -> float: + if self.finished: + return 1.0 + return min(self.pos / (float(self.length or 1) or 1), 1.0) + + @property + def time_per_iteration(self) -> float: + if not self.avg: + return 0.0 + return sum(self.avg) / float(len(self.avg)) + + @property + def eta(self) -> float: + if self.length is not None and not self.finished: + return self.time_per_iteration * (self.length - self.pos) + return 0.0 + + def format_eta(self) -> str: + if self.eta_known: + t = int(self.eta) + seconds = t % 60 + t //= 60 + minutes = t % 60 + t //= 60 + hours = t % 24 + t //= 24 + if t > 0: + return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" + else: + return f"{hours:02}:{minutes:02}:{seconds:02}" + return "" + + def format_pos(self) -> str: + pos = str(self.pos) + if self.length is not None: + pos += f"/{self.length}" + return pos + + def format_pct(self) -> str: + return f"{int(self.pct * 100): 4}%"[1:] + + def format_bar(self) -> str: + if self.length is not None: + bar_length = int(self.pct * self.width) + bar = self.fill_char * bar_length + bar += self.empty_char * (self.width - bar_length) + elif self.finished: + bar = self.fill_char * self.width + else: + chars = list(self.empty_char * (self.width or 1)) + if self.time_per_iteration != 0: + chars[ + int( + (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) + * self.width + ) + ] = self.fill_char + bar = "".join(chars) + return bar + + def format_progress_line(self) -> str: + show_percent = self.show_percent + + info_bits = [] + if self.length is not None and show_percent is None: + show_percent = not self.show_pos + + if self.show_pos: + info_bits.append(self.format_pos()) + if show_percent: + info_bits.append(self.format_pct()) + if self.show_eta and self.eta_known and not self.finished: + info_bits.append(self.format_eta()) + if self.item_show_func is not None: + item_info = self.item_show_func(self.current_item) + if item_info is not None: + info_bits.append(item_info) + + return ( + self.bar_template + % { + "label": self.label, + "bar": self.format_bar(), + "info": self.info_sep.join(info_bits), + } + ).rstrip() + + def render_progress(self) -> None: + import shutil + + if self.is_hidden: + # Only output the label as it changes if the output is not a + # TTY. Use file=stderr if you expect to be piping stdout. + if self._last_line != self.label: + self._last_line = self.label + echo(self.label, file=self.file, color=self.color) + + return + + buf = [] + # Update width in case the terminal has been resized + if self.autowidth: + old_width = self.width + self.width = 0 + clutter_length = term_len(self.format_progress_line()) + new_width = max(0, shutil.get_terminal_size().columns - clutter_length) + if new_width < old_width: + buf.append(BEFORE_BAR) + buf.append(" " * self.max_width) # type: ignore + self.max_width = new_width + self.width = new_width + + clear_width = self.width + if self.max_width is not None: + clear_width = self.max_width + + buf.append(BEFORE_BAR) + line = self.format_progress_line() + line_len = term_len(line) + if self.max_width is None or self.max_width < line_len: + self.max_width = line_len + + buf.append(line) + buf.append(" " * (clear_width - line_len)) + line = "".join(buf) + # Render the line only if it changed. + + if line != self._last_line: + self._last_line = line + echo(line, file=self.file, color=self.color, nl=False) + self.file.flush() + + def make_step(self, n_steps: int) -> None: + self.pos += n_steps + if self.length is not None and self.pos >= self.length: + self.finished = True + + if (time.time() - self.last_eta) < 1.0: + return + + self.last_eta = time.time() + + # self.avg is a rolling list of length <= 7 of steps where steps are + # defined as time elapsed divided by the total progress through + # self.length. + if self.pos: + step = (time.time() - self.start) / self.pos + else: + step = time.time() - self.start + + self.avg = self.avg[-6:] + [step] + + self.eta_known = self.length is not None + + def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: + """Update the progress bar by advancing a specified number of + steps, and optionally set the ``current_item`` for this new + position. + + :param n_steps: Number of steps to advance. + :param current_item: Optional item to set as ``current_item`` + for the updated position. + + .. versionchanged:: 8.0 + Added the ``current_item`` optional parameter. + + .. versionchanged:: 8.0 + Only render when the number of steps meets the + ``update_min_steps`` threshold. + """ + if current_item is not None: + self.current_item = current_item + + self._completed_intervals += n_steps + + if self._completed_intervals >= self.update_min_steps: + self.make_step(self._completed_intervals) + self.render_progress() + self._completed_intervals = 0 + + def finish(self) -> None: + self.eta_known = False + self.current_item = None + self.finished = True + + def generator(self) -> t.Iterator[V]: + """Return a generator which yields the items added to the bar + during construction, and updates the progress bar *after* the + yielded block returns. + """ + # WARNING: the iterator interface for `ProgressBar` relies on + # this and only works because this is a simple generator which + # doesn't create or manage additional state. If this function + # changes, the impact should be evaluated both against + # `iter(bar)` and `next(bar)`. `next()` in particular may call + # `self.generator()` repeatedly, and this must remain safe in + # order for that interface to work. + if not self.entered: + raise RuntimeError("You need to use progress bars in a with block.") + + if self.is_hidden: + yield from self.iter + else: + for rv in self.iter: + self.current_item = rv + + # This allows show_item_func to be updated before the + # item is processed. Only trigger at the beginning of + # the update interval. + if self._completed_intervals == 0: + self.render_progress() + + yield rv + self.update(1) + + self.finish() + self.render_progress() + + +def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: + """Decide what method to use for paging through text.""" + stdout = _default_text_stdout() + if not isatty(sys.stdin) or not isatty(stdout): + return _nullpager(stdout, generator, color) + pager_cmd = (os.environ.get("PAGER", None) or "").strip() + if pager_cmd: + if WIN: + return _tempfilepager(generator, pager_cmd, color) + return _pipepager(generator, pager_cmd, color) + if os.environ.get("TERM") in ("dumb", "emacs"): + return _nullpager(stdout, generator, color) + if WIN or sys.platform.startswith("os2"): + return _tempfilepager(generator, "more <", color) + if hasattr(os, "system") and os.system("(less) 2>/dev/null") == 0: + return _pipepager(generator, "less", color) + + import tempfile + + fd, filename = tempfile.mkstemp() + os.close(fd) + try: + if hasattr(os, "system") and os.system(f'more "{filename}"') == 0: + return _pipepager(generator, "more", color) + return _nullpager(stdout, generator, color) + finally: + os.unlink(filename) + + +def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> None: + """Page through text by feeding it to another program. Invoking a + pager through this might support colors. + """ + import subprocess + + env = dict(os.environ) + + # If we're piping to less we might support colors under the + # condition that + cmd_detail = cmd.rsplit("/", 1)[-1].split() + if color is None and cmd_detail[0] == "less": + less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" + if not less_flags: + env["LESS"] = "-R" + color = True + elif "r" in less_flags or "R" in less_flags: + color = True + + c = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, env=env) + stdin = t.cast(t.BinaryIO, c.stdin) + encoding = get_best_encoding(stdin) + try: + for text in generator: + if not color: + text = strip_ansi(text) + + stdin.write(text.encode(encoding, "replace")) + except (OSError, KeyboardInterrupt): + pass + else: + stdin.close() + + # Less doesn't respect ^C, but catches it for its own UI purposes (aborting + # search or other commands inside less). + # + # That means when the user hits ^C, the parent process (click) terminates, + # but less is still alive, paging the output and messing up the terminal. + # + # If the user wants to make the pager exit on ^C, they should set + # `LESS='-K'`. It's not our decision to make. + while True: + try: + c.wait() + except KeyboardInterrupt: + pass + else: + break + + +def _tempfilepager( + generator: t.Iterable[str], cmd: str, color: t.Optional[bool] +) -> None: + """Page through text by invoking a program on a temporary file.""" + import tempfile + + fd, filename = tempfile.mkstemp() + # TODO: This never terminates if the passed generator never terminates. + text = "".join(generator) + if not color: + text = strip_ansi(text) + encoding = get_best_encoding(sys.stdout) + with open_stream(filename, "wb")[0] as f: + f.write(text.encode(encoding)) + try: + os.system(f'{cmd} "{filename}"') + finally: + os.close(fd) + os.unlink(filename) + + +def _nullpager( + stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] +) -> None: + """Simply print unformatted text. This is the ultimate fallback.""" + for text in generator: + if not color: + text = strip_ansi(text) + stream.write(text) + + +class Editor: + def __init__( + self, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + ) -> None: + self.editor = editor + self.env = env + self.require_save = require_save + self.extension = extension + + def get_editor(self) -> str: + if self.editor is not None: + return self.editor + for key in "VISUAL", "EDITOR": + rv = os.environ.get(key) + if rv: + return rv + if WIN: + return "notepad" + for editor in "sensible-editor", "vim", "nano": + if os.system(f"which {editor} >/dev/null 2>&1") == 0: + return editor + return "vi" + + def edit_file(self, filename: str) -> None: + import subprocess + + editor = self.get_editor() + environ: t.Optional[t.Dict[str, str]] = None + + if self.env: + environ = os.environ.copy() + environ.update(self.env) + + try: + c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) + exit_code = c.wait() + if exit_code != 0: + raise ClickException( + _("{editor}: Editing failed").format(editor=editor) + ) + except OSError as e: + raise ClickException( + _("{editor}: Editing failed: {e}").format(editor=editor, e=e) + ) from e + + def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: + import tempfile + + if not text: + data = b"" + elif isinstance(text, (bytes, bytearray)): + data = text + else: + if text and not text.endswith("\n"): + text += "\n" + + if WIN: + data = text.replace("\n", "\r\n").encode("utf-8-sig") + else: + data = text.encode("utf-8") + + fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) + f: t.BinaryIO + + try: + with os.fdopen(fd, "wb") as f: + f.write(data) + + # If the filesystem resolution is 1 second, like Mac OS + # 10.12 Extended, or 2 seconds, like FAT32, and the editor + # closes very fast, require_save can fail. Set the modified + # time to be 2 seconds in the past to work around this. + os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) + # Depending on the resolution, the exact value might not be + # recorded, so get the new recorded value. + timestamp = os.path.getmtime(name) + + self.edit_file(name) + + if self.require_save and os.path.getmtime(name) == timestamp: + return None + + with open(name, "rb") as f: + rv = f.read() + + if isinstance(text, (bytes, bytearray)): + return rv + + return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore + finally: + os.unlink(name) + + +def open_url(url: str, wait: bool = False, locate: bool = False) -> int: + import subprocess + + def _unquote_file(url: str) -> str: + from urllib.parse import unquote + + if url.startswith("file://"): + url = unquote(url[7:]) + + return url + + if sys.platform == "darwin": + args = ["open"] + if wait: + args.append("-W") + if locate: + args.append("-R") + args.append(_unquote_file(url)) + null = open("/dev/null", "w") + try: + return subprocess.Popen(args, stderr=null).wait() + finally: + null.close() + elif WIN: + if locate: + url = _unquote_file(url.replace('"', "")) + args = f'explorer /select,"{url}"' + else: + url = url.replace('"', "") + wait_str = "/WAIT" if wait else "" + args = f'start {wait_str} "" "{url}"' + return os.system(args) + elif CYGWIN: + if locate: + url = os.path.dirname(_unquote_file(url).replace('"', "")) + args = f'cygstart "{url}"' + else: + url = url.replace('"', "") + wait_str = "-w" if wait else "" + args = f'cygstart {wait_str} "{url}"' + return os.system(args) + + try: + if locate: + url = os.path.dirname(_unquote_file(url)) or "." + else: + url = _unquote_file(url) + c = subprocess.Popen(["xdg-open", url]) + if wait: + return c.wait() + return 0 + except OSError: + if url.startswith(("http://", "https://")) and not locate and not wait: + import webbrowser + + webbrowser.open(url) + return 0 + return 1 + + +def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: + if ch == "\x03": + raise KeyboardInterrupt() + + if ch == "\x04" and not WIN: # Unix-like, Ctrl+D + raise EOFError() + + if ch == "\x1a" and WIN: # Windows, Ctrl+Z + raise EOFError() + + return None + + +if WIN: + import msvcrt + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + yield -1 + + def getchar(echo: bool) -> str: + # The function `getch` will return a bytes object corresponding to + # the pressed character. Since Windows 10 build 1803, it will also + # return \x00 when called a second time after pressing a regular key. + # + # `getwch` does not share this probably-bugged behavior. Moreover, it + # returns a Unicode object by default, which is what we want. + # + # Either of these functions will return \x00 or \xe0 to indicate + # a special key, and you need to call the same function again to get + # the "rest" of the code. The fun part is that \u00e0 is + # "latin small letter a with grave", so if you type that on a French + # keyboard, you _also_ get a \xe0. + # E.g., consider the Up arrow. This returns \xe0 and then \x48. The + # resulting Unicode string reads as "a with grave" + "capital H". + # This is indistinguishable from when the user actually types + # "a with grave" and then "capital H". + # + # When \xe0 is returned, we assume it's part of a special-key sequence + # and call `getwch` again, but that means that when the user types + # the \u00e0 character, `getchar` doesn't return until a second + # character is typed. + # The alternative is returning immediately, but that would mess up + # cross-platform handling of arrow keys and others that start with + # \xe0. Another option is using `getch`, but then we can't reliably + # read non-ASCII characters, because return values of `getch` are + # limited to the current 8-bit codepage. + # + # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` + # is doing the right thing in more situations than with `getch`. + func: t.Callable[[], str] + + if echo: + func = msvcrt.getwche # type: ignore + else: + func = msvcrt.getwch # type: ignore + + rv = func() + + if rv in ("\x00", "\xe0"): + # \x00 and \xe0 are control characters that indicate special key, + # see above. + rv += func() + + _translate_ch_to_exc(rv) + return rv + +else: + import tty + import termios + + @contextlib.contextmanager + def raw_terminal() -> t.Iterator[int]: + f: t.Optional[t.TextIO] + fd: int + + if not isatty(sys.stdin): + f = open("/dev/tty") + fd = f.fileno() + else: + fd = sys.stdin.fileno() + f = None + + try: + old_settings = termios.tcgetattr(fd) + + try: + tty.setraw(fd) + yield fd + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + sys.stdout.flush() + + if f is not None: + f.close() + except termios.error: + pass + + def getchar(echo: bool) -> str: + with raw_terminal() as fd: + ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") + + if echo and isatty(sys.stdout): + sys.stdout.write(ch) + + _translate_ch_to_exc(ch) + return ch diff --git a/flask-server/venv/lib/python3.10/site-packages/click/_textwrap.py b/flask-server/venv/lib/python3.10/site-packages/click/_textwrap.py new file mode 100644 index 00000000..b47dcbd4 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/_textwrap.py @@ -0,0 +1,49 @@ +import textwrap +import typing as t +from contextlib import contextmanager + + +class TextWrapper(textwrap.TextWrapper): + def _handle_long_word( + self, + reversed_chunks: t.List[str], + cur_line: t.List[str], + cur_len: int, + width: int, + ) -> None: + space_left = max(width - cur_len, 1) + + if self.break_long_words: + last = reversed_chunks[-1] + cut = last[:space_left] + res = last[space_left:] + cur_line.append(cut) + reversed_chunks[-1] = res + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + @contextmanager + def extra_indent(self, indent: str) -> t.Iterator[None]: + old_initial_indent = self.initial_indent + old_subsequent_indent = self.subsequent_indent + self.initial_indent += indent + self.subsequent_indent += indent + + try: + yield + finally: + self.initial_indent = old_initial_indent + self.subsequent_indent = old_subsequent_indent + + def indent_only(self, text: str) -> str: + rv = [] + + for idx, line in enumerate(text.splitlines()): + indent = self.initial_indent + + if idx > 0: + indent = self.subsequent_indent + + rv.append(f"{indent}{line}") + + return "\n".join(rv) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/_winconsole.py b/flask-server/venv/lib/python3.10/site-packages/click/_winconsole.py new file mode 100644 index 00000000..6b20df31 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/_winconsole.py @@ -0,0 +1,279 @@ +# This module is based on the excellent work by Adam Bartoš who +# provided a lot of what went into the implementation here in +# the discussion to issue1602 in the Python bug tracker. +# +# There are some general differences in regards to how this works +# compared to the original patches as we do not need to patch +# the entire interpreter but just work in our little world of +# echo and prompt. +import io +import sys +import time +import typing as t +from ctypes import byref +from ctypes import c_char +from ctypes import c_char_p +from ctypes import c_int +from ctypes import c_ssize_t +from ctypes import c_ulong +from ctypes import c_void_p +from ctypes import POINTER +from ctypes import py_object +from ctypes import Structure +from ctypes.wintypes import DWORD +from ctypes.wintypes import HANDLE +from ctypes.wintypes import LPCWSTR +from ctypes.wintypes import LPWSTR + +from ._compat import _NonClosingTextIOWrapper + +assert sys.platform == "win32" +import msvcrt # noqa: E402 +from ctypes import windll # noqa: E402 +from ctypes import WINFUNCTYPE # noqa: E402 + +c_ssize_p = POINTER(c_ssize_t) + +kernel32 = windll.kernel32 +GetStdHandle = kernel32.GetStdHandle +ReadConsoleW = kernel32.ReadConsoleW +WriteConsoleW = kernel32.WriteConsoleW +GetConsoleMode = kernel32.GetConsoleMode +GetLastError = kernel32.GetLastError +GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) +CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( + ("CommandLineToArgvW", windll.shell32) +) +LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) + +STDIN_HANDLE = GetStdHandle(-10) +STDOUT_HANDLE = GetStdHandle(-11) +STDERR_HANDLE = GetStdHandle(-12) + +PyBUF_SIMPLE = 0 +PyBUF_WRITABLE = 1 + +ERROR_SUCCESS = 0 +ERROR_NOT_ENOUGH_MEMORY = 8 +ERROR_OPERATION_ABORTED = 995 + +STDIN_FILENO = 0 +STDOUT_FILENO = 1 +STDERR_FILENO = 2 + +EOF = b"\x1a" +MAX_BYTES_WRITTEN = 32767 + +try: + from ctypes import pythonapi +except ImportError: + # On PyPy we cannot get buffers so our ability to operate here is + # severely limited. + get_buffer = None +else: + + class Py_buffer(Structure): + _fields_ = [ + ("buf", c_void_p), + ("obj", py_object), + ("len", c_ssize_t), + ("itemsize", c_ssize_t), + ("readonly", c_int), + ("ndim", c_int), + ("format", c_char_p), + ("shape", c_ssize_p), + ("strides", c_ssize_p), + ("suboffsets", c_ssize_p), + ("internal", c_void_p), + ] + + PyObject_GetBuffer = pythonapi.PyObject_GetBuffer + PyBuffer_Release = pythonapi.PyBuffer_Release + + def get_buffer(obj, writable=False): + buf = Py_buffer() + flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE + PyObject_GetBuffer(py_object(obj), byref(buf), flags) + + try: + buffer_type = c_char * buf.len + return buffer_type.from_address(buf.buf) + finally: + PyBuffer_Release(byref(buf)) + + +class _WindowsConsoleRawIOBase(io.RawIOBase): + def __init__(self, handle): + self.handle = handle + + def isatty(self): + super().isatty() + return True + + +class _WindowsConsoleReader(_WindowsConsoleRawIOBase): + def readable(self): + return True + + def readinto(self, b): + bytes_to_be_read = len(b) + if not bytes_to_be_read: + return 0 + elif bytes_to_be_read % 2: + raise ValueError( + "cannot read odd number of bytes from UTF-16-LE encoded console" + ) + + buffer = get_buffer(b, writable=True) + code_units_to_be_read = bytes_to_be_read // 2 + code_units_read = c_ulong() + + rv = ReadConsoleW( + HANDLE(self.handle), + buffer, + code_units_to_be_read, + byref(code_units_read), + None, + ) + if GetLastError() == ERROR_OPERATION_ABORTED: + # wait for KeyboardInterrupt + time.sleep(0.1) + if not rv: + raise OSError(f"Windows error: {GetLastError()}") + + if buffer[0] == EOF: + return 0 + return 2 * code_units_read.value + + +class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): + def writable(self): + return True + + @staticmethod + def _get_error_message(errno): + if errno == ERROR_SUCCESS: + return "ERROR_SUCCESS" + elif errno == ERROR_NOT_ENOUGH_MEMORY: + return "ERROR_NOT_ENOUGH_MEMORY" + return f"Windows error {errno}" + + def write(self, b): + bytes_to_be_written = len(b) + buf = get_buffer(b) + code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 + code_units_written = c_ulong() + + WriteConsoleW( + HANDLE(self.handle), + buf, + code_units_to_be_written, + byref(code_units_written), + None, + ) + bytes_written = 2 * code_units_written.value + + if bytes_written == 0 and bytes_to_be_written > 0: + raise OSError(self._get_error_message(GetLastError())) + return bytes_written + + +class ConsoleStream: + def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: + self._text_stream = text_stream + self.buffer = byte_stream + + @property + def name(self) -> str: + return self.buffer.name + + def write(self, x: t.AnyStr) -> int: + if isinstance(x, str): + return self._text_stream.write(x) + try: + self.flush() + except Exception: + pass + return self.buffer.write(x) + + def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: + for line in lines: + self.write(line) + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._text_stream, name) + + def isatty(self) -> bool: + return self.buffer.isatty() + + def __repr__(self): + return f"" + + +def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: + text_stream = _NonClosingTextIOWrapper( + io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), + "utf-16-le", + "strict", + line_buffering=True, + ) + return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) + + +_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { + 0: _get_text_stdin, + 1: _get_text_stdout, + 2: _get_text_stderr, +} + + +def _is_console(f: t.TextIO) -> bool: + if not hasattr(f, "fileno"): + return False + + try: + fileno = f.fileno() + except (OSError, io.UnsupportedOperation): + return False + + handle = msvcrt.get_osfhandle(fileno) + return bool(GetConsoleMode(handle, byref(DWORD()))) + + +def _get_windows_console_stream( + f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] +) -> t.Optional[t.TextIO]: + if ( + get_buffer is not None + and encoding in {"utf-16-le", None} + and errors in {"strict", None} + and _is_console(f) + ): + func = _stream_factories.get(f.fileno()) + if func is not None: + b = getattr(f, "buffer", None) + + if b is None: + return None + + return func(b) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/core.py b/flask-server/venv/lib/python3.10/site-packages/click/core.py new file mode 100644 index 00000000..5abfb0f3 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/core.py @@ -0,0 +1,2998 @@ +import enum +import errno +import inspect +import os +import sys +import typing as t +from collections import abc +from contextlib import contextmanager +from contextlib import ExitStack +from functools import partial +from functools import update_wrapper +from gettext import gettext as _ +from gettext import ngettext +from itertools import repeat + +from . import types +from .exceptions import Abort +from .exceptions import BadParameter +from .exceptions import ClickException +from .exceptions import Exit +from .exceptions import MissingParameter +from .exceptions import UsageError +from .formatting import HelpFormatter +from .formatting import join_options +from .globals import pop_context +from .globals import push_context +from .parser import _flag_needs_value +from .parser import OptionParser +from .parser import split_opt +from .termui import confirm +from .termui import prompt +from .termui import style +from .utils import _detect_program_name +from .utils import _expand_args +from .utils import echo +from .utils import make_default_short_help +from .utils import make_str +from .utils import PacifyFlushWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from .shell_completion import CompletionItem + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +V = t.TypeVar("V") + + +def _complete_visible_commands( + ctx: "Context", incomplete: str +) -> t.Iterator[t.Tuple[str, "Command"]]: + """List all the subcommands of a group that start with the + incomplete value and aren't hidden. + + :param ctx: Invocation context for the group. + :param incomplete: Value being completed. May be empty. + """ + multi = t.cast(MultiCommand, ctx.command) + + for name in multi.list_commands(ctx): + if name.startswith(incomplete): + command = multi.get_command(ctx, name) + + if command is not None and not command.hidden: + yield name, command + + +def _check_multicommand( + base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False +) -> None: + if not base_command.chain or not isinstance(cmd, MultiCommand): + return + if register: + hint = ( + "It is not possible to add multi commands as children to" + " another multi command that is in chain mode." + ) + else: + hint = ( + "Found a multi command as subcommand to a multi command" + " that is in chain mode. This is not supported." + ) + raise RuntimeError( + f"{hint}. Command {base_command.name!r} is set to chain and" + f" {cmd_name!r} was added as a subcommand but it in itself is a" + f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" + f" within a chained {type(base_command).__name__} named" + f" {base_command.name!r})." + ) + + +def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: + return list(zip(*repeat(iter(iterable), batch_size))) + + +@contextmanager +def augment_usage_errors( + ctx: "Context", param: t.Optional["Parameter"] = None +) -> t.Iterator[None]: + """Context manager that attaches extra information to exceptions.""" + try: + yield + except BadParameter as e: + if e.ctx is None: + e.ctx = ctx + if param is not None and e.param is None: + e.param = param + raise + except UsageError as e: + if e.ctx is None: + e.ctx = ctx + raise + + +def iter_params_for_processing( + invocation_order: t.Sequence["Parameter"], + declaration_order: t.Sequence["Parameter"], +) -> t.List["Parameter"]: + """Given a sequence of parameters in the order as should be considered + for processing and an iterable of parameters that exist, this returns + a list in the correct order as they should be processed. + """ + + def sort_key(item: "Parameter") -> t.Tuple[bool, float]: + try: + idx: float = invocation_order.index(item) + except ValueError: + idx = float("inf") + + return not item.is_eager, idx + + return sorted(declaration_order, key=sort_key) + + +class ParameterSource(enum.Enum): + """This is an :class:`~enum.Enum` that indicates the source of a + parameter's value. + + Use :meth:`click.Context.get_parameter_source` to get the + source for a parameter by name. + + .. versionchanged:: 8.0 + Use :class:`~enum.Enum` and drop the ``validate`` method. + + .. versionchanged:: 8.0 + Added the ``PROMPT`` value. + """ + + COMMANDLINE = enum.auto() + """The value was provided by the command line args.""" + ENVIRONMENT = enum.auto() + """The value was provided with an environment variable.""" + DEFAULT = enum.auto() + """Used the default specified by the parameter.""" + DEFAULT_MAP = enum.auto() + """Used a default provided by :attr:`Context.default_map`.""" + PROMPT = enum.auto() + """Used a prompt to confirm a default or provide a value.""" + + +class Context: + """The context is a special internal object that holds state relevant + for the script execution at every single level. It's normally invisible + to commands unless they opt-in to getting access to it. + + The context is useful as it can pass internal objects around and can + control special execution features such as reading data from + environment variables. + + A context can be used as context manager in which case it will call + :meth:`close` on teardown. + + :param command: the command class for this context. + :param parent: the parent context. + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it is usually + the name of the script, for commands below it it's + the name of the script. + :param obj: an arbitrary object of user data. + :param auto_envvar_prefix: the prefix to use for automatic environment + variables. If this is `None` then reading + from environment variables is disabled. This + does not affect manually set environment + variables which are always read. + :param default_map: a dictionary (like object) with default values + for parameters. + :param terminal_width: the width of the terminal. The default is + inherit from parent context. If no context + defines the terminal width then auto + detection will be applied. + :param max_content_width: the maximum width for content rendered by + Click (this currently only affects help + pages). This defaults to 80 characters if + not overridden. In other words: even if the + terminal is larger than that, Click will not + format things wider than 80 characters by + default. In addition to that, formatters might + add some safety mapping on the right. + :param resilient_parsing: if this flag is enabled then Click will + parse without any interactivity or callback + invocation. Default values will also be + ignored. This is useful for implementing + things such as completion support. + :param allow_extra_args: if this is set to `True` then extra arguments + at the end will not raise an error and will be + kept on the context. The default is to inherit + from the command. + :param allow_interspersed_args: if this is set to `False` then options + and arguments cannot be mixed. The + default is to inherit from the command. + :param ignore_unknown_options: instructs click to ignore options it does + not know and keeps them for later + processing. + :param help_option_names: optionally a list of strings that define how + the default help parameter is named. The + default is ``['--help']``. + :param token_normalize_func: an optional function that is used to + normalize tokens (options, choices, + etc.). This for instance can be used to + implement case insensitive behavior. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are used in texts that Click prints which is by + default not the case. This for instance would affect + help output. + :param show_default: Show the default value for commands. If this + value is not set, it defaults to the value from the parent + context. ``Command.show_default`` overrides this default for the + specific command. + + .. versionchanged:: 8.1 + The ``show_default`` parameter is overridden by + ``Command.show_default``, instead of the other way around. + + .. versionchanged:: 8.0 + The ``show_default`` parameter defaults to the value from the + parent context. + + .. versionchanged:: 7.1 + Added the ``show_default`` parameter. + + .. versionchanged:: 4.0 + Added the ``color``, ``ignore_unknown_options``, and + ``max_content_width`` parameters. + + .. versionchanged:: 3.0 + Added the ``allow_extra_args`` and ``allow_interspersed_args`` + parameters. + + .. versionchanged:: 2.0 + Added the ``resilient_parsing``, ``help_option_names``, and + ``token_normalize_func`` parameters. + """ + + #: The formatter class to create with :meth:`make_formatter`. + #: + #: .. versionadded:: 8.0 + formatter_class: t.Type["HelpFormatter"] = HelpFormatter + + def __init__( + self, + command: "Command", + parent: t.Optional["Context"] = None, + info_name: t.Optional[str] = None, + obj: t.Optional[t.Any] = None, + auto_envvar_prefix: t.Optional[str] = None, + default_map: t.Optional[t.Dict[str, t.Any]] = None, + terminal_width: t.Optional[int] = None, + max_content_width: t.Optional[int] = None, + resilient_parsing: bool = False, + allow_extra_args: t.Optional[bool] = None, + allow_interspersed_args: t.Optional[bool] = None, + ignore_unknown_options: t.Optional[bool] = None, + help_option_names: t.Optional[t.List[str]] = None, + token_normalize_func: t.Optional[t.Callable[[str], str]] = None, + color: t.Optional[bool] = None, + show_default: t.Optional[bool] = None, + ) -> None: + #: the parent context or `None` if none exists. + self.parent = parent + #: the :class:`Command` for this context. + self.command = command + #: the descriptive information name + self.info_name = info_name + #: Map of parameter names to their parsed values. Parameters + #: with ``expose_value=False`` are not stored. + self.params: t.Dict[str, t.Any] = {} + #: the leftover arguments. + self.args: t.List[str] = [] + #: protected arguments. These are arguments that are prepended + #: to `args` when certain parsing scenarios are encountered but + #: must be never propagated to another arguments. This is used + #: to implement nested parsing. + self.protected_args: t.List[str] = [] + #: the collected prefixes of the command's options. + self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() + + if obj is None and parent is not None: + obj = parent.obj + + #: the user object stored. + self.obj: t.Any = obj + self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) + + #: A dictionary (-like object) with defaults for parameters. + if ( + default_map is None + and info_name is not None + and parent is not None + and parent.default_map is not None + ): + default_map = parent.default_map.get(info_name) + + self.default_map: t.Optional[t.Dict[str, t.Any]] = default_map + + #: This flag indicates if a subcommand is going to be executed. A + #: group callback can use this information to figure out if it's + #: being executed directly or because the execution flow passes + #: onwards to a subcommand. By default it's None, but it can be + #: the name of the subcommand to execute. + #: + #: If chaining is enabled this will be set to ``'*'`` in case + #: any commands are executed. It is however not possible to + #: figure out which ones. If you require this knowledge you + #: should use a :func:`result_callback`. + self.invoked_subcommand: t.Optional[str] = None + + if terminal_width is None and parent is not None: + terminal_width = parent.terminal_width + + #: The width of the terminal (None is autodetection). + self.terminal_width: t.Optional[int] = terminal_width + + if max_content_width is None and parent is not None: + max_content_width = parent.max_content_width + + #: The maximum width of formatted content (None implies a sensible + #: default which is 80 for most things). + self.max_content_width: t.Optional[int] = max_content_width + + if allow_extra_args is None: + allow_extra_args = command.allow_extra_args + + #: Indicates if the context allows extra args or if it should + #: fail on parsing. + #: + #: .. versionadded:: 3.0 + self.allow_extra_args = allow_extra_args + + if allow_interspersed_args is None: + allow_interspersed_args = command.allow_interspersed_args + + #: Indicates if the context allows mixing of arguments and + #: options or not. + #: + #: .. versionadded:: 3.0 + self.allow_interspersed_args: bool = allow_interspersed_args + + if ignore_unknown_options is None: + ignore_unknown_options = command.ignore_unknown_options + + #: Instructs click to ignore options that a command does not + #: understand and will store it on the context for later + #: processing. This is primarily useful for situations where you + #: want to call into external programs. Generally this pattern is + #: strongly discouraged because it's not possibly to losslessly + #: forward all arguments. + #: + #: .. versionadded:: 4.0 + self.ignore_unknown_options: bool = ignore_unknown_options + + if help_option_names is None: + if parent is not None: + help_option_names = parent.help_option_names + else: + help_option_names = ["--help"] + + #: The names for the help options. + self.help_option_names: t.List[str] = help_option_names + + if token_normalize_func is None and parent is not None: + token_normalize_func = parent.token_normalize_func + + #: An optional normalization function for tokens. This is + #: options, choices, commands etc. + self.token_normalize_func: t.Optional[ + t.Callable[[str], str] + ] = token_normalize_func + + #: Indicates if resilient parsing is enabled. In that case Click + #: will do its best to not cause any failures and default values + #: will be ignored. Useful for completion. + self.resilient_parsing: bool = resilient_parsing + + # If there is no envvar prefix yet, but the parent has one and + # the command on this level has a name, we can expand the envvar + # prefix automatically. + if auto_envvar_prefix is None: + if ( + parent is not None + and parent.auto_envvar_prefix is not None + and self.info_name is not None + ): + auto_envvar_prefix = ( + f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" + ) + else: + auto_envvar_prefix = auto_envvar_prefix.upper() + + if auto_envvar_prefix is not None: + auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") + + self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix + + if color is None and parent is not None: + color = parent.color + + #: Controls if styling output is wanted or not. + self.color: t.Optional[bool] = color + + if show_default is None and parent is not None: + show_default = parent.show_default + + #: Show option default values when formatting help text. + self.show_default: t.Optional[bool] = show_default + + self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] + self._depth = 0 + self._parameter_source: t.Dict[str, ParameterSource] = {} + self._exit_stack = ExitStack() + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire CLI + structure. + + .. code-block:: python + + with Context(cli) as ctx: + info = ctx.to_info_dict() + + .. versionadded:: 8.0 + """ + return { + "command": self.command.to_info_dict(self), + "info_name": self.info_name, + "allow_extra_args": self.allow_extra_args, + "allow_interspersed_args": self.allow_interspersed_args, + "ignore_unknown_options": self.ignore_unknown_options, + "auto_envvar_prefix": self.auto_envvar_prefix, + } + + def __enter__(self) -> "Context": + self._depth += 1 + push_context(self) + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self._depth -= 1 + if self._depth == 0: + self.close() + pop_context() + + @contextmanager + def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: + """This helper method can be used with the context object to promote + it to the current thread local (see :func:`get_current_context`). + The default behavior of this is to invoke the cleanup functions which + can be disabled by setting `cleanup` to `False`. The cleanup + functions are typically used for things such as closing file handles. + + If the cleanup is intended the context object can also be directly + used as a context manager. + + Example usage:: + + with ctx.scope(): + assert get_current_context() is ctx + + This is equivalent:: + + with ctx: + assert get_current_context() is ctx + + .. versionadded:: 5.0 + + :param cleanup: controls if the cleanup functions should be run or + not. The default is to run these functions. In + some situations the context only wants to be + temporarily pushed in which case this can be disabled. + Nested pushes automatically defer the cleanup. + """ + if not cleanup: + self._depth += 1 + try: + with self as rv: + yield rv + finally: + if not cleanup: + self._depth -= 1 + + @property + def meta(self) -> t.Dict[str, t.Any]: + """This is a dictionary which is shared with all the contexts + that are nested. It exists so that click utilities can store some + state here if they need to. It is however the responsibility of + that code to manage this dictionary well. + + The keys are supposed to be unique dotted strings. For instance + module paths are a good choice for it. What is stored in there is + irrelevant for the operation of click. However what is important is + that code that places data here adheres to the general semantics of + the system. + + Example usage:: + + LANG_KEY = f'{__name__}.lang' + + def set_language(value): + ctx = get_current_context() + ctx.meta[LANG_KEY] = value + + def get_language(): + return get_current_context().meta.get(LANG_KEY, 'en_US') + + .. versionadded:: 5.0 + """ + return self._meta + + def make_formatter(self) -> HelpFormatter: + """Creates the :class:`~click.HelpFormatter` for the help and + usage output. + + To quickly customize the formatter class used without overriding + this method, set the :attr:`formatter_class` attribute. + + .. versionchanged:: 8.0 + Added the :attr:`formatter_class` attribute. + """ + return self.formatter_class( + width=self.terminal_width, max_width=self.max_content_width + ) + + def with_resource(self, context_manager: t.ContextManager[V]) -> V: + """Register a resource as if it were used in a ``with`` + statement. The resource will be cleaned up when the context is + popped. + + Uses :meth:`contextlib.ExitStack.enter_context`. It calls the + resource's ``__enter__()`` method and returns the result. When + the context is popped, it closes the stack, which calls the + resource's ``__exit__()`` method. + + To register a cleanup function for something that isn't a + context manager, use :meth:`call_on_close`. Or use something + from :mod:`contextlib` to turn it into a context manager first. + + .. code-block:: python + + @click.group() + @click.option("--name") + @click.pass_context + def cli(ctx): + ctx.obj = ctx.with_resource(connect_db(name)) + + :param context_manager: The context manager to enter. + :return: Whatever ``context_manager.__enter__()`` returns. + + .. versionadded:: 8.0 + """ + return self._exit_stack.enter_context(context_manager) + + def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: + """Register a function to be called when the context tears down. + + This can be used to close resources opened during the script + execution. Resources that support Python's context manager + protocol which would be used in a ``with`` statement should be + registered with :meth:`with_resource` instead. + + :param f: The function to execute on teardown. + """ + return self._exit_stack.callback(f) + + def close(self) -> None: + """Invoke all close callbacks registered with + :meth:`call_on_close`, and exit all context managers entered + with :meth:`with_resource`. + """ + self._exit_stack.close() + # In case the context is reused, create a new exit stack. + self._exit_stack = ExitStack() + + @property + def command_path(self) -> str: + """The computed command path. This is used for the ``usage`` + information on the help page. It's automatically created by + combining the info names of the chain of contexts to the root. + """ + rv = "" + if self.info_name is not None: + rv = self.info_name + if self.parent is not None: + parent_command_path = [self.parent.command_path] + + if isinstance(self.parent.command, Command): + for param in self.parent.command.get_params(self): + parent_command_path.extend(param.get_usage_pieces(self)) + + rv = f"{' '.join(parent_command_path)} {rv}" + return rv.lstrip() + + def find_root(self) -> "Context": + """Finds the outermost context.""" + node = self + while node.parent is not None: + node = node.parent + return node + + def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: + """Finds the closest object of a given type.""" + node: t.Optional["Context"] = self + + while node is not None: + if isinstance(node.obj, object_type): + return node.obj + + node = node.parent + + return None + + def ensure_object(self, object_type: t.Type[V]) -> V: + """Like :meth:`find_object` but sets the innermost object to a + new instance of `object_type` if it does not exist. + """ + rv = self.find_object(object_type) + if rv is None: + self.obj = rv = object_type() + return rv + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def lookup_default( + self, name: str, call: "te.Literal[False]" = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: + """Get the default for a parameter from :attr:`default_map`. + + :param name: Name of the parameter. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + if self.default_map is not None: + value = self.default_map.get(name) + + if call and callable(value): + return value() + + return value + + return None + + def fail(self, message: str) -> "te.NoReturn": + """Aborts the execution of the program with a specific error + message. + + :param message: the error message to fail with. + """ + raise UsageError(message, self) + + def abort(self) -> "te.NoReturn": + """Aborts the script.""" + raise Abort() + + def exit(self, code: int = 0) -> "te.NoReturn": + """Exits the application with a given exit code.""" + raise Exit(code) + + def get_usage(self) -> str: + """Helper method to get formatted usage string for the current + context and command. + """ + return self.command.get_usage(self) + + def get_help(self) -> str: + """Helper method to get formatted help page for the current + context and command. + """ + return self.command.get_help(self) + + def _make_sub_context(self, command: "Command") -> "Context": + """Create a new context of the same type as this context, but + for a new command. + + :meta private: + """ + return type(self)(command, info_name=command.name, parent=self) + + def invoke( + __self, # noqa: B902 + __callback: t.Union["Command", t.Callable[..., t.Any]], + *args: t.Any, + **kwargs: t.Any, + ) -> t.Any: + """Invokes a command callback in exactly the way it expects. There + are two ways to invoke this method: + + 1. the first argument can be a callback and all other arguments and + keyword arguments are forwarded directly to the function. + 2. the first argument is a click command object. In that case all + arguments are forwarded as well but proper click parameters + (options and click arguments) must be keyword arguments and Click + will fill in defaults. + + Note that before Click 3.2 keyword arguments were not properly filled + in against the intention of this code and no context was created. For + more information about this change and why it was done in a bugfix + release see :ref:`upgrade-to-3.2`. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if :meth:`forward` is called at multiple levels. + """ + if isinstance(__callback, Command): + other_cmd = __callback + + if other_cmd.callback is None: + raise TypeError( + "The given command does not have a callback that can be invoked." + ) + else: + __callback = other_cmd.callback + + ctx = __self._make_sub_context(other_cmd) + + for param in other_cmd.params: + if param.name not in kwargs and param.expose_value: + kwargs[param.name] = param.type_cast_value( # type: ignore + ctx, param.get_default(ctx) + ) + + # Track all kwargs as params, so that forward() will pass + # them on in subsequent calls. + ctx.params.update(kwargs) + else: + ctx = __self + + with augment_usage_errors(__self): + with ctx: + return __callback(*args, **kwargs) + + def forward( + __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any # noqa: B902 + ) -> t.Any: + """Similar to :meth:`invoke` but fills in default keyword + arguments from the current context if the other command expects + it. This cannot invoke callbacks directly, only other commands. + + .. versionchanged:: 8.0 + All ``kwargs`` are tracked in :attr:`params` so they will be + passed if ``forward`` is called at multiple levels. + """ + # Can only forward to other commands, not direct callbacks. + if not isinstance(__cmd, Command): + raise TypeError("Callback is not a command.") + + for param in __self.params: + if param not in kwargs: + kwargs[param] = __self.params[param] + + return __self.invoke(__cmd, *args, **kwargs) + + def set_parameter_source(self, name: str, source: ParameterSource) -> None: + """Set the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + :param name: The name of the parameter. + :param source: A member of :class:`~click.core.ParameterSource`. + """ + self._parameter_source[name] = source + + def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: + """Get the source of a parameter. This indicates the location + from which the value of the parameter was obtained. + + This can be useful for determining when a user specified a value + on the command line that is the same as the default value. It + will be :attr:`~click.core.ParameterSource.DEFAULT` only if the + value was actually taken from the default. + + :param name: The name of the parameter. + :rtype: ParameterSource + + .. versionchanged:: 8.0 + Returns ``None`` if the parameter was not provided from any + source. + """ + return self._parameter_source.get(name) + + +class BaseCommand: + """The base command implements the minimal API contract of commands. + Most code will never use this as it does not implement a lot of useful + functionality but it can act as the direct subclass of alternative + parsing methods that do not depend on the Click parser. + + For instance, this can be used to bridge Click and other systems like + argparse or docopt. + + Because base commands do not implement a lot of the API that other + parts of Click take for granted, they are not supported for all + operations. For instance, they cannot be used with the decorators + usually and they have no built-in callback system. + + .. versionchanged:: 2.0 + Added the `context_settings` parameter. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + """ + + #: The context class to create with :meth:`make_context`. + #: + #: .. versionadded:: 8.0 + context_class: t.Type[Context] = Context + #: the default for the :attr:`Context.allow_extra_args` flag. + allow_extra_args = False + #: the default for the :attr:`Context.allow_interspersed_args` flag. + allow_interspersed_args = True + #: the default for the :attr:`Context.ignore_unknown_options` flag. + ignore_unknown_options = False + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + ) -> None: + #: the name the command thinks it has. Upon registering a command + #: on a :class:`Group` the group will default the command name + #: with this information. You should instead use the + #: :class:`Context`\'s :attr:`~Context.info_name` attribute. + self.name = name + + if context_settings is None: + context_settings = {} + + #: an optional dictionary with defaults passed to the context. + self.context_settings: t.Dict[str, t.Any] = context_settings + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. This traverses the entire structure + below this command. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + :param ctx: A :class:`Context` representing this command. + + .. versionadded:: 8.0 + """ + return {"name": self.name} + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def get_usage(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get usage") + + def get_help(self, ctx: Context) -> str: + raise NotImplementedError("Base commands cannot get help") + + def make_context( + self, + info_name: t.Optional[str], + args: t.List[str], + parent: t.Optional[Context] = None, + **extra: t.Any, + ) -> Context: + """This function when given an info name and arguments will kick + off the parsing and create a new :class:`Context`. It does not + invoke the actual command callback though. + + To quickly customize the context class used without overriding + this method, set the :attr:`context_class` attribute. + + :param info_name: the info name for this invocation. Generally this + is the most descriptive name for the script or + command. For the toplevel script it's usually + the name of the script, for commands below it it's + the name of the command. + :param args: the arguments to parse as list of strings. + :param parent: the parent context if available. + :param extra: extra keyword arguments forwarded to the context + constructor. + + .. versionchanged:: 8.0 + Added the :attr:`context_class` attribute. + """ + for key, value in self.context_settings.items(): + if key not in extra: + extra[key] = value + + ctx = self.context_class( + self, info_name=info_name, parent=parent, **extra # type: ignore + ) + + with ctx.scope(cleanup=False): + self.parse_args(ctx, args) + return ctx + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + """Given a context and a list of arguments this creates the parser + and parses the arguments, then modifies the context as necessary. + This is automatically invoked by :meth:`make_context`. + """ + raise NotImplementedError("Base commands do not know how to parse arguments.") + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the command. The default + implementation is raising a not implemented error. + """ + raise NotImplementedError("Base commands are not invokable by default") + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of chained multi-commands. + + Any command could be part of a chained multi-command, so sibling + commands are valid at any point during command completion. Other + command classes will return more completions. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + while ctx.parent is not None: + ctx = ctx.parent + + if isinstance(ctx.command, MultiCommand) and ctx.command.chain: + results.extend( + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + if name not in ctx.protected_args + ) + + return results + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: "te.Literal[True]" = True, + **extra: t.Any, + ) -> "te.NoReturn": + ... + + @t.overload + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = ..., + **extra: t.Any, + ) -> t.Any: + ... + + def main( + self, + args: t.Optional[t.Sequence[str]] = None, + prog_name: t.Optional[str] = None, + complete_var: t.Optional[str] = None, + standalone_mode: bool = True, + windows_expand_args: bool = True, + **extra: t.Any, + ) -> t.Any: + """This is the way to invoke a script with all the bells and + whistles as a command line application. This will always terminate + the application after a call. If this is not wanted, ``SystemExit`` + needs to be caught. + + This method is also available by directly calling the instance of + a :class:`Command`. + + :param args: the arguments that should be used for parsing. If not + provided, ``sys.argv[1:]`` is used. + :param prog_name: the program name that should be used. By default + the program name is constructed by taking the file + name from ``sys.argv[0]``. + :param complete_var: the environment variable that controls the + bash completion support. The default is + ``"__COMPLETE"`` with prog_name in + uppercase. + :param standalone_mode: the default behavior is to invoke the script + in standalone mode. Click will then + handle exceptions and convert them into + error messages and the function will never + return but shut down the interpreter. If + this is set to `False` they will be + propagated to the caller and the return + value of this function is the return value + of :meth:`invoke`. + :param windows_expand_args: Expand glob patterns, user dir, and + env vars in command line args on Windows. + :param extra: extra keyword arguments are forwarded to the context + constructor. See :class:`Context` for more information. + + .. versionchanged:: 8.0.1 + Added the ``windows_expand_args`` parameter to allow + disabling command line arg expansion on Windows. + + .. versionchanged:: 8.0 + When taking arguments from ``sys.argv`` on Windows, glob + patterns, user dir, and env vars are expanded. + + .. versionchanged:: 3.0 + Added the ``standalone_mode`` parameter. + """ + if args is None: + args = sys.argv[1:] + + if os.name == "nt" and windows_expand_args: + args = _expand_args(args) + else: + args = list(args) + + if prog_name is None: + prog_name = _detect_program_name() + + # Process shell completion requests and exit early. + self._main_shell_completion(extra, prog_name, complete_var) + + try: + try: + with self.make_context(prog_name, args, **extra) as ctx: + rv = self.invoke(ctx) + if not standalone_mode: + return rv + # it's not safe to `ctx.exit(rv)` here! + # note that `rv` may actually contain data like "1" which + # has obvious effects + # more subtle case: `rv=[None, None]` can come out of + # chained commands which all returned `None` -- so it's not + # even always obvious that `rv` indicates success/failure + # by its truthiness/falsiness + ctx.exit() + except (EOFError, KeyboardInterrupt): + echo(file=sys.stderr) + raise Abort() from None + except ClickException as e: + if not standalone_mode: + raise + e.show() + sys.exit(e.exit_code) + except OSError as e: + if e.errno == errno.EPIPE: + sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) + sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) + sys.exit(1) + else: + raise + except Exit as e: + if standalone_mode: + sys.exit(e.exit_code) + else: + # in non-standalone mode, return the exit code + # note that this is only reached if `self.invoke` above raises + # an Exit explicitly -- thus bypassing the check there which + # would return its result + # the results of non-standalone execution may therefore be + # somewhat ambiguous: if there are codepaths which lead to + # `ctx.exit(1)` and to `return 1`, the caller won't be able to + # tell the difference between the two + return e.exit_code + except Abort: + if not standalone_mode: + raise + echo(_("Aborted!"), file=sys.stderr) + sys.exit(1) + + def _main_shell_completion( + self, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: t.Optional[str] = None, + ) -> None: + """Check if the shell is asking for tab completion, process + that, then exit early. Called from :meth:`main` before the + program is invoked. + + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. Defaults to + ``_{PROG_NAME}_COMPLETE``. + """ + if complete_var is None: + complete_var = f"_{prog_name}_COMPLETE".replace("-", "_").upper() + + instruction = os.environ.get(complete_var) + + if not instruction: + return + + from .shell_completion import shell_complete + + rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) + sys.exit(rv) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: + """Alias for :meth:`main`.""" + return self.main(*args, **kwargs) + + +class Command(BaseCommand): + """Commands are the basic building block of command line interfaces in + Click. A basic command handles command line parsing and might dispatch + more parsing to commands nested below it. + + :param name: the name of the command to use unless a group overrides it. + :param context_settings: an optional dictionary with defaults that are + passed to the context object. + :param callback: the callback to invoke. This is optional. + :param params: the parameters to register with this command. This can + be either :class:`Option` or :class:`Argument` objects. + :param help: the help string to use for this command. + :param epilog: like the help string but it's printed at the end of the + help page after everything else. + :param short_help: the short help to use for this command. This is + shown on the command listing of the parent command. + :param add_help_option: by default each command registers a ``--help`` + option. This can be disabled by this parameter. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is disabled by default. + If enabled this will add ``--help`` as argument + if no arguments are passed + :param hidden: hide this command from help outputs. + + :param deprecated: issues a message indicating that + the command is deprecated. + + .. versionchanged:: 8.1 + ``help``, ``epilog``, and ``short_help`` are stored unprocessed, + all formatting is done when outputting help text, not at init, + and is done even if not using the ``@command`` decorator. + + .. versionchanged:: 8.0 + Added a ``repr`` showing the command name. + + .. versionchanged:: 7.1 + Added the ``no_args_is_help`` parameter. + + .. versionchanged:: 2.0 + Added the ``context_settings`` parameter. + """ + + def __init__( + self, + name: t.Optional[str], + context_settings: t.Optional[t.Dict[str, t.Any]] = None, + callback: t.Optional[t.Callable[..., t.Any]] = None, + params: t.Optional[t.List["Parameter"]] = None, + help: t.Optional[str] = None, + epilog: t.Optional[str] = None, + short_help: t.Optional[str] = None, + options_metavar: t.Optional[str] = "[OPTIONS]", + add_help_option: bool = True, + no_args_is_help: bool = False, + hidden: bool = False, + deprecated: bool = False, + ) -> None: + super().__init__(name, context_settings) + #: the callback to execute when the command fires. This might be + #: `None` in which case nothing happens. + self.callback = callback + #: the list of parameters for this command in the order they + #: should show up in the help page and execute. Eager parameters + #: will automatically be handled before non eager ones. + self.params: t.List["Parameter"] = params or [] + self.help = help + self.epilog = epilog + self.options_metavar = options_metavar + self.short_help = short_help + self.add_help_option = add_help_option + self.no_args_is_help = no_args_is_help + self.hidden = hidden + self.deprecated = deprecated + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + info_dict.update( + params=[param.to_info_dict() for param in self.get_params(ctx)], + help=self.help, + epilog=self.epilog, + short_help=self.short_help, + hidden=self.hidden, + deprecated=self.deprecated, + ) + return info_dict + + def get_usage(self, ctx: Context) -> str: + """Formats the usage line into a string and returns it. + + Calls :meth:`format_usage` internally. + """ + formatter = ctx.make_formatter() + self.format_usage(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_params(self, ctx: Context) -> t.List["Parameter"]: + rv = self.params + help_option = self.get_help_option(ctx) + + if help_option is not None: + rv = [*rv, help_option] + + return rv + + def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the usage line into the formatter. + + This is a low-level method called by :meth:`get_usage`. + """ + pieces = self.collect_usage_pieces(ctx) + formatter.write_usage(ctx.command_path, " ".join(pieces)) + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + """Returns all the pieces that go into the usage line and returns + it as a list of strings. + """ + rv = [self.options_metavar] if self.options_metavar else [] + + for param in self.get_params(ctx): + rv.extend(param.get_usage_pieces(ctx)) + + return rv + + def get_help_option_names(self, ctx: Context) -> t.List[str]: + """Returns the names for the help option.""" + all_names = set(ctx.help_option_names) + for param in self.params: + all_names.difference_update(param.opts) + all_names.difference_update(param.secondary_opts) + return list(all_names) + + def get_help_option(self, ctx: Context) -> t.Optional["Option"]: + """Returns the help option object.""" + help_options = self.get_help_option_names(ctx) + + if not help_options or not self.add_help_option: + return None + + def show_help(ctx: Context, param: "Parameter", value: str) -> None: + if value and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + return Option( + help_options, + is_flag=True, + is_eager=True, + expose_value=False, + callback=show_help, + help=_("Show this message and exit."), + ) + + def make_parser(self, ctx: Context) -> OptionParser: + """Creates the underlying option parser for this command.""" + parser = OptionParser(ctx) + for param in self.get_params(ctx): + param.add_to_parser(parser, ctx) + return parser + + def get_help(self, ctx: Context) -> str: + """Formats the help into a string and returns it. + + Calls :meth:`format_help` internally. + """ + formatter = ctx.make_formatter() + self.format_help(ctx, formatter) + return formatter.getvalue().rstrip("\n") + + def get_short_help_str(self, limit: int = 45) -> str: + """Gets short help for the command or makes it by shortening the + long help string. + """ + if self.short_help: + text = inspect.cleandoc(self.short_help) + elif self.help: + text = make_default_short_help(self.help, limit) + else: + text = "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + return text.strip() + + def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help into the formatter if it exists. + + This is a low-level method called by :meth:`get_help`. + + This calls the following methods: + + - :meth:`format_usage` + - :meth:`format_help_text` + - :meth:`format_options` + - :meth:`format_epilog` + """ + self.format_usage(ctx, formatter) + self.format_help_text(ctx, formatter) + self.format_options(ctx, formatter) + self.format_epilog(ctx, formatter) + + def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the help text to the formatter if it exists.""" + text = self.help if self.help is not None else "" + + if self.deprecated: + text = _("(Deprecated) {text}").format(text=text) + + if text: + text = inspect.cleandoc(text).partition("\f")[0] + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(text) + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes all the options into the formatter if they exist.""" + opts = [] + for param in self.get_params(ctx): + rv = param.get_help_record(ctx) + if rv is not None: + opts.append(rv) + + if opts: + with formatter.section(_("Options")): + formatter.write_dl(opts) + + def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: + """Writes the epilog into the formatter if it exists.""" + if self.epilog: + epilog = inspect.cleandoc(self.epilog) + formatter.write_paragraph() + + with formatter.indentation(): + formatter.write_text(epilog) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + parser = self.make_parser(ctx) + opts, args, param_order = parser.parse_args(args=args) + + for param in iter_params_for_processing(param_order, self.get_params(ctx)): + value, args = param.handle_parse_result(ctx, opts, args) + + if args and not ctx.allow_extra_args and not ctx.resilient_parsing: + ctx.fail( + ngettext( + "Got unexpected extra argument ({args})", + "Got unexpected extra arguments ({args})", + len(args), + ).format(args=" ".join(map(str, args))) + ) + + ctx.args = args + ctx._opt_prefixes.update(parser._opt_prefixes) + return args + + def invoke(self, ctx: Context) -> t.Any: + """Given a context, this invokes the attached callback (if it exists) + in the right way. + """ + if self.deprecated: + message = _( + "DeprecationWarning: The command {name!r} is deprecated." + ).format(name=self.name) + echo(style(message, fg="red"), err=True) + + if self.callback is not None: + return ctx.invoke(self.callback, **ctx.params) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options and chained multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results: t.List["CompletionItem"] = [] + + if incomplete and not incomplete[0].isalnum(): + for param in self.get_params(ctx): + if ( + not isinstance(param, Option) + or param.hidden + or ( + not param.multiple + and ctx.get_parameter_source(param.name) # type: ignore + is ParameterSource.COMMANDLINE + ) + ): + continue + + results.extend( + CompletionItem(name, help=param.help) + for name in [*param.opts, *param.secondary_opts] + if name.startswith(incomplete) + ) + + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class MultiCommand(Command): + """A multi command is the basic implementation of a command that + dispatches to subcommands. The most common version is the + :class:`Group`. + + :param invoke_without_command: this controls how the multi command itself + is invoked. By default it's only invoked + if a subcommand is provided. + :param no_args_is_help: this controls what happens if no arguments are + provided. This option is enabled by default if + `invoke_without_command` is disabled or disabled + if it's enabled. If enabled this will add + ``--help`` as argument if no arguments are + passed. + :param subcommand_metavar: the string that is used in the documentation + to indicate the subcommand place. + :param chain: if this is set to `True` chaining of multiple subcommands + is enabled. This restricts the form of commands in that + they cannot have optional arguments but it allows + multiple commands to be chained together. + :param result_callback: The result callback to attach to this multi + command. This can be set or changed later with the + :meth:`result_callback` decorator. + """ + + allow_extra_args = True + allow_interspersed_args = False + + def __init__( + self, + name: t.Optional[str] = None, + invoke_without_command: bool = False, + no_args_is_help: t.Optional[bool] = None, + subcommand_metavar: t.Optional[str] = None, + chain: bool = False, + result_callback: t.Optional[t.Callable[..., t.Any]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if no_args_is_help is None: + no_args_is_help = not invoke_without_command + + self.no_args_is_help = no_args_is_help + self.invoke_without_command = invoke_without_command + + if subcommand_metavar is None: + if chain: + subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." + else: + subcommand_metavar = "COMMAND [ARGS]..." + + self.subcommand_metavar = subcommand_metavar + self.chain = chain + # The result callback that is stored. This can be set or + # overridden with the :func:`result_callback` decorator. + self._result_callback = result_callback + + if self.chain: + for param in self.params: + if isinstance(param, Argument) and not param.required: + raise RuntimeError( + "Multi commands in chain mode cannot have" + " optional arguments." + ) + + def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict(ctx) + commands = {} + + for name in self.list_commands(ctx): + command = self.get_command(ctx, name) + + if command is None: + continue + + sub_ctx = ctx._make_sub_context(command) + + with sub_ctx.scope(cleanup=False): + commands[name] = command.to_info_dict(sub_ctx) + + info_dict.update(commands=commands, chain=self.chain) + return info_dict + + def collect_usage_pieces(self, ctx: Context) -> t.List[str]: + rv = super().collect_usage_pieces(ctx) + rv.append(self.subcommand_metavar) + return rv + + def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: + super().format_options(ctx, formatter) + self.format_commands(ctx, formatter) + + def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: + """Adds a result callback to the command. By default if a + result callback is already registered this will chain them but + this can be disabled with the `replace` parameter. The result + callback is invoked with the return value of the subcommand + (or the list of return values from all subcommands if chaining + is enabled) as well as the parameters as they would be passed + to the main callback. + + Example:: + + @click.group() + @click.option('-i', '--input', default=23) + def cli(input): + return 42 + + @cli.result_callback() + def process_result(result, input): + return result + input + + :param replace: if set to `True` an already existing result + callback will be removed. + + .. versionchanged:: 8.0 + Renamed from ``resultcallback``. + + .. versionadded:: 3.0 + """ + + def decorator(f: F) -> F: + old_callback = self._result_callback + + if old_callback is None or replace: + self._result_callback = f + return f + + def function(__value, *args, **kwargs): # type: ignore + inner = old_callback(__value, *args, **kwargs) # type: ignore + return f(inner, *args, **kwargs) + + self._result_callback = rv = update_wrapper(t.cast(F, function), f) + return rv + + return decorator + + def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: + """Extra format methods for multi methods that adds all the commands + after the options. + """ + commands = [] + for subcommand in self.list_commands(ctx): + cmd = self.get_command(ctx, subcommand) + # What is this, the tool lied about a command. Ignore it + if cmd is None: + continue + if cmd.hidden: + continue + + commands.append((subcommand, cmd)) + + # allow for 3 times the default spacing + if len(commands): + limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) + + rows = [] + for subcommand, cmd in commands: + help = cmd.get_short_help_str(limit) + rows.append((subcommand, help)) + + if rows: + with formatter.section(_("Commands")): + formatter.write_dl(rows) + + def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: + if not args and self.no_args_is_help and not ctx.resilient_parsing: + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + rest = super().parse_args(ctx, args) + + if self.chain: + ctx.protected_args = rest + ctx.args = [] + elif rest: + ctx.protected_args, ctx.args = rest[:1], rest[1:] + + return ctx.args + + def invoke(self, ctx: Context) -> t.Any: + def _process_result(value: t.Any) -> t.Any: + if self._result_callback is not None: + value = ctx.invoke(self._result_callback, value, **ctx.params) + return value + + if not ctx.protected_args: + if self.invoke_without_command: + # No subcommand was invoked, so the result callback is + # invoked with the group return value for regular + # groups, or an empty list for chained groups. + with ctx: + rv = super().invoke(ctx) + return _process_result([] if self.chain else rv) + ctx.fail(_("Missing command.")) + + # Fetch args back out + args = [*ctx.protected_args, *ctx.args] + ctx.args = [] + ctx.protected_args = [] + + # If we're not in chain mode, we only allow the invocation of a + # single command but we also inform the current context about the + # name of the command to invoke. + if not self.chain: + # Make sure the context is entered so we do not clean up + # resources until the result processor has worked. + with ctx: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + ctx.invoked_subcommand = cmd_name + super().invoke(ctx) + sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) + with sub_ctx: + return _process_result(sub_ctx.command.invoke(sub_ctx)) + + # In chain mode we create the contexts step by step, but after the + # base command has been invoked. Because at that point we do not + # know the subcommands yet, the invoked subcommand attribute is + # set to ``*`` to inform the command that subcommands are executed + # but nothing else. + with ctx: + ctx.invoked_subcommand = "*" if args else None + super().invoke(ctx) + + # Otherwise we make every single context and invoke them in a + # chain. In that case the return value to the result processor + # is the list of all invoked subcommand's results. + contexts = [] + while args: + cmd_name, cmd, args = self.resolve_command(ctx, args) + assert cmd is not None + sub_ctx = cmd.make_context( + cmd_name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + ) + contexts.append(sub_ctx) + args, sub_ctx.args = sub_ctx.args, [] + + rv = [] + for sub_ctx in contexts: + with sub_ctx: + rv.append(sub_ctx.command.invoke(sub_ctx)) + return _process_result(rv) + + def resolve_command( + self, ctx: Context, args: t.List[str] + ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: + cmd_name = make_str(args[0]) + original_cmd_name = cmd_name + + # Get the command + cmd = self.get_command(ctx, cmd_name) + + # If we can't find the command but there is a normalization + # function available, we try with that one. + if cmd is None and ctx.token_normalize_func is not None: + cmd_name = ctx.token_normalize_func(cmd_name) + cmd = self.get_command(ctx, cmd_name) + + # If we don't find the command we want to show an error message + # to the user that it was not provided. However, there is + # something else we should do: if the first argument looks like + # an option we want to kick off parsing again for arguments to + # resolve things like --help which now should go to the main + # place. + if cmd is None and not ctx.resilient_parsing: + if split_opt(cmd_name)[0]: + self.parse_args(ctx, ctx.args) + ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) + return cmd_name if cmd else None, cmd, args[1:] + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + """Given a context and a command name, this returns a + :class:`Command` object if it exists or returns `None`. + """ + raise NotImplementedError + + def list_commands(self, ctx: Context) -> t.List[str]: + """Returns a list of subcommand names in the order they should + appear. + """ + return [] + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. Looks + at the names of options, subcommands, and chained + multi-commands. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + results = [ + CompletionItem(name, help=command.get_short_help_str()) + for name, command in _complete_visible_commands(ctx, incomplete) + ] + results.extend(super().shell_complete(ctx, incomplete)) + return results + + +class Group(MultiCommand): + """A group allows a command to have subcommands attached. This is + the most common way to implement nesting in Click. + + :param name: The name of the group command. + :param commands: A dict mapping names to :class:`Command` objects. + Can also be a list of :class:`Command`, which will use + :attr:`Command.name` to create the dict. + :param attrs: Other command arguments described in + :class:`MultiCommand`, :class:`Command`, and + :class:`BaseCommand`. + + .. versionchanged:: 8.0 + The ``commmands`` argument can be a list of command objects. + """ + + #: If set, this is used by the group's :meth:`command` decorator + #: as the default :class:`Command` class. This is useful to make all + #: subcommands use a custom command class. + #: + #: .. versionadded:: 8.0 + command_class: t.Optional[t.Type[Command]] = None + + #: If set, this is used by the group's :meth:`group` decorator + #: as the default :class:`Group` class. This is useful to make all + #: subgroups use a custom group class. + #: + #: If set to the special value :class:`type` (literally + #: ``group_class = type``), this group's class will be used as the + #: default class. This makes a custom group class continue to make + #: custom groups. + #: + #: .. versionadded:: 8.0 + group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None + # Literal[type] isn't valid, so use Type[type] + + def __init__( + self, + name: t.Optional[str] = None, + commands: t.Optional[t.Union[t.Dict[str, Command], t.Sequence[Command]]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + + if commands is None: + commands = {} + elif isinstance(commands, abc.Sequence): + commands = {c.name: c for c in commands if c.name is not None} + + #: The registered subcommands by their exported names. + self.commands: t.Dict[str, Command] = commands + + def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: + """Registers another :class:`Command` with this group. If the name + is not provided, the name of the command is used. + """ + name = name or cmd.name + if name is None: + raise TypeError("Command has no name.") + _check_multicommand(self, name, cmd, register=True) + self.commands[name] = cmd + + @t.overload + def command(self, __func: t.Callable[..., t.Any]) -> Command: + ... + + @t.overload + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], Command]: + ... + + def command( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: + """A shortcut decorator for declaring and attaching a command to + the group. This takes the same arguments as :func:`command` and + immediately registers the created command with this group by + calling :meth:`add_command`. + + To customize the command class used, set the + :attr:`command_class` attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`command_class` attribute. + """ + from .decorators import command + + if self.command_class and kwargs.get("cls") is None: + kwargs["cls"] = self.command_class + + func: t.Optional[t.Callable] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'command(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + def decorator(f: t.Callable[..., t.Any]) -> Command: + cmd: Command = command(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + @t.overload + def group(self, __func: t.Callable[..., t.Any]) -> "Group": + ... + + @t.overload + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: + ... + + def group( + self, *args: t.Any, **kwargs: t.Any + ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: + """A shortcut decorator for declaring and attaching a group to + the group. This takes the same arguments as :func:`group` and + immediately registers the created group with this group by + calling :meth:`add_command`. + + To customize the group class used, set the :attr:`group_class` + attribute. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.0 + Added the :attr:`group_class` attribute. + """ + from .decorators import group + + func: t.Optional[t.Callable] = None + + if args and callable(args[0]): + assert ( + len(args) == 1 and not kwargs + ), "Use 'group(**kwargs)(callable)' to provide arguments." + (func,) = args + args = () + + if self.group_class is not None and kwargs.get("cls") is None: + if self.group_class is type: + kwargs["cls"] = type(self) + else: + kwargs["cls"] = self.group_class + + def decorator(f: t.Callable[..., t.Any]) -> "Group": + cmd: Group = group(*args, **kwargs)(f) + self.add_command(cmd) + return cmd + + if func is not None: + return decorator(func) + + return decorator + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + return self.commands.get(cmd_name) + + def list_commands(self, ctx: Context) -> t.List[str]: + return sorted(self.commands) + + +class CommandCollection(MultiCommand): + """A command collection is a multi command that merges multiple multi + commands together into one. This is a straightforward implementation + that accepts a list of different multi commands as sources and + provides all the commands for each of them. + """ + + def __init__( + self, + name: t.Optional[str] = None, + sources: t.Optional[t.List[MultiCommand]] = None, + **attrs: t.Any, + ) -> None: + super().__init__(name, **attrs) + #: The list of registered multi commands. + self.sources: t.List[MultiCommand] = sources or [] + + def add_source(self, multi_cmd: MultiCommand) -> None: + """Adds a new multi command to the chain dispatcher.""" + self.sources.append(multi_cmd) + + def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: + for source in self.sources: + rv = source.get_command(ctx, cmd_name) + + if rv is not None: + if self.chain: + _check_multicommand(self, cmd_name, rv) + + return rv + + return None + + def list_commands(self, ctx: Context) -> t.List[str]: + rv: t.Set[str] = set() + + for source in self.sources: + rv.update(source.list_commands(ctx)) + + return sorted(rv) + + +def _check_iter(value: t.Any) -> t.Iterator[t.Any]: + """Check if the value is iterable but not a string. Raises a type + error, or return an iterator over the value. + """ + if isinstance(value, str): + raise TypeError + + return iter(value) + + +class Parameter: + r"""A parameter to a command comes in two versions: they are either + :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently + not supported by design as some of the internals for parsing are + intentionally not finalized. + + Some settings are supported by both options and arguments. + + :param param_decls: the parameter declarations for this option or + argument. This is a list of flags or argument + names. + :param type: the type that should be used. Either a :class:`ParamType` + or a Python type. The later is converted into the former + automatically if supported. + :param required: controls if this is optional or not. + :param default: the default value if omitted. This can also be a callable, + in which case it's invoked when the default is needed + without any arguments. + :param callback: A function to further process or validate the value + after type conversion. It is called as ``f(ctx, param, value)`` + and must return the value. It is called for all sources, + including prompts. + :param nargs: the number of arguments to match. If not ``1`` the return + value is a tuple instead of single value. The default for + nargs is ``1`` (except if the type is a tuple, then it's + the arity of the tuple). If ``nargs=-1``, all remaining + parameters are collected. + :param metavar: how the value is represented in the help page. + :param expose_value: if this is `True` then the value is passed onwards + to the command callback and stored on the context, + otherwise it's skipped. + :param is_eager: eager values are processed before non eager ones. This + should not be set for arguments or it will inverse the + order of processing. + :param envvar: a string or list of strings that are environment variables + that should be checked. + :param shell_complete: A function that returns custom shell + completions. Used instead of the param's type completion if + given. Takes ``ctx, param, incomplete`` and must return a list + of :class:`~click.shell_completion.CompletionItem` or a list of + strings. + + .. versionchanged:: 8.0 + ``process_value`` validates required parameters and bounded + ``nargs``, and invokes the parameter callback before returning + the value. This allows the callback to validate prompts. + ``full_process_value`` is removed. + + .. versionchanged:: 8.0 + ``autocompletion`` is renamed to ``shell_complete`` and has new + semantics described above. The old name is deprecated and will + be removed in 8.1, until then it will be wrapped to match the + new requirements. + + .. versionchanged:: 8.0 + For ``multiple=True, nargs>1``, the default must be a list of + tuples. + + .. versionchanged:: 8.0 + Setting a default is no longer required for ``nargs>1``, it will + default to ``None``. ``multiple=True`` or ``nargs=-1`` will + default to ``()``. + + .. versionchanged:: 7.1 + Empty environment variables are ignored rather than taking the + empty string value. This makes it possible for scripts to clear + variables if they can't unset them. + + .. versionchanged:: 2.0 + Changed signature for parameter callback to also be passed the + parameter. The old callback format will still work, but it will + raise a warning to give you a chance to migrate the code easier. + """ + + param_type_name = "parameter" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + required: bool = False, + default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, + callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, + nargs: t.Optional[int] = None, + multiple: bool = False, + metavar: t.Optional[str] = None, + expose_value: bool = True, + is_eager: bool = False, + envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, + shell_complete: t.Optional[ + t.Callable[ + [Context, "Parameter", str], + t.Union[t.List["CompletionItem"], t.List[str]], + ] + ] = None, + ) -> None: + self.name, self.opts, self.secondary_opts = self._parse_decls( + param_decls or (), expose_value + ) + self.type = types.convert_type(type, default) + + # Default nargs to what the type tells us if we have that + # information available. + if nargs is None: + if self.type.is_composite: + nargs = self.type.arity + else: + nargs = 1 + + self.required = required + self.callback = callback + self.nargs = nargs + self.multiple = multiple + self.expose_value = expose_value + self.default = default + self.is_eager = is_eager + self.metavar = metavar + self.envvar = envvar + self._custom_shell_complete = shell_complete + + if __debug__: + if self.type.is_composite and nargs != self.type.arity: + raise ValueError( + f"'nargs' must be {self.type.arity} (or None) for" + f" type {self.type!r}, but it was {nargs}." + ) + + # Skip no default or callable default. + check_default = default if not callable(default) else None + + if check_default is not None: + if multiple: + try: + # Only check the first value against nargs. + check_default = next(_check_iter(check_default), None) + except TypeError: + raise ValueError( + "'default' must be a list when 'multiple' is true." + ) from None + + # Can be None for multiple with empty default. + if nargs != 1 and check_default is not None: + try: + _check_iter(check_default) + except TypeError: + if multiple: + message = ( + "'default' must be a list of lists when 'multiple' is" + " true and 'nargs' != 1." + ) + else: + message = "'default' must be a list when 'nargs' != 1." + + raise ValueError(message) from None + + if nargs > 1 and len(check_default) != nargs: + subject = "item length" if multiple else "length" + raise ValueError( + f"'default' {subject} must match nargs={nargs}." + ) + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + return { + "name": self.name, + "param_type_name": self.param_type_name, + "opts": self.opts, + "secondary_opts": self.secondary_opts, + "type": self.type.to_info_dict(), + "required": self.required, + "nargs": self.nargs, + "multiple": self.multiple, + "default": self.default, + "envvar": self.envvar, + } + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.name}>" + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + raise NotImplementedError() + + @property + def human_readable_name(self) -> str: + """Returns the human readable name of this parameter. This is the + same as the name for options, but the metavar for arguments. + """ + return self.name # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + + metavar = self.type.get_metavar(self) + + if metavar is None: + metavar = self.type.name.upper() + + if self.nargs != 1: + metavar += "..." + + return metavar + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + """Get the default for the parameter. Tries + :meth:`Context.lookup_default` first, then the local default. + + :param ctx: Current context. + :param call: If the default is a callable, call it. Disable to + return the callable instead. + + .. versionchanged:: 8.0.2 + Type casting is no longer performed when getting a default. + + .. versionchanged:: 8.0.1 + Type casting can fail in resilient parsing mode. Invalid + defaults will not prevent showing help text. + + .. versionchanged:: 8.0 + Looks at ``ctx.default_map`` first. + + .. versionchanged:: 8.0 + Added the ``call`` parameter. + """ + value = ctx.lookup_default(self.name, call=False) # type: ignore + + if value is None: + value = self.default + + if call and callable(value): + value = value() + + return value + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + raise NotImplementedError() + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, t.Any] + ) -> t.Tuple[t.Any, ParameterSource]: + value = opts.get(self.name) # type: ignore + source = ParameterSource.COMMANDLINE + + if value is None: + value = self.value_from_envvar(ctx) + source = ParameterSource.ENVIRONMENT + + if value is None: + value = ctx.lookup_default(self.name) # type: ignore + source = ParameterSource.DEFAULT_MAP + + if value is None: + value = self.get_default(ctx) + source = ParameterSource.DEFAULT + + return value, source + + def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: + """Convert and validate a value against the option's + :attr:`type`, :attr:`multiple`, and :attr:`nargs`. + """ + if value is None: + return () if self.multiple or self.nargs == -1 else None + + def check_iter(value: t.Any) -> t.Iterator: + try: + return _check_iter(value) + except TypeError: + # This should only happen when passing in args manually, + # the parser should construct an iterable when parsing + # the command line. + raise BadParameter( + _("Value must be an iterable."), ctx=ctx, param=self + ) from None + + if self.nargs == 1 or self.type.is_composite: + convert: t.Callable[[t.Any], t.Any] = partial( + self.type, param=self, ctx=ctx + ) + elif self.nargs == -1: + + def convert(value: t.Any) -> t.Tuple: + return tuple(self.type(x, self, ctx) for x in check_iter(value)) + + else: # nargs > 1 + + def convert(value: t.Any) -> t.Tuple: + value = tuple(check_iter(value)) + + if len(value) != self.nargs: + raise BadParameter( + ngettext( + "Takes {nargs} values but 1 was given.", + "Takes {nargs} values but {len} were given.", + len(value), + ).format(nargs=self.nargs, len=len(value)), + ctx=ctx, + param=self, + ) + + return tuple(self.type(x, self, ctx) for x in value) + + if self.multiple: + return tuple(convert(x) for x in check_iter(value)) + + return convert(value) + + def value_is_missing(self, value: t.Any) -> bool: + if value is None: + return True + + if (self.nargs != 1 or self.multiple) and value == (): + return True + + return False + + def process_value(self, ctx: Context, value: t.Any) -> t.Any: + value = self.type_cast_value(ctx, value) + + if self.required and self.value_is_missing(value): + raise MissingParameter(ctx=ctx, param=self) + + if self.callback is not None: + value = self.callback(ctx, self, value) + + return value + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + if self.envvar is None: + return None + + if isinstance(self.envvar, str): + rv = os.environ.get(self.envvar) + + if rv: + return rv + else: + for envvar in self.envvar: + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is not None and self.nargs != 1: + rv = self.type.split_envvar_value(rv) + + return rv + + def handle_parse_result( + self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] + ) -> t.Tuple[t.Any, t.List[str]]: + with augment_usage_errors(ctx, param=self): + value, source = self.consume_value(ctx, opts) + ctx.set_parameter_source(self.name, source) # type: ignore + + try: + value = self.process_value(ctx, value) + except Exception: + if not ctx.resilient_parsing: + raise + + value = None + + if self.expose_value: + ctx.params[self.name] = value # type: ignore + + return value, args + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + pass + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [] + + def get_error_hint(self, ctx: Context) -> str: + """Get a stringified version of the param for use in error messages to + indicate which param caused the error. + """ + hint_list = self.opts or [self.human_readable_name] + return " / ".join(f"'{x}'" for x in hint_list) + + def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: + """Return a list of completions for the incomplete value. If a + ``shell_complete`` function was given during init, it is used. + Otherwise, the :attr:`type` + :meth:`~click.types.ParamType.shell_complete` function is used. + + :param ctx: Invocation context for this command. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + if self._custom_shell_complete is not None: + results = self._custom_shell_complete(ctx, self, incomplete) + + if results and isinstance(results[0], str): + from click.shell_completion import CompletionItem + + results = [CompletionItem(c) for c in results] + + return t.cast(t.List["CompletionItem"], results) + + return self.type.shell_complete(ctx, self, incomplete) + + +class Option(Parameter): + """Options are usually optional values on the command line and + have some extra features that arguments don't have. + + All other parameters are passed onwards to the parameter constructor. + + :param show_default: Show the default value for this option in its + help text. Values are not shown by default, unless + :attr:`Context.show_default` is ``True``. If this value is a + string, it shows that string in parentheses instead of the + actual value. This is particularly useful for dynamic options. + For single option boolean flags, the default remains hidden if + its value is ``False``. + :param show_envvar: Controls if an environment variable should be + shown on the help page. Normally, environment variables are not + shown. + :param prompt: If set to ``True`` or a non empty string then the + user will be prompted for input. If set to ``True`` the prompt + will be the option name capitalized. + :param confirmation_prompt: Prompt a second time to confirm the + value if it was prompted for. Can be set to a string instead of + ``True`` to customize the message. + :param prompt_required: If set to ``False``, the user will be + prompted for input only when the option was specified as a flag + without a value. + :param hide_input: If this is ``True`` then the input on the prompt + will be hidden from the user. This is useful for password input. + :param is_flag: forces this option to act as a flag. The default is + auto detection. + :param flag_value: which value should be used for this flag if it's + enabled. This is set to a boolean automatically if + the option string contains a slash to mark two options. + :param multiple: if this is set to `True` then the argument is accepted + multiple times and recorded. This is similar to ``nargs`` + in how it works but supports arbitrary number of + arguments. + :param count: this flag makes an option increment an integer. + :param allow_from_autoenv: if this is enabled then the value of this + parameter will be pulled from an environment + variable in case a prefix is defined on the + context. + :param help: the help string. + :param hidden: hide this option from help outputs. + + .. versionchanged:: 8.1.0 + Help text indentation is cleaned here instead of only in the + ``@option`` decorator. + + .. versionchanged:: 8.1.0 + The ``show_default`` parameter overrides + ``Context.show_default``. + + .. versionchanged:: 8.1.0 + The default of a single option boolean flag is not shown if the + default value is ``False``. + + .. versionchanged:: 8.0.1 + ``type`` is detected from ``flag_value`` if given. + """ + + param_type_name = "option" + + def __init__( + self, + param_decls: t.Optional[t.Sequence[str]] = None, + show_default: t.Union[bool, str, None] = None, + prompt: t.Union[bool, str] = False, + confirmation_prompt: t.Union[bool, str] = False, + prompt_required: bool = True, + hide_input: bool = False, + is_flag: t.Optional[bool] = None, + flag_value: t.Optional[t.Any] = None, + multiple: bool = False, + count: bool = False, + allow_from_autoenv: bool = True, + type: t.Optional[t.Union[types.ParamType, t.Any]] = None, + help: t.Optional[str] = None, + hidden: bool = False, + show_choices: bool = True, + show_envvar: bool = False, + **attrs: t.Any, + ) -> None: + if help: + help = inspect.cleandoc(help) + + default_is_missing = "default" not in attrs + super().__init__(param_decls, type=type, multiple=multiple, **attrs) + + if prompt is True: + if self.name is None: + raise TypeError("'name' is required with 'prompt=True'.") + + prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() + elif prompt is False: + prompt_text = None + else: + prompt_text = prompt + + self.prompt = prompt_text + self.confirmation_prompt = confirmation_prompt + self.prompt_required = prompt_required + self.hide_input = hide_input + self.hidden = hidden + + # If prompt is enabled but not required, then the option can be + # used as a flag to indicate using prompt or flag_value. + self._flag_needs_value = self.prompt is not None and not self.prompt_required + + if is_flag is None: + if flag_value is not None: + # Implicitly a flag because flag_value was set. + is_flag = True + elif self._flag_needs_value: + # Not a flag, but when used as a flag it shows a prompt. + is_flag = False + else: + # Implicitly a flag because flag options were given. + is_flag = bool(self.secondary_opts) + elif is_flag is False and not self._flag_needs_value: + # Not a flag, and prompt is not enabled, can be used as a + # flag if flag_value is set. + self._flag_needs_value = flag_value is not None + + if is_flag and default_is_missing and not self.required: + self.default: t.Union[t.Any, t.Callable[[], t.Any]] = False + + if flag_value is None: + flag_value = not self.default + + if is_flag and type is None: + # Re-guess the type from the flag value instead of the + # default. + self.type = types.convert_type(None, flag_value) + + self.is_flag: bool = is_flag + self.is_bool_flag = is_flag and isinstance(self.type, types.BoolParamType) + self.flag_value: t.Any = flag_value + + # Counting + self.count = count + if count: + if type is None: + self.type = types.IntRange(min=0) + if default_is_missing: + self.default = 0 + + self.allow_from_autoenv = allow_from_autoenv + self.help = help + self.show_default = show_default + self.show_choices = show_choices + self.show_envvar = show_envvar + + if __debug__: + if self.nargs == -1: + raise TypeError("nargs=-1 is not supported for options.") + + if self.prompt and self.is_flag and not self.is_bool_flag: + raise TypeError("'prompt' is not valid for non-boolean flag.") + + if not self.is_bool_flag and self.secondary_opts: + raise TypeError("Secondary flag is not valid for non-boolean flag.") + + if self.is_bool_flag and self.hide_input and self.prompt is not None: + raise TypeError( + "'prompt' with 'hide_input' is not valid for boolean flag." + ) + + if self.count: + if self.multiple: + raise TypeError("'count' is not valid with 'multiple'.") + + if self.is_flag: + raise TypeError("'count' is not valid with 'is_flag'.") + + if self.multiple and self.is_flag: + raise TypeError("'multiple' is not valid with 'is_flag', use 'count'.") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + help=self.help, + prompt=self.prompt, + is_flag=self.is_flag, + flag_value=self.flag_value, + count=self.count, + hidden=self.hidden, + ) + return info_dict + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + opts = [] + secondary_opts = [] + name = None + possible_names = [] + + for decl in decls: + if decl.isidentifier(): + if name is not None: + raise TypeError(f"Name '{name}' defined twice") + name = decl + else: + split_char = ";" if decl[:1] == "/" else "/" + if split_char in decl: + first, second = decl.split(split_char, 1) + first = first.rstrip() + if first: + possible_names.append(split_opt(first)) + opts.append(first) + second = second.lstrip() + if second: + secondary_opts.append(second.lstrip()) + if first == second: + raise ValueError( + f"Boolean option {decl!r} cannot use the" + " same flag for true/false." + ) + else: + possible_names.append(split_opt(decl)) + opts.append(decl) + + if name is None and possible_names: + possible_names.sort(key=lambda x: -len(x[0])) # group long options first + name = possible_names[0][1].replace("-", "_").lower() + if not name.isidentifier(): + name = None + + if name is None: + if not expose_value: + return None, opts, secondary_opts + raise TypeError("Could not determine name for option") + + if not opts and not secondary_opts: + raise TypeError( + f"No options defined but a name was passed ({name})." + " Did you mean to declare an argument instead? Did" + f" you mean to pass '--{name}'?" + ) + + return name, opts, secondary_opts + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + if self.multiple: + action = "append" + elif self.count: + action = "count" + else: + action = "store" + + if self.is_flag: + action = f"{action}_const" + + if self.is_bool_flag and self.secondary_opts: + parser.add_option( + obj=self, opts=self.opts, dest=self.name, action=action, const=True + ) + parser.add_option( + obj=self, + opts=self.secondary_opts, + dest=self.name, + action=action, + const=False, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + const=self.flag_value, + ) + else: + parser.add_option( + obj=self, + opts=self.opts, + dest=self.name, + action=action, + nargs=self.nargs, + ) + + def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: + if self.hidden: + return None + + any_prefix_is_slash = False + + def _write_opts(opts: t.Sequence[str]) -> str: + nonlocal any_prefix_is_slash + + rv, any_slashes = join_options(opts) + + if any_slashes: + any_prefix_is_slash = True + + if not self.is_flag and not self.count: + rv += f" {self.make_metavar()}" + + return rv + + rv = [_write_opts(self.opts)] + + if self.secondary_opts: + rv.append(_write_opts(self.secondary_opts)) + + help = self.help or "" + extra = [] + + if self.show_envvar: + envvar = self.envvar + + if envvar is None: + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + + if envvar is not None: + var_str = ( + envvar + if isinstance(envvar, str) + else ", ".join(str(d) for d in envvar) + ) + extra.append(_("env var: {var}").format(var=var_str)) + + # Temporarily enable resilient parsing to avoid type casting + # failing for the default. Might be possible to extend this to + # help formatting in general. + resilient = ctx.resilient_parsing + ctx.resilient_parsing = True + + try: + default_value = self.get_default(ctx, call=False) + finally: + ctx.resilient_parsing = resilient + + show_default = False + show_default_is_str = False + + if self.show_default is not None: + if isinstance(self.show_default, str): + show_default_is_str = show_default = True + else: + show_default = self.show_default + elif ctx.show_default is not None: + show_default = ctx.show_default + + if show_default_is_str or (show_default and (default_value is not None)): + if show_default_is_str: + default_string = f"({self.show_default})" + elif isinstance(default_value, (list, tuple)): + default_string = ", ".join(str(d) for d in default_value) + elif inspect.isfunction(default_value): + default_string = _("(dynamic)") + elif self.is_bool_flag and self.secondary_opts: + # For boolean flags that have distinct True/False opts, + # use the opt without prefix instead of the value. + default_string = split_opt( + (self.opts if self.default else self.secondary_opts)[0] + )[1] + elif self.is_bool_flag and not self.secondary_opts and not default_value: + default_string = "" + else: + default_string = str(default_value) + + if default_string: + extra.append(_("default: {default}").format(default=default_string)) + + if ( + isinstance(self.type, types._NumberRangeBase) + # skip count with default range type + and not (self.count and self.type.min == 0 and self.type.max is None) + ): + range_str = self.type._describe_range() + + if range_str: + extra.append(range_str) + + if self.required: + extra.append(_("required")) + + if extra: + extra_str = "; ".join(extra) + help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" + + return ("; " if any_prefix_is_slash else " / ").join(rv), help + + @t.overload + def get_default( + self, ctx: Context, call: "te.Literal[True]" = True + ) -> t.Optional[t.Any]: + ... + + @t.overload + def get_default( + self, ctx: Context, call: bool = ... + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + ... + + def get_default( + self, ctx: Context, call: bool = True + ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: + # If we're a non boolean flag our default is more complex because + # we need to look at all flags in the same group to figure out + # if we're the default one in which case we return the flag + # value as default. + if self.is_flag and not self.is_bool_flag: + for param in ctx.command.params: + if param.name == self.name and param.default: + return param.flag_value # type: ignore + + return None + + return super().get_default(ctx, call=call) + + def prompt_for_value(self, ctx: Context) -> t.Any: + """This is an alternative flow that can be activated in the full + value processing if a value does not exist. It will prompt the + user until a valid value exists and then returns the processed + value as result. + """ + assert self.prompt is not None + + # Calculate the default before prompting anything to be stable. + default = self.get_default(ctx) + + # If this is a prompt for a flag we need to handle this + # differently. + if self.is_bool_flag: + return confirm(self.prompt, default) + + return prompt( + self.prompt, + default=default, + type=self.type, + hide_input=self.hide_input, + show_choices=self.show_choices, + confirmation_prompt=self.confirmation_prompt, + value_proc=lambda x: self.process_value(ctx, x), + ) + + def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: + rv = super().resolve_envvar_value(ctx) + + if rv is not None: + return rv + + if ( + self.allow_from_autoenv + and ctx.auto_envvar_prefix is not None + and self.name is not None + ): + envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" + rv = os.environ.get(envvar) + + if rv: + return rv + + return None + + def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: + rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) + + if rv is None: + return None + + value_depth = (self.nargs != 1) + bool(self.multiple) + + if value_depth > 0: + rv = self.type.split_envvar_value(rv) + + if self.multiple and self.nargs != 1: + rv = batch(rv, self.nargs) + + return rv + + def consume_value( + self, ctx: Context, opts: t.Mapping[str, "Parameter"] + ) -> t.Tuple[t.Any, ParameterSource]: + value, source = super().consume_value(ctx, opts) + + # The parser will emit a sentinel value if the option can be + # given as a flag without a value. This is different from None + # to distinguish from the flag not being given at all. + if value is _flag_needs_value: + if self.prompt is not None and not ctx.resilient_parsing: + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + else: + value = self.flag_value + source = ParameterSource.COMMANDLINE + + elif ( + self.multiple + and value is not None + and any(v is _flag_needs_value for v in value) + ): + value = [self.flag_value if v is _flag_needs_value else v for v in value] + source = ParameterSource.COMMANDLINE + + # The value wasn't set, or used the param's default, prompt if + # prompting is enabled. + elif ( + source in {None, ParameterSource.DEFAULT} + and self.prompt is not None + and (self.required or self.prompt_required) + and not ctx.resilient_parsing + ): + value = self.prompt_for_value(ctx) + source = ParameterSource.PROMPT + + return value, source + + +class Argument(Parameter): + """Arguments are positional parameters to a command. They generally + provide fewer features than options but can have infinite ``nargs`` + and are required by default. + + All parameters are passed onwards to the parameter constructor. + """ + + param_type_name = "argument" + + def __init__( + self, + param_decls: t.Sequence[str], + required: t.Optional[bool] = None, + **attrs: t.Any, + ) -> None: + if required is None: + if attrs.get("default") is not None: + required = False + else: + required = attrs.get("nargs", 1) > 0 + + if "multiple" in attrs: + raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") + + super().__init__(param_decls, required=required, **attrs) + + if __debug__: + if self.default is not None and self.nargs == -1: + raise TypeError("'default' is not supported for nargs=-1.") + + @property + def human_readable_name(self) -> str: + if self.metavar is not None: + return self.metavar + return self.name.upper() # type: ignore + + def make_metavar(self) -> str: + if self.metavar is not None: + return self.metavar + var = self.type.get_metavar(self) + if not var: + var = self.name.upper() # type: ignore + if not self.required: + var = f"[{var}]" + if self.nargs != 1: + var += "..." + return var + + def _parse_decls( + self, decls: t.Sequence[str], expose_value: bool + ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: + if not decls: + if not expose_value: + return None, [], [] + raise TypeError("Could not determine name for argument") + if len(decls) == 1: + name = arg = decls[0] + name = name.replace("-", "_").lower() + else: + raise TypeError( + "Arguments take exactly one parameter declaration, got" + f" {len(decls)}." + ) + return name, [arg], [] + + def get_usage_pieces(self, ctx: Context) -> t.List[str]: + return [self.make_metavar()] + + def get_error_hint(self, ctx: Context) -> str: + return f"'{self.make_metavar()}'" + + def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: + parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/decorators.py b/flask-server/venv/lib/python3.10/site-packages/click/decorators.py new file mode 100644 index 00000000..28618dc5 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/decorators.py @@ -0,0 +1,497 @@ +import inspect +import types +import typing as t +from functools import update_wrapper +from gettext import gettext as _ + +from .core import Argument +from .core import Command +from .core import Context +from .core import Group +from .core import Option +from .core import Parameter +from .globals import get_current_context +from .utils import echo + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) +FC = t.TypeVar("FC", bound=t.Union[t.Callable[..., t.Any], Command]) + + +def pass_context(f: F) -> F: + """Marks a callback as wanting to receive the current context + object as first argument. + """ + + def new_func(*args, **kwargs): # type: ignore + return f(get_current_context(), *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def pass_obj(f: F) -> F: + """Similar to :func:`pass_context`, but only pass the object on the + context onwards (:attr:`Context.obj`). This is useful if that object + represents the state of a nested system. + """ + + def new_func(*args, **kwargs): # type: ignore + return f(get_current_context().obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + +def make_pass_decorator( + object_type: t.Type, ensure: bool = False +) -> "t.Callable[[F], F]": + """Given an object type this creates a decorator that will work + similar to :func:`pass_obj` but instead of passing the object of the + current context, it will find the innermost context of type + :func:`object_type`. + + This generates a decorator that works roughly like this:: + + from functools import update_wrapper + + def decorator(f): + @pass_context + def new_func(ctx, *args, **kwargs): + obj = ctx.find_object(object_type) + return ctx.invoke(f, obj, *args, **kwargs) + return update_wrapper(new_func, f) + return decorator + + :param object_type: the type of the object to pass. + :param ensure: if set to `True`, a new object will be created and + remembered on the context if it's not there yet. + """ + + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + + if ensure: + obj = ctx.ensure_object(object_type) + else: + obj = ctx.find_object(object_type) + + if obj is None: + raise RuntimeError( + "Managed to invoke callback without a context" + f" object of type {object_type.__name__!r}" + " existing." + ) + + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + return decorator + + +def pass_meta_key( + key: str, *, doc_description: t.Optional[str] = None +) -> "t.Callable[[F], F]": + """Create a decorator that passes a key from + :attr:`click.Context.meta` as the first argument to the decorated + function. + + :param key: Key in ``Context.meta`` to pass. + :param doc_description: Description of the object being passed, + inserted into the decorator's docstring. Defaults to "the 'key' + key from Context.meta". + + .. versionadded:: 8.0 + """ + + def decorator(f: F) -> F: + def new_func(*args, **kwargs): # type: ignore + ctx = get_current_context() + obj = ctx.meta[key] + return ctx.invoke(f, obj, *args, **kwargs) + + return update_wrapper(t.cast(F, new_func), f) + + if doc_description is None: + doc_description = f"the {key!r} key from :attr:`click.Context.meta`" + + decorator.__doc__ = ( + f"Decorator that passes {doc_description} as the first argument" + " to the decorated function." + ) + return decorator + + +CmdType = t.TypeVar("CmdType", bound=Command) + + +@t.overload +def command( + __func: t.Callable[..., t.Any], +) -> Command: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[..., Command]: + ... + + +@t.overload +def command( + name: t.Optional[str] = None, + cls: t.Type[CmdType] = ..., + **attrs: t.Any, +) -> t.Callable[..., CmdType]: + ... + + +def command( + name: t.Union[str, t.Callable[..., t.Any], None] = None, + cls: t.Optional[t.Type[Command]] = None, + **attrs: t.Any, +) -> t.Union[Command, t.Callable[..., Command]]: + r"""Creates a new :class:`Command` and uses the decorated function as + callback. This will also automatically attach all decorated + :func:`option`\s and :func:`argument`\s as parameters to the command. + + The name of the command defaults to the name of the function with + underscores replaced by dashes. If you want to change that, you can + pass the intended name as the first argument. + + All keyword arguments are forwarded to the underlying command class. + For the ``params`` argument, any decorated params are appended to + the end of the list. + + Once decorated the function turns into a :class:`Command` instance + that can be invoked as a command line utility or be attached to a + command :class:`Group`. + + :param name: the name of the command. This defaults to the function + name with underscores replaced by dashes. + :param cls: the command class to instantiate. This defaults to + :class:`Command`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + + .. versionchanged:: 8.1 + The ``params`` argument can be used. Decorated params are + appended to the end of the list. + """ + + func: t.Optional[t.Callable[..., t.Any]] = None + + if callable(name): + func = name + name = None + assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." + assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." + + if cls is None: + cls = Command + + def decorator(f: t.Callable[..., t.Any]) -> Command: + if isinstance(f, Command): + raise TypeError("Attempted to convert a callback into a command twice.") + + attr_params = attrs.pop("params", None) + params = attr_params if attr_params is not None else [] + + try: + decorator_params = f.__click_params__ # type: ignore + except AttributeError: + pass + else: + del f.__click_params__ # type: ignore + params.extend(reversed(decorator_params)) + + if attrs.get("help") is None: + attrs["help"] = f.__doc__ + + cmd = cls( # type: ignore[misc] + name=name or f.__name__.lower().replace("_", "-"), # type: ignore[arg-type] + callback=f, + params=params, + **attrs, + ) + cmd.__doc__ = f.__doc__ + return cmd + + if func is not None: + return decorator(func) + + return decorator + + +@t.overload +def group( + __func: t.Callable[..., t.Any], +) -> Group: + ... + + +@t.overload +def group( + name: t.Optional[str] = None, + **attrs: t.Any, +) -> t.Callable[[F], Group]: + ... + + +def group( + name: t.Union[str, t.Callable[..., t.Any], None] = None, **attrs: t.Any +) -> t.Union[Group, t.Callable[[F], Group]]: + """Creates a new :class:`Group` with a function as callback. This + works otherwise the same as :func:`command` just that the `cls` + parameter is set to :class:`Group`. + + .. versionchanged:: 8.1 + This decorator can be applied without parentheses. + """ + if attrs.get("cls") is None: + attrs["cls"] = Group + + if callable(name): + grp: t.Callable[[F], Group] = t.cast(Group, command(**attrs)) + return grp(name) + + return t.cast(Group, command(name, **attrs)) + + +def _param_memo(f: FC, param: Parameter) -> None: + if isinstance(f, Command): + f.params.append(param) + else: + if not hasattr(f, "__click_params__"): + f.__click_params__ = [] # type: ignore + + f.__click_params__.append(param) # type: ignore + + +def argument(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: + """Attaches an argument to the command. All positional arguments are + passed as parameter declarations to :class:`Argument`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Argument` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the argument class to instantiate. This defaults to + :class:`Argument`. + """ + + def decorator(f: FC) -> FC: + ArgumentClass = attrs.pop("cls", None) or Argument + _param_memo(f, ArgumentClass(param_decls, **attrs)) + return f + + return decorator + + +def option(*param_decls: str, **attrs: t.Any) -> t.Callable[[FC], FC]: + """Attaches an option to the command. All positional arguments are + passed as parameter declarations to :class:`Option`; all keyword + arguments are forwarded unchanged (except ``cls``). + This is equivalent to creating an :class:`Option` instance manually + and attaching it to the :attr:`Command.params` list. + + :param cls: the option class to instantiate. This defaults to + :class:`Option`. + """ + + def decorator(f: FC) -> FC: + # Issue 926, copy attrs, so pre-defined options can re-use the same cls= + option_attrs = attrs.copy() + OptionClass = option_attrs.pop("cls", None) or Option + _param_memo(f, OptionClass(param_decls, **option_attrs)) + return f + + return decorator + + +def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--yes`` option which shows a prompt before continuing if + not passed. If the prompt is declined, the program will exit. + + :param param_decls: One or more option names. Defaults to the single + value ``"--yes"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value: + ctx.abort() + + if not param_decls: + param_decls = ("--yes",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("callback", callback) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("prompt", "Do you want to continue?") + kwargs.setdefault("help", "Confirm the action without prompting.") + return option(*param_decls, **kwargs) + + +def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--password`` option which prompts for a password, hiding + input and asking to enter the value again for confirmation. + + :param param_decls: One or more option names. Defaults to the single + value ``"--password"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + if not param_decls: + param_decls = ("--password",) + + kwargs.setdefault("prompt", True) + kwargs.setdefault("confirmation_prompt", True) + kwargs.setdefault("hide_input", True) + return option(*param_decls, **kwargs) + + +def version_option( + version: t.Optional[str] = None, + *param_decls: str, + package_name: t.Optional[str] = None, + prog_name: t.Optional[str] = None, + message: t.Optional[str] = None, + **kwargs: t.Any, +) -> t.Callable[[FC], FC]: + """Add a ``--version`` option which immediately prints the version + number and exits the program. + + If ``version`` is not provided, Click will try to detect it using + :func:`importlib.metadata.version` to get the version for the + ``package_name``. On Python < 3.8, the ``importlib_metadata`` + backport must be installed. + + If ``package_name`` is not provided, Click will try to detect it by + inspecting the stack frames. This will be used to detect the + version, so it must match the name of the installed package. + + :param version: The version number to show. If not provided, Click + will try to detect it. + :param param_decls: One or more option names. Defaults to the single + value ``"--version"``. + :param package_name: The package name to detect the version from. If + not provided, Click will try to detect it. + :param prog_name: The name of the CLI to show in the message. If not + provided, it will be detected from the command. + :param message: The message to show. The values ``%(prog)s``, + ``%(package)s``, and ``%(version)s`` are available. Defaults to + ``"%(prog)s, version %(version)s"``. + :param kwargs: Extra arguments are passed to :func:`option`. + :raise RuntimeError: ``version`` could not be detected. + + .. versionchanged:: 8.0 + Add the ``package_name`` parameter, and the ``%(package)s`` + value for messages. + + .. versionchanged:: 8.0 + Use :mod:`importlib.metadata` instead of ``pkg_resources``. The + version is detected based on the package name, not the entry + point name. The Python package name must match the installed + package name, or be passed with ``package_name=``. + """ + if message is None: + message = _("%(prog)s, version %(version)s") + + if version is None and package_name is None: + frame = inspect.currentframe() + f_back = frame.f_back if frame is not None else None + f_globals = f_back.f_globals if f_back is not None else None + # break reference cycle + # https://docs.python.org/3/library/inspect.html#the-interpreter-stack + del frame + + if f_globals is not None: + package_name = f_globals.get("__name__") + + if package_name == "__main__": + package_name = f_globals.get("__package__") + + if package_name: + package_name = package_name.partition(".")[0] + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + nonlocal prog_name + nonlocal version + + if prog_name is None: + prog_name = ctx.find_root().info_name + + if version is None and package_name is not None: + metadata: t.Optional[types.ModuleType] + + try: + from importlib import metadata # type: ignore + except ImportError: + # Python < 3.8 + import importlib_metadata as metadata # type: ignore + + try: + version = metadata.version(package_name) # type: ignore + except metadata.PackageNotFoundError: # type: ignore + raise RuntimeError( + f"{package_name!r} is not installed. Try passing" + " 'package_name' instead." + ) from None + + if version is None: + raise RuntimeError( + f"Could not determine the version for {package_name!r} automatically." + ) + + echo( + t.cast(str, message) + % {"prog": prog_name, "package": package_name, "version": version}, + color=ctx.color, + ) + ctx.exit() + + if not param_decls: + param_decls = ("--version",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show the version and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) + + +def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: + """Add a ``--help`` option which immediately prints the help page + and exits the program. + + This is usually unnecessary, as the ``--help`` option is added to + each command automatically unless ``add_help_option=False`` is + passed. + + :param param_decls: One or more option names. Defaults to the single + value ``"--help"``. + :param kwargs: Extra arguments are passed to :func:`option`. + """ + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + if not value or ctx.resilient_parsing: + return + + echo(ctx.get_help(), color=ctx.color) + ctx.exit() + + if not param_decls: + param_decls = ("--help",) + + kwargs.setdefault("is_flag", True) + kwargs.setdefault("expose_value", False) + kwargs.setdefault("is_eager", True) + kwargs.setdefault("help", _("Show this message and exit.")) + kwargs["callback"] = callback + return option(*param_decls, **kwargs) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/exceptions.py b/flask-server/venv/lib/python3.10/site-packages/click/exceptions.py new file mode 100644 index 00000000..9e20b3eb --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/exceptions.py @@ -0,0 +1,287 @@ +import os +import typing as t +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import get_text_stderr +from .utils import echo + +if t.TYPE_CHECKING: + from .core import Context + from .core import Parameter + + +def _join_param_hints( + param_hint: t.Optional[t.Union[t.Sequence[str], str]] +) -> t.Optional[str]: + if param_hint is not None and not isinstance(param_hint, str): + return " / ".join(repr(x) for x in param_hint) + + return param_hint + + +class ClickException(Exception): + """An exception that Click can handle and show to the user.""" + + #: The exit code for this exception. + exit_code = 1 + + def __init__(self, message: str) -> None: + super().__init__(message) + self.message = message + + def format_message(self) -> str: + return self.message + + def __str__(self) -> str: + return self.message + + def show(self, file: t.Optional[t.IO] = None) -> None: + if file is None: + file = get_text_stderr() + + echo(_("Error: {message}").format(message=self.format_message()), file=file) + + +class UsageError(ClickException): + """An internal exception that signals a usage error. This typically + aborts any further handling. + + :param message: the error message to display. + :param ctx: optionally the context that caused this error. Click will + fill in the context automatically in some situations. + """ + + exit_code = 2 + + def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: + super().__init__(message) + self.ctx = ctx + self.cmd = self.ctx.command if self.ctx else None + + def show(self, file: t.Optional[t.IO] = None) -> None: + if file is None: + file = get_text_stderr() + color = None + hint = "" + if ( + self.ctx is not None + and self.ctx.command.get_help_option(self.ctx) is not None + ): + hint = _("Try '{command} {option}' for help.").format( + command=self.ctx.command_path, option=self.ctx.help_option_names[0] + ) + hint = f"{hint}\n" + if self.ctx is not None: + color = self.ctx.color + echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) + echo( + _("Error: {message}").format(message=self.format_message()), + file=file, + color=color, + ) + + +class BadParameter(UsageError): + """An exception that formats out a standardized error message for a + bad parameter. This is useful when thrown from a callback or type as + Click will attach contextual information to it (for instance, which + parameter it is). + + .. versionadded:: 2.0 + + :param param: the parameter object that caused this error. This can + be left out, and Click will attach this info itself + if possible. + :param param_hint: a string that shows up as parameter name. This + can be used as alternative to `param` in cases + where custom validation should happen. If it is + a string it's used as such, if it's a list then + each item is quoted and separated. + """ + + def __init__( + self, + message: str, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + ) -> None: + super().__init__(message, ctx) + self.param = param + self.param_hint = param_hint + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + return _("Invalid value: {message}").format(message=self.message) + + return _("Invalid value for {param_hint}: {message}").format( + param_hint=_join_param_hints(param_hint), message=self.message + ) + + +class MissingParameter(BadParameter): + """Raised if click required an option or argument but it was not + provided when invoking the script. + + .. versionadded:: 4.0 + + :param param_type: a string that indicates the type of the parameter. + The default is to inherit the parameter type from + the given `param`. Valid values are ``'parameter'``, + ``'option'`` or ``'argument'``. + """ + + def __init__( + self, + message: t.Optional[str] = None, + ctx: t.Optional["Context"] = None, + param: t.Optional["Parameter"] = None, + param_hint: t.Optional[str] = None, + param_type: t.Optional[str] = None, + ) -> None: + super().__init__(message or "", ctx, param, param_hint) + self.param_type = param_type + + def format_message(self) -> str: + if self.param_hint is not None: + param_hint: t.Optional[str] = self.param_hint + elif self.param is not None: + param_hint = self.param.get_error_hint(self.ctx) # type: ignore + else: + param_hint = None + + param_hint = _join_param_hints(param_hint) + param_hint = f" {param_hint}" if param_hint else "" + + param_type = self.param_type + if param_type is None and self.param is not None: + param_type = self.param.param_type_name + + msg = self.message + if self.param is not None: + msg_extra = self.param.type.get_missing_message(self.param) + if msg_extra: + if msg: + msg += f". {msg_extra}" + else: + msg = msg_extra + + msg = f" {msg}" if msg else "" + + # Translate param_type for known types. + if param_type == "argument": + missing = _("Missing argument") + elif param_type == "option": + missing = _("Missing option") + elif param_type == "parameter": + missing = _("Missing parameter") + else: + missing = _("Missing {param_type}").format(param_type=param_type) + + return f"{missing}{param_hint}.{msg}" + + def __str__(self) -> str: + if not self.message: + param_name = self.param.name if self.param else None + return _("Missing parameter: {param_name}").format(param_name=param_name) + else: + return self.message + + +class NoSuchOption(UsageError): + """Raised if click attempted to handle an option that does not + exist. + + .. versionadded:: 4.0 + """ + + def __init__( + self, + option_name: str, + message: t.Optional[str] = None, + possibilities: t.Optional[t.Sequence[str]] = None, + ctx: t.Optional["Context"] = None, + ) -> None: + if message is None: + message = _("No such option: {name}").format(name=option_name) + + super().__init__(message, ctx) + self.option_name = option_name + self.possibilities = possibilities + + def format_message(self) -> str: + if not self.possibilities: + return self.message + + possibility_str = ", ".join(sorted(self.possibilities)) + suggest = ngettext( + "Did you mean {possibility}?", + "(Possible options: {possibilities})", + len(self.possibilities), + ).format(possibility=possibility_str, possibilities=possibility_str) + return f"{self.message} {suggest}" + + +class BadOptionUsage(UsageError): + """Raised if an option is generally supplied but the use of the option + was incorrect. This is for instance raised if the number of arguments + for an option is not correct. + + .. versionadded:: 4.0 + + :param option_name: the name of the option being used incorrectly. + """ + + def __init__( + self, option_name: str, message: str, ctx: t.Optional["Context"] = None + ) -> None: + super().__init__(message, ctx) + self.option_name = option_name + + +class BadArgumentUsage(UsageError): + """Raised if an argument is generally supplied but the use of the argument + was incorrect. This is for instance raised if the number of values + for an argument is not correct. + + .. versionadded:: 6.0 + """ + + +class FileError(ClickException): + """Raised if a file cannot be opened.""" + + def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: + if hint is None: + hint = _("unknown error") + + super().__init__(hint) + self.ui_filename = os.fsdecode(filename) + self.filename = filename + + def format_message(self) -> str: + return _("Could not open file {filename!r}: {message}").format( + filename=self.ui_filename, message=self.message + ) + + +class Abort(RuntimeError): + """An internal signalling exception that signals Click to abort.""" + + +class Exit(RuntimeError): + """An exception that indicates that the application should exit with some + status code. + + :param code: the status code to exit with. + """ + + __slots__ = ("exit_code",) + + def __init__(self, code: int = 0) -> None: + self.exit_code = code diff --git a/flask-server/venv/lib/python3.10/site-packages/click/formatting.py b/flask-server/venv/lib/python3.10/site-packages/click/formatting.py new file mode 100644 index 00000000..ddd2a2f8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/formatting.py @@ -0,0 +1,301 @@ +import typing as t +from contextlib import contextmanager +from gettext import gettext as _ + +from ._compat import term_len +from .parser import split_opt + +# Can force a width. This is used by the test system +FORCED_WIDTH: t.Optional[int] = None + + +def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: + widths: t.Dict[int, int] = {} + + for row in rows: + for idx, col in enumerate(row): + widths[idx] = max(widths.get(idx, 0), term_len(col)) + + return tuple(y for x, y in sorted(widths.items())) + + +def iter_rows( + rows: t.Iterable[t.Tuple[str, str]], col_count: int +) -> t.Iterator[t.Tuple[str, ...]]: + for row in rows: + yield row + ("",) * (col_count - len(row)) + + +def wrap_text( + text: str, + width: int = 78, + initial_indent: str = "", + subsequent_indent: str = "", + preserve_paragraphs: bool = False, +) -> str: + """A helper function that intelligently wraps text. By default, it + assumes that it operates on a single paragraph of text but if the + `preserve_paragraphs` parameter is provided it will intelligently + handle paragraphs (defined by two empty lines). + + If paragraphs are handled, a paragraph can be prefixed with an empty + line containing the ``\\b`` character (``\\x08``) to indicate that + no rewrapping should happen in that block. + + :param text: the text that should be rewrapped. + :param width: the maximum width for the text. + :param initial_indent: the initial indent that should be placed on the + first line as a string. + :param subsequent_indent: the indent string that should be placed on + each consecutive line. + :param preserve_paragraphs: if this flag is set then the wrapping will + intelligently handle paragraphs. + """ + from ._textwrap import TextWrapper + + text = text.expandtabs() + wrapper = TextWrapper( + width, + initial_indent=initial_indent, + subsequent_indent=subsequent_indent, + replace_whitespace=False, + ) + if not preserve_paragraphs: + return wrapper.fill(text) + + p: t.List[t.Tuple[int, bool, str]] = [] + buf: t.List[str] = [] + indent = None + + def _flush_par() -> None: + if not buf: + return + if buf[0].strip() == "\b": + p.append((indent or 0, True, "\n".join(buf[1:]))) + else: + p.append((indent or 0, False, " ".join(buf))) + del buf[:] + + for line in text.splitlines(): + if not line: + _flush_par() + indent = None + else: + if indent is None: + orig_len = term_len(line) + line = line.lstrip() + indent = orig_len - term_len(line) + buf.append(line) + _flush_par() + + rv = [] + for indent, raw, text in p: + with wrapper.extra_indent(" " * indent): + if raw: + rv.append(wrapper.indent_only(text)) + else: + rv.append(wrapper.fill(text)) + + return "\n\n".join(rv) + + +class HelpFormatter: + """This class helps with formatting text-based help pages. It's + usually just needed for very special internal cases, but it's also + exposed so that developers can write their own fancy outputs. + + At present, it always writes into memory. + + :param indent_increment: the additional increment for each level. + :param width: the width for the text. This defaults to the terminal + width clamped to a maximum of 78. + """ + + def __init__( + self, + indent_increment: int = 2, + width: t.Optional[int] = None, + max_width: t.Optional[int] = None, + ) -> None: + import shutil + + self.indent_increment = indent_increment + if max_width is None: + max_width = 80 + if width is None: + width = FORCED_WIDTH + if width is None: + width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) + self.width = width + self.current_indent = 0 + self.buffer: t.List[str] = [] + + def write(self, string: str) -> None: + """Writes a unicode string into the internal buffer.""" + self.buffer.append(string) + + def indent(self) -> None: + """Increases the indentation.""" + self.current_indent += self.indent_increment + + def dedent(self) -> None: + """Decreases the indentation.""" + self.current_indent -= self.indent_increment + + def write_usage( + self, prog: str, args: str = "", prefix: t.Optional[str] = None + ) -> None: + """Writes a usage line into the buffer. + + :param prog: the program name. + :param args: whitespace separated list of arguments. + :param prefix: The prefix for the first line. Defaults to + ``"Usage: "``. + """ + if prefix is None: + prefix = f"{_('Usage:')} " + + usage_prefix = f"{prefix:>{self.current_indent}}{prog} " + text_width = self.width - self.current_indent + + if text_width >= (term_len(usage_prefix) + 20): + # The arguments will fit to the right of the prefix. + indent = " " * term_len(usage_prefix) + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) + ) + else: + # The prefix is too long, put the arguments on the next line. + self.write(usage_prefix) + self.write("\n") + indent = " " * (max(self.current_indent, term_len(prefix)) + 4) + self.write( + wrap_text( + args, text_width, initial_indent=indent, subsequent_indent=indent + ) + ) + + self.write("\n") + + def write_heading(self, heading: str) -> None: + """Writes a heading into the buffer.""" + self.write(f"{'':>{self.current_indent}}{heading}:\n") + + def write_paragraph(self) -> None: + """Writes a paragraph into the buffer.""" + if self.buffer: + self.write("\n") + + def write_text(self, text: str) -> None: + """Writes re-indented text into the buffer. This rewraps and + preserves paragraphs. + """ + indent = " " * self.current_indent + self.write( + wrap_text( + text, + self.width, + initial_indent=indent, + subsequent_indent=indent, + preserve_paragraphs=True, + ) + ) + self.write("\n") + + def write_dl( + self, + rows: t.Sequence[t.Tuple[str, str]], + col_max: int = 30, + col_spacing: int = 2, + ) -> None: + """Writes a definition list into the buffer. This is how options + and commands are usually formatted. + + :param rows: a list of two item tuples for the terms and values. + :param col_max: the maximum width of the first column. + :param col_spacing: the number of spaces between the first and + second column. + """ + rows = list(rows) + widths = measure_table(rows) + if len(widths) != 2: + raise TypeError("Expected two columns for definition list") + + first_col = min(widths[0], col_max) + col_spacing + + for first, second in iter_rows(rows, len(widths)): + self.write(f"{'':>{self.current_indent}}{first}") + if not second: + self.write("\n") + continue + if term_len(first) <= first_col - col_spacing: + self.write(" " * (first_col - term_len(first))) + else: + self.write("\n") + self.write(" " * (first_col + self.current_indent)) + + text_width = max(self.width - first_col - 2, 10) + wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) + lines = wrapped_text.splitlines() + + if lines: + self.write(f"{lines[0]}\n") + + for line in lines[1:]: + self.write(f"{'':>{first_col + self.current_indent}}{line}\n") + else: + self.write("\n") + + @contextmanager + def section(self, name: str) -> t.Iterator[None]: + """Helpful context manager that writes a paragraph, a heading, + and the indents. + + :param name: the section name that is written as heading. + """ + self.write_paragraph() + self.write_heading(name) + self.indent() + try: + yield + finally: + self.dedent() + + @contextmanager + def indentation(self) -> t.Iterator[None]: + """A context manager that increases the indentation.""" + self.indent() + try: + yield + finally: + self.dedent() + + def getvalue(self) -> str: + """Returns the buffer contents.""" + return "".join(self.buffer) + + +def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: + """Given a list of option strings this joins them in the most appropriate + way and returns them in the form ``(formatted_string, + any_prefix_is_slash)`` where the second item in the tuple is a flag that + indicates if any of the option prefixes was a slash. + """ + rv = [] + any_prefix_is_slash = False + + for opt in options: + prefix = split_opt(opt)[0] + + if prefix == "/": + any_prefix_is_slash = True + + rv.append((len(prefix), opt)) + + rv.sort(key=lambda x: x[0]) + return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/flask-server/venv/lib/python3.10/site-packages/click/globals.py b/flask-server/venv/lib/python3.10/site-packages/click/globals.py new file mode 100644 index 00000000..480058f1 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/globals.py @@ -0,0 +1,68 @@ +import typing as t +from threading import local + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + +_local = local() + + +@t.overload +def get_current_context(silent: "te.Literal[False]" = False) -> "Context": + ... + + +@t.overload +def get_current_context(silent: bool = ...) -> t.Optional["Context"]: + ... + + +def get_current_context(silent: bool = False) -> t.Optional["Context"]: + """Returns the current click context. This can be used as a way to + access the current context object from anywhere. This is a more implicit + alternative to the :func:`pass_context` decorator. This function is + primarily useful for helpers such as :func:`echo` which might be + interested in changing its behavior based on the current context. + + To push the current context, :meth:`Context.scope` can be used. + + .. versionadded:: 5.0 + + :param silent: if set to `True` the return value is `None` if no context + is available. The default behavior is to raise a + :exc:`RuntimeError`. + """ + try: + return t.cast("Context", _local.stack[-1]) + except (AttributeError, IndexError) as e: + if not silent: + raise RuntimeError("There is no active click context.") from e + + return None + + +def push_context(ctx: "Context") -> None: + """Pushes a new context to the current stack.""" + _local.__dict__.setdefault("stack", []).append(ctx) + + +def pop_context() -> None: + """Removes the top level from the stack.""" + _local.stack.pop() + + +def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: + """Internal helper to get the default value of the color flag. If a + value is passed it's returned unchanged, otherwise it's looked up from + the current context. + """ + if color is not None: + return color + + ctx = get_current_context(silent=True) + + if ctx is not None: + return ctx.color + + return None diff --git a/flask-server/venv/lib/python3.10/site-packages/click/parser.py b/flask-server/venv/lib/python3.10/site-packages/click/parser.py new file mode 100644 index 00000000..2d5a2ed7 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/parser.py @@ -0,0 +1,529 @@ +""" +This module started out as largely a copy paste from the stdlib's +optparse module with the features removed that we do not need from +optparse because we implement them in Click on a higher level (for +instance type handling, help formatting and a lot more). + +The plan is to remove more and more from here over time. + +The reason this is a different module and not optparse from the stdlib +is that there are differences in 2.x and 3.x about the error messages +generated and optparse in the stdlib uses gettext for no good reason +and might cause us issues. + +Click uses parts of optparse written by Gregory P. Ward and maintained +by the Python Software Foundation. This is limited to code in parser.py. + +Copyright 2001-2006 Gregory P. Ward. All rights reserved. +Copyright 2002-2006 Python Software Foundation. All rights reserved. +""" +# This code uses parts of optparse written by Gregory P. Ward and +# maintained by the Python Software Foundation. +# Copyright 2001-2006 Gregory P. Ward +# Copyright 2002-2006 Python Software Foundation +import typing as t +from collections import deque +from gettext import gettext as _ +from gettext import ngettext + +from .exceptions import BadArgumentUsage +from .exceptions import BadOptionUsage +from .exceptions import NoSuchOption +from .exceptions import UsageError + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Argument as CoreArgument + from .core import Context + from .core import Option as CoreOption + from .core import Parameter as CoreParameter + +V = t.TypeVar("V") + +# Sentinel value that indicates an option was passed as a flag without a +# value but is not a flag option. Option.consume_value uses this to +# prompt or use the flag_value. +_flag_needs_value = object() + + +def _unpack_args( + args: t.Sequence[str], nargs_spec: t.Sequence[int] +) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: + """Given an iterable of arguments and an iterable of nargs specifications, + it returns a tuple with all the unpacked arguments at the first index + and all remaining arguments as the second. + + The nargs specification is the number of arguments that should be consumed + or `-1` to indicate that this position should eat up all the remainders. + + Missing items are filled with `None`. + """ + args = deque(args) + nargs_spec = deque(nargs_spec) + rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] + spos: t.Optional[int] = None + + def _fetch(c: "te.Deque[V]") -> t.Optional[V]: + try: + if spos is None: + return c.popleft() + else: + return c.pop() + except IndexError: + return None + + while nargs_spec: + nargs = _fetch(nargs_spec) + + if nargs is None: + continue + + if nargs == 1: + rv.append(_fetch(args)) + elif nargs > 1: + x = [_fetch(args) for _ in range(nargs)] + + # If we're reversed, we're pulling in the arguments in reverse, + # so we need to turn them around. + if spos is not None: + x.reverse() + + rv.append(tuple(x)) + elif nargs < 0: + if spos is not None: + raise TypeError("Cannot have two nargs < 0") + + spos = len(rv) + rv.append(None) + + # spos is the position of the wildcard (star). If it's not `None`, + # we fill it with the remainder. + if spos is not None: + rv[spos] = tuple(args) + args = [] + rv[spos + 1 :] = reversed(rv[spos + 1 :]) + + return tuple(rv), list(args) + + +def split_opt(opt: str) -> t.Tuple[str, str]: + first = opt[:1] + if first.isalnum(): + return "", opt + if opt[1:2] == first: + return opt[:2], opt[2:] + return first, opt[1:] + + +def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: + if ctx is None or ctx.token_normalize_func is None: + return opt + prefix, opt = split_opt(opt) + return f"{prefix}{ctx.token_normalize_func(opt)}" + + +def split_arg_string(string: str) -> t.List[str]: + """Split an argument string as with :func:`shlex.split`, but don't + fail if the string is incomplete. Ignores a missing closing quote or + incomplete escape sequence and uses the partial token as-is. + + .. code-block:: python + + split_arg_string("example 'my file") + ["example", "my file"] + + split_arg_string("example my\\") + ["example", "my"] + + :param string: String to split. + """ + import shlex + + lex = shlex.shlex(string, posix=True) + lex.whitespace_split = True + lex.commenters = "" + out = [] + + try: + for token in lex: + out.append(token) + except ValueError: + # Raised when end-of-string is reached in an invalid state. Use + # the partial token as-is. The quote or escape character is in + # lex.state, not lex.token. + out.append(lex.token) + + return out + + +class Option: + def __init__( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ): + self._short_opts = [] + self._long_opts = [] + self.prefixes = set() + + for opt in opts: + prefix, value = split_opt(opt) + if not prefix: + raise ValueError(f"Invalid start character for option ({opt})") + self.prefixes.add(prefix[0]) + if len(prefix) == 1 and len(value) == 1: + self._short_opts.append(opt) + else: + self._long_opts.append(opt) + self.prefixes.add(prefix) + + if action is None: + action = "store" + + self.dest = dest + self.action = action + self.nargs = nargs + self.const = const + self.obj = obj + + @property + def takes_value(self) -> bool: + return self.action in ("store", "append") + + def process(self, value: str, state: "ParsingState") -> None: + if self.action == "store": + state.opts[self.dest] = value # type: ignore + elif self.action == "store_const": + state.opts[self.dest] = self.const # type: ignore + elif self.action == "append": + state.opts.setdefault(self.dest, []).append(value) # type: ignore + elif self.action == "append_const": + state.opts.setdefault(self.dest, []).append(self.const) # type: ignore + elif self.action == "count": + state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore + else: + raise ValueError(f"unknown action '{self.action}'") + state.order.append(self.obj) + + +class Argument: + def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): + self.dest = dest + self.nargs = nargs + self.obj = obj + + def process( + self, + value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], + state: "ParsingState", + ) -> None: + if self.nargs > 1: + assert value is not None + holes = sum(1 for x in value if x is None) + if holes == len(value): + value = None + elif holes != 0: + raise BadArgumentUsage( + _("Argument {name!r} takes {nargs} values.").format( + name=self.dest, nargs=self.nargs + ) + ) + + if self.nargs == -1 and self.obj.envvar is not None and value == (): + # Replace empty tuple with None so that a value from the + # environment may be tried. + value = None + + state.opts[self.dest] = value # type: ignore + state.order.append(self.obj) + + +class ParsingState: + def __init__(self, rargs: t.List[str]) -> None: + self.opts: t.Dict[str, t.Any] = {} + self.largs: t.List[str] = [] + self.rargs = rargs + self.order: t.List["CoreParameter"] = [] + + +class OptionParser: + """The option parser is an internal class that is ultimately used to + parse options and arguments. It's modelled after optparse and brings + a similar but vastly simplified API. It should generally not be used + directly as the high level Click classes wrap it for you. + + It's not nearly as extensible as optparse or argparse as it does not + implement features that are implemented on a higher level (such as + types or defaults). + + :param ctx: optionally the :class:`~click.Context` where this parser + should go with. + """ + + def __init__(self, ctx: t.Optional["Context"] = None) -> None: + #: The :class:`~click.Context` for this parser. This might be + #: `None` for some advanced use cases. + self.ctx = ctx + #: This controls how the parser deals with interspersed arguments. + #: If this is set to `False`, the parser will stop on the first + #: non-option. Click uses this to implement nested subcommands + #: safely. + self.allow_interspersed_args = True + #: This tells the parser how to deal with unknown options. By + #: default it will error out (which is sensible), but there is a + #: second mode where it will ignore it and continue processing + #: after shifting all the unknown options into the resulting args. + self.ignore_unknown_options = False + + if ctx is not None: + self.allow_interspersed_args = ctx.allow_interspersed_args + self.ignore_unknown_options = ctx.ignore_unknown_options + + self._short_opt: t.Dict[str, Option] = {} + self._long_opt: t.Dict[str, Option] = {} + self._opt_prefixes = {"-", "--"} + self._args: t.List[Argument] = [] + + def add_option( + self, + obj: "CoreOption", + opts: t.Sequence[str], + dest: t.Optional[str], + action: t.Optional[str] = None, + nargs: int = 1, + const: t.Optional[t.Any] = None, + ) -> None: + """Adds a new option named `dest` to the parser. The destination + is not inferred (unlike with optparse) and needs to be explicitly + provided. Action can be any of ``store``, ``store_const``, + ``append``, ``append_const`` or ``count``. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + opts = [normalize_opt(opt, self.ctx) for opt in opts] + option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) + self._opt_prefixes.update(option.prefixes) + for opt in option._short_opts: + self._short_opt[opt] = option + for opt in option._long_opts: + self._long_opt[opt] = option + + def add_argument( + self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 + ) -> None: + """Adds a positional argument named `dest` to the parser. + + The `obj` can be used to identify the option in the order list + that is returned from the parser. + """ + self._args.append(Argument(obj, dest=dest, nargs=nargs)) + + def parse_args( + self, args: t.List[str] + ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: + """Parses positional arguments and returns ``(values, args, order)`` + for the parsed options and arguments as well as the leftover + arguments if there are any. The order is a list of objects as they + appear on the command line. If arguments appear multiple times they + will be memorized multiple times as well. + """ + state = ParsingState(args) + try: + self._process_args_for_options(state) + self._process_args_for_args(state) + except UsageError: + if self.ctx is None or not self.ctx.resilient_parsing: + raise + return state.opts, state.largs, state.order + + def _process_args_for_args(self, state: ParsingState) -> None: + pargs, args = _unpack_args( + state.largs + state.rargs, [x.nargs for x in self._args] + ) + + for idx, arg in enumerate(self._args): + arg.process(pargs[idx], state) + + state.largs = args + state.rargs = [] + + def _process_args_for_options(self, state: ParsingState) -> None: + while state.rargs: + arg = state.rargs.pop(0) + arglen = len(arg) + # Double dashes always handled explicitly regardless of what + # prefixes are valid. + if arg == "--": + return + elif arg[:1] in self._opt_prefixes and arglen > 1: + self._process_opts(arg, state) + elif self.allow_interspersed_args: + state.largs.append(arg) + else: + state.rargs.insert(0, arg) + return + + # Say this is the original argument list: + # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] + # ^ + # (we are about to process arg(i)). + # + # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of + # [arg0, ..., arg(i-1)] (any options and their arguments will have + # been removed from largs). + # + # The while loop will usually consume 1 or more arguments per pass. + # If it consumes 1 (eg. arg is an option that takes no arguments), + # then after _process_arg() is done the situation is: + # + # largs = subset of [arg0, ..., arg(i)] + # rargs = [arg(i+1), ..., arg(N-1)] + # + # If allow_interspersed_args is false, largs will always be + # *empty* -- still a subset of [arg0, ..., arg(i-1)], but + # not a very interesting subset! + + def _match_long_opt( + self, opt: str, explicit_value: t.Optional[str], state: ParsingState + ) -> None: + if opt not in self._long_opt: + from difflib import get_close_matches + + possibilities = get_close_matches(opt, self._long_opt) + raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) + + option = self._long_opt[opt] + if option.takes_value: + # At this point it's safe to modify rargs by injecting the + # explicit value, because no exception is raised in this + # branch. This means that the inserted value will be fully + # consumed. + if explicit_value is not None: + state.rargs.insert(0, explicit_value) + + value = self._get_value_from_state(opt, option, state) + + elif explicit_value is not None: + raise BadOptionUsage( + opt, _("Option {name!r} does not take a value.").format(name=opt) + ) + + else: + value = None + + option.process(value, state) + + def _match_short_opt(self, arg: str, state: ParsingState) -> None: + stop = False + i = 1 + prefix = arg[0] + unknown_options = [] + + for ch in arg[1:]: + opt = normalize_opt(f"{prefix}{ch}", self.ctx) + option = self._short_opt.get(opt) + i += 1 + + if not option: + if self.ignore_unknown_options: + unknown_options.append(ch) + continue + raise NoSuchOption(opt, ctx=self.ctx) + if option.takes_value: + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + state.rargs.insert(0, arg[i:]) + stop = True + + value = self._get_value_from_state(opt, option, state) + + else: + value = None + + option.process(value, state) + + if stop: + break + + # If we got any unknown options we re-combinate the string of the + # remaining options and re-attach the prefix, then report that + # to the state as new larg. This way there is basic combinatorics + # that can be achieved while still ignoring unknown arguments. + if self.ignore_unknown_options and unknown_options: + state.largs.append(f"{prefix}{''.join(unknown_options)}") + + def _get_value_from_state( + self, option_name: str, option: Option, state: ParsingState + ) -> t.Any: + nargs = option.nargs + + if len(state.rargs) < nargs: + if option.obj._flag_needs_value: + # Option allows omitting the value. + value = _flag_needs_value + else: + raise BadOptionUsage( + option_name, + ngettext( + "Option {name!r} requires an argument.", + "Option {name!r} requires {nargs} arguments.", + nargs, + ).format(name=option_name, nargs=nargs), + ) + elif nargs == 1: + next_rarg = state.rargs[0] + + if ( + option.obj._flag_needs_value + and isinstance(next_rarg, str) + and next_rarg[:1] in self._opt_prefixes + and len(next_rarg) > 1 + ): + # The next arg looks like the start of an option, don't + # use it as the value if omitting the value is allowed. + value = _flag_needs_value + else: + value = state.rargs.pop(0) + else: + value = tuple(state.rargs[:nargs]) + del state.rargs[:nargs] + + return value + + def _process_opts(self, arg: str, state: ParsingState) -> None: + explicit_value = None + # Long option handling happens in two parts. The first part is + # supporting explicitly attached values. In any case, we will try + # to long match the option first. + if "=" in arg: + long_opt, explicit_value = arg.split("=", 1) + else: + long_opt = arg + norm_long_opt = normalize_opt(long_opt, self.ctx) + + # At this point we will match the (assumed) long option through + # the long option matching code. Note that this allows options + # like "-foo" to be matched as long options. + try: + self._match_long_opt(norm_long_opt, explicit_value, state) + except NoSuchOption: + # At this point the long option matching failed, and we need + # to try with short options. However there is a special rule + # which says, that if we have a two character options prefix + # (applies to "--foo" for instance), we do not dispatch to the + # short option code and will instead raise the no option + # error. + if arg[:2] not in self._opt_prefixes: + self._match_short_opt(arg, state) + return + + if not self.ignore_unknown_options: + raise + + state.largs.append(arg) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/py.typed b/flask-server/venv/lib/python3.10/site-packages/click/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/flask-server/venv/lib/python3.10/site-packages/click/shell_completion.py b/flask-server/venv/lib/python3.10/site-packages/click/shell_completion.py new file mode 100644 index 00000000..c17a8e64 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/shell_completion.py @@ -0,0 +1,580 @@ +import os +import re +import typing as t +from gettext import gettext as _ + +from .core import Argument +from .core import BaseCommand +from .core import Context +from .core import MultiCommand +from .core import Option +from .core import Parameter +from .core import ParameterSource +from .parser import split_arg_string +from .utils import echo + + +def shell_complete( + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + instruction: str, +) -> int: + """Perform shell completion for the given CLI program. + + :param cli: Command being called. + :param ctx_args: Extra arguments to pass to + ``cli.make_context``. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + :param instruction: Value of ``complete_var`` with the completion + instruction and shell, in the form ``instruction_shell``. + :return: Status code to exit with. + """ + shell, _, instruction = instruction.partition("_") + comp_cls = get_completion_class(shell) + + if comp_cls is None: + return 1 + + comp = comp_cls(cli, ctx_args, prog_name, complete_var) + + if instruction == "source": + echo(comp.source()) + return 0 + + if instruction == "complete": + echo(comp.complete()) + return 0 + + return 1 + + +class CompletionItem: + """Represents a completion value and metadata about the value. The + default metadata is ``type`` to indicate special shell handling, + and ``help`` if a shell supports showing a help string next to the + value. + + Arbitrary parameters can be passed when creating the object, and + accessed using ``item.attr``. If an attribute wasn't passed, + accessing it returns ``None``. + + :param value: The completion suggestion. + :param type: Tells the shell script to provide special completion + support for the type. Click uses ``"dir"`` and ``"file"``. + :param help: String shown next to the value if supported. + :param kwargs: Arbitrary metadata. The built-in implementations + don't use this, but custom type completions paired with custom + shell support could use it. + """ + + __slots__ = ("value", "type", "help", "_info") + + def __init__( + self, + value: t.Any, + type: str = "plain", + help: t.Optional[str] = None, + **kwargs: t.Any, + ) -> None: + self.value = value + self.type = type + self.help = help + self._info = kwargs + + def __getattr__(self, name: str) -> t.Any: + return self._info.get(name) + + +# Only Bash >= 4.4 has the nosort option. +_SOURCE_BASH = """\ +%(complete_func)s() { + local IFS=$'\\n' + local response + + response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ +%(complete_var)s=bash_complete $1) + + for completion in $response; do + IFS=',' read type value <<< "$completion" + + if [[ $type == 'dir' ]]; then + COMPREPLY=() + compopt -o dirnames + elif [[ $type == 'file' ]]; then + COMPREPLY=() + compopt -o default + elif [[ $type == 'plain' ]]; then + COMPREPLY+=($value) + fi + done + + return 0 +} + +%(complete_func)s_setup() { + complete -o nosort -F %(complete_func)s %(prog_name)s +} + +%(complete_func)s_setup; +""" + +_SOURCE_ZSH = """\ +#compdef %(prog_name)s + +%(complete_func)s() { + local -a completions + local -a completions_with_descriptions + local -a response + (( ! $+commands[%(prog_name)s] )) && return 1 + + response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ +%(complete_var)s=zsh_complete %(prog_name)s)}") + + for type key descr in ${response}; do + if [[ "$type" == "plain" ]]; then + if [[ "$descr" == "_" ]]; then + completions+=("$key") + else + completions_with_descriptions+=("$key":"$descr") + fi + elif [[ "$type" == "dir" ]]; then + _path_files -/ + elif [[ "$type" == "file" ]]; then + _path_files -f + fi + done + + if [ -n "$completions_with_descriptions" ]; then + _describe -V unsorted completions_with_descriptions -U + fi + + if [ -n "$completions" ]; then + compadd -U -V unsorted -a completions + fi +} + +compdef %(complete_func)s %(prog_name)s; +""" + +_SOURCE_FISH = """\ +function %(complete_func)s; + set -l response; + + for value in (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ +COMP_CWORD=(commandline -t) %(prog_name)s); + set response $response $value; + end; + + for completion in $response; + set -l metadata (string split "," $completion); + + if test $metadata[1] = "dir"; + __fish_complete_directories $metadata[2]; + else if test $metadata[1] = "file"; + __fish_complete_path $metadata[2]; + else if test $metadata[1] = "plain"; + echo $metadata[2]; + end; + end; +end; + +complete --no-files --command %(prog_name)s --arguments \ +"(%(complete_func)s)"; +""" + + +class ShellComplete: + """Base class for providing shell completion support. A subclass for + a given shell will override attributes and methods to implement the + completion instructions (``source`` and ``complete``). + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param complete_var: Name of the environment variable that holds + the completion instruction. + + .. versionadded:: 8.0 + """ + + name: t.ClassVar[str] + """Name to register the shell as with :func:`add_completion_class`. + This is used in completion instructions (``{name}_source`` and + ``{name}_complete``). + """ + + source_template: t.ClassVar[str] + """Completion script template formatted by :meth:`source`. This must + be provided by subclasses. + """ + + def __init__( + self, + cli: BaseCommand, + ctx_args: t.Dict[str, t.Any], + prog_name: str, + complete_var: str, + ) -> None: + self.cli = cli + self.ctx_args = ctx_args + self.prog_name = prog_name + self.complete_var = complete_var + + @property + def func_name(self) -> str: + """The name of the shell function defined by the completion + script. + """ + safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), re.ASCII) + return f"_{safe_name}_completion" + + def source_vars(self) -> t.Dict[str, t.Any]: + """Vars for formatting :attr:`source_template`. + + By default this provides ``complete_func``, ``complete_var``, + and ``prog_name``. + """ + return { + "complete_func": self.func_name, + "complete_var": self.complete_var, + "prog_name": self.prog_name, + } + + def source(self) -> str: + """Produce the shell script that defines the completion + function. By default this ``%``-style formats + :attr:`source_template` with the dict returned by + :meth:`source_vars`. + """ + return self.source_template % self.source_vars() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + """Use the env vars defined by the shell script to return a + tuple of ``args, incomplete``. This must be implemented by + subclasses. + """ + raise NotImplementedError + + def get_completions( + self, args: t.List[str], incomplete: str + ) -> t.List[CompletionItem]: + """Determine the context and last complete command or parameter + from the complete args. Call that object's ``shell_complete`` + method to get the completions for the incomplete value. + + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) + obj, incomplete = _resolve_incomplete(ctx, args, incomplete) + return obj.shell_complete(ctx, incomplete) + + def format_completion(self, item: CompletionItem) -> str: + """Format a completion item into the form recognized by the + shell script. This must be implemented by subclasses. + + :param item: Completion item to format. + """ + raise NotImplementedError + + def complete(self) -> str: + """Produce the completion data to send back to the shell. + + By default this calls :meth:`get_completion_args`, gets the + completions, then calls :meth:`format_completion` for each + completion. + """ + args, incomplete = self.get_completion_args() + completions = self.get_completions(args, incomplete) + out = [self.format_completion(item) for item in completions] + return "\n".join(out) + + +class BashComplete(ShellComplete): + """Shell completion for Bash.""" + + name = "bash" + source_template = _SOURCE_BASH + + def _check_version(self) -> None: + import subprocess + + output = subprocess.run( + ["bash", "-c", "echo ${BASH_VERSION}"], stdout=subprocess.PIPE + ) + match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) + + if match is not None: + major, minor = match.groups() + + if major < "4" or major == "4" and minor < "4": + raise RuntimeError( + _( + "Shell completion is not supported for Bash" + " versions older than 4.4." + ) + ) + else: + raise RuntimeError( + _("Couldn't detect Bash version, shell completion is not supported.") + ) + + def source(self) -> str: + self._check_version() + return super().source() + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type},{item.value}" + + +class ZshComplete(ShellComplete): + """Shell completion for Zsh.""" + + name = "zsh" + source_template = _SOURCE_ZSH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + cword = int(os.environ["COMP_CWORD"]) + args = cwords[1:cword] + + try: + incomplete = cwords[cword] + except IndexError: + incomplete = "" + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" + + +class FishComplete(ShellComplete): + """Shell completion for Fish.""" + + name = "fish" + source_template = _SOURCE_FISH + + def get_completion_args(self) -> t.Tuple[t.List[str], str]: + cwords = split_arg_string(os.environ["COMP_WORDS"]) + incomplete = os.environ["COMP_CWORD"] + args = cwords[1:] + + # Fish stores the partial word in both COMP_WORDS and + # COMP_CWORD, remove it from complete args. + if incomplete and args and args[-1] == incomplete: + args.pop() + + return args, incomplete + + def format_completion(self, item: CompletionItem) -> str: + if item.help: + return f"{item.type},{item.value}\t{item.help}" + + return f"{item.type},{item.value}" + + +_available_shells: t.Dict[str, t.Type[ShellComplete]] = { + "bash": BashComplete, + "fish": FishComplete, + "zsh": ZshComplete, +} + + +def add_completion_class( + cls: t.Type[ShellComplete], name: t.Optional[str] = None +) -> None: + """Register a :class:`ShellComplete` subclass under the given name. + The name will be provided by the completion instruction environment + variable during completion. + + :param cls: The completion class that will handle completion for the + shell. + :param name: Name to register the class under. Defaults to the + class's ``name`` attribute. + """ + if name is None: + name = cls.name + + _available_shells[name] = cls + + +def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: + """Look up a registered :class:`ShellComplete` subclass by the name + provided by the completion instruction environment variable. If the + name isn't registered, returns ``None``. + + :param shell: Name the class is registered under. + """ + return _available_shells.get(shell) + + +def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: + """Determine if the given parameter is an argument that can still + accept values. + + :param ctx: Invocation context for the command represented by the + parsed complete args. + :param param: Argument object being checked. + """ + if not isinstance(param, Argument): + return False + + assert param.name is not None + value = ctx.params[param.name] + return ( + param.nargs == -1 + or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE + or ( + param.nargs > 1 + and isinstance(value, (tuple, list)) + and len(value) < param.nargs + ) + ) + + +def _start_of_option(ctx: Context, value: str) -> bool: + """Check if the value looks like the start of an option.""" + if not value: + return False + + c = value[0] + return c in ctx._opt_prefixes + + +def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: + """Determine if the given parameter is an option that needs a value. + + :param args: List of complete args before the incomplete value. + :param param: Option object being checked. + """ + if not isinstance(param, Option): + return False + + if param.is_flag or param.count: + return False + + last_option = None + + for index, arg in enumerate(reversed(args)): + if index + 1 > param.nargs: + break + + if _start_of_option(ctx, arg): + last_option = arg + + return last_option is not None and last_option in param.opts + + +def _resolve_context( + cli: BaseCommand, ctx_args: t.Dict[str, t.Any], prog_name: str, args: t.List[str] +) -> Context: + """Produce the context hierarchy starting with the command and + traversing the complete arguments. This only follows the commands, + it doesn't trigger input prompts or callbacks. + + :param cli: Command being called. + :param prog_name: Name of the executable in the shell. + :param args: List of complete args before the incomplete value. + """ + ctx_args["resilient_parsing"] = True + ctx = cli.make_context(prog_name, args.copy(), **ctx_args) + args = ctx.protected_args + ctx.args + + while args: + command = ctx.command + + if isinstance(command, MultiCommand): + if not command.chain: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) + args = ctx.protected_args + ctx.args + else: + while args: + name, cmd, args = command.resolve_command(ctx, args) + + if cmd is None: + return ctx + + sub_ctx = cmd.make_context( + name, + args, + parent=ctx, + allow_extra_args=True, + allow_interspersed_args=False, + resilient_parsing=True, + ) + args = sub_ctx.args + + ctx = sub_ctx + args = [*sub_ctx.protected_args, *sub_ctx.args] + else: + break + + return ctx + + +def _resolve_incomplete( + ctx: Context, args: t.List[str], incomplete: str +) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: + """Find the Click object that will handle the completion of the + incomplete value. Return the object and the incomplete value. + + :param ctx: Invocation context for the command represented by + the parsed complete args. + :param args: List of complete args before the incomplete value. + :param incomplete: Value being completed. May be empty. + """ + # Different shells treat an "=" between a long option name and + # value differently. Might keep the value joined, return the "=" + # as a separate item, or return the split name and value. Always + # split and discard the "=" to make completion easier. + if incomplete == "=": + incomplete = "" + elif "=" in incomplete and _start_of_option(ctx, incomplete): + name, _, incomplete = incomplete.partition("=") + args.append(name) + + # The "--" marker tells Click to stop treating values as options + # even if they start with the option character. If it hasn't been + # given and the incomplete arg looks like an option, the current + # command will provide option name completions. + if "--" not in args and _start_of_option(ctx, incomplete): + return ctx.command, incomplete + + params = ctx.command.get_params(ctx) + + # If the last complete arg is an option name with an incomplete + # value, the option will provide value completions. + for param in params: + if _is_incomplete_option(ctx, args, param): + return param, incomplete + + # It's not an option name or value. The first argument without a + # parsed value will provide value completions. + for param in params: + if _is_incomplete_argument(ctx, param): + return param, incomplete + + # There were no unparsed arguments, the command may be a group that + # will provide command name completions. + return ctx.command, incomplete diff --git a/flask-server/venv/lib/python3.10/site-packages/click/termui.py b/flask-server/venv/lib/python3.10/site-packages/click/termui.py new file mode 100644 index 00000000..bfb2f5ae --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/termui.py @@ -0,0 +1,787 @@ +import inspect +import io +import itertools +import os +import sys +import typing as t +from gettext import gettext as _ + +from ._compat import isatty +from ._compat import strip_ansi +from ._compat import WIN +from .exceptions import Abort +from .exceptions import UsageError +from .globals import resolve_color_default +from .types import Choice +from .types import convert_type +from .types import ParamType +from .utils import echo +from .utils import LazyFile + +if t.TYPE_CHECKING: + from ._termui_impl import ProgressBar + +V = t.TypeVar("V") + +# The prompt functions to use. The doc tools currently override these +# functions to customize how they work. +visible_prompt_func: t.Callable[[str], str] = input + +_ansi_colors = { + "black": 30, + "red": 31, + "green": 32, + "yellow": 33, + "blue": 34, + "magenta": 35, + "cyan": 36, + "white": 37, + "reset": 39, + "bright_black": 90, + "bright_red": 91, + "bright_green": 92, + "bright_yellow": 93, + "bright_blue": 94, + "bright_magenta": 95, + "bright_cyan": 96, + "bright_white": 97, +} +_ansi_reset_all = "\033[0m" + + +def hidden_prompt_func(prompt: str) -> str: + import getpass + + return getpass.getpass(prompt) + + +def _build_prompt( + text: str, + suffix: str, + show_default: bool = False, + default: t.Optional[t.Any] = None, + show_choices: bool = True, + type: t.Optional[ParamType] = None, +) -> str: + prompt = text + if type is not None and show_choices and isinstance(type, Choice): + prompt += f" ({', '.join(map(str, type.choices))})" + if default is not None and show_default: + prompt = f"{prompt} [{_format_default(default)}]" + return f"{prompt}{suffix}" + + +def _format_default(default: t.Any) -> t.Any: + if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): + return default.name # type: ignore + + return default + + +def prompt( + text: str, + default: t.Optional[t.Any] = None, + hide_input: bool = False, + confirmation_prompt: t.Union[bool, str] = False, + type: t.Optional[t.Union[ParamType, t.Any]] = None, + value_proc: t.Optional[t.Callable[[str], t.Any]] = None, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, + show_choices: bool = True, +) -> t.Any: + """Prompts a user for input. This is a convenience function that can + be used to prompt a user for input later. + + If the user aborts the input by sending an interrupt signal, this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the text to show for the prompt. + :param default: the default value to use if no input happens. If this + is not given it will prompt until it's aborted. + :param hide_input: if this is set to true then the input value will + be hidden. + :param confirmation_prompt: Prompt a second time to confirm the + value. Can be set to a string instead of ``True`` to customize + the message. + :param type: the type to use to check the value against. + :param value_proc: if this parameter is provided it's a function that + is invoked instead of the type conversion to + convert a value. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + :param show_choices: Show or hide choices if the passed type is a Choice. + For example if type is a Choice of either day or week, + show_choices is true and text is "Group by" then the + prompt will be "Group by (day, week): ". + + .. versionadded:: 8.0 + ``confirmation_prompt`` can be a custom string. + + .. versionadded:: 7.0 + Added the ``show_choices`` parameter. + + .. versionadded:: 6.0 + Added unicode support for cmd.exe on Windows. + + .. versionadded:: 4.0 + Added the `err` parameter. + + """ + + def prompt_func(text: str) -> str: + f = hidden_prompt_func if hide_input else visible_prompt_func + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(text.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + return f(" ") + except (KeyboardInterrupt, EOFError): + # getpass doesn't print a newline if the user aborts input with ^C. + # Allegedly this behavior is inherited from getpass(3). + # A doc bug has been filed at https://bugs.python.org/issue24711 + if hide_input: + echo(None, err=err) + raise Abort() from None + + if value_proc is None: + value_proc = convert_type(type, default) + + prompt = _build_prompt( + text, prompt_suffix, show_default, default, show_choices, type + ) + + if confirmation_prompt: + if confirmation_prompt is True: + confirmation_prompt = _("Repeat for confirmation") + + confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) + + while True: + while True: + value = prompt_func(prompt) + if value: + break + elif default is not None: + value = default + break + try: + result = value_proc(value) + except UsageError as e: + if hide_input: + echo(_("Error: The value you entered was invalid."), err=err) + else: + echo(_("Error: {e.message}").format(e=e), err=err) # noqa: B306 + continue + if not confirmation_prompt: + return result + while True: + value2 = prompt_func(confirmation_prompt) + is_empty = not value and not value2 + if value2 or is_empty: + break + if value == value2: + return result + echo(_("Error: The two entered values do not match."), err=err) + + +def confirm( + text: str, + default: t.Optional[bool] = False, + abort: bool = False, + prompt_suffix: str = ": ", + show_default: bool = True, + err: bool = False, +) -> bool: + """Prompts for confirmation (yes/no question). + + If the user aborts the input by sending a interrupt signal this + function will catch it and raise a :exc:`Abort` exception. + + :param text: the question to ask. + :param default: The default value to use when no input is given. If + ``None``, repeat until input is given. + :param abort: if this is set to `True` a negative answer aborts the + exception by raising :exc:`Abort`. + :param prompt_suffix: a suffix that should be added to the prompt. + :param show_default: shows or hides the default value in the prompt. + :param err: if set to true the file defaults to ``stderr`` instead of + ``stdout``, the same as with echo. + + .. versionchanged:: 8.0 + Repeat until input is given if ``default`` is ``None``. + + .. versionadded:: 4.0 + Added the ``err`` parameter. + """ + prompt = _build_prompt( + text, + prompt_suffix, + show_default, + "y/n" if default is None else ("Y/n" if default else "y/N"), + ) + + while True: + try: + # Write the prompt separately so that we get nice + # coloring through colorama on Windows + echo(prompt.rstrip(" "), nl=False, err=err) + # Echo a space to stdout to work around an issue where + # readline causes backspace to clear the whole line. + value = visible_prompt_func(" ").lower().strip() + except (KeyboardInterrupt, EOFError): + raise Abort() from None + if value in ("y", "yes"): + rv = True + elif value in ("n", "no"): + rv = False + elif default is not None and value == "": + rv = default + else: + echo(_("Error: invalid input"), err=err) + continue + break + if abort and not rv: + raise Abort() + return rv + + +def echo_via_pager( + text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], + color: t.Optional[bool] = None, +) -> None: + """This function takes a text and shows it via an environment specific + pager on stdout. + + .. versionchanged:: 3.0 + Added the `color` flag. + + :param text_or_generator: the text to page, or alternatively, a + generator emitting the text to page. + :param color: controls if the pager supports ANSI colors or not. The + default is autodetection. + """ + color = resolve_color_default(color) + + if inspect.isgeneratorfunction(text_or_generator): + i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() + elif isinstance(text_or_generator, str): + i = [text_or_generator] + else: + i = iter(t.cast(t.Iterable[str], text_or_generator)) + + # convert every element of i to a text type if necessary + text_generator = (el if isinstance(el, str) else str(el) for el in i) + + from ._termui_impl import pager + + return pager(itertools.chain(text_generator, "\n"), color) + + +def progressbar( + iterable: t.Optional[t.Iterable[V]] = None, + length: t.Optional[int] = None, + label: t.Optional[str] = None, + show_eta: bool = True, + show_percent: t.Optional[bool] = None, + show_pos: bool = False, + item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, + fill_char: str = "#", + empty_char: str = "-", + bar_template: str = "%(label)s [%(bar)s] %(info)s", + info_sep: str = " ", + width: int = 36, + file: t.Optional[t.TextIO] = None, + color: t.Optional[bool] = None, + update_min_steps: int = 1, +) -> "ProgressBar[V]": + """This function creates an iterable context manager that can be used + to iterate over something while showing a progress bar. It will + either iterate over the `iterable` or `length` items (that are counted + up). While iteration happens, this function will print a rendered + progress bar to the given `file` (defaults to stdout) and will attempt + to calculate remaining time and more. By default, this progress bar + will not be rendered if the file is not a terminal. + + The context manager creates the progress bar. When the context + manager is entered the progress bar is already created. With every + iteration over the progress bar, the iterable passed to the bar is + advanced and the bar is updated. When the context manager exits, + a newline is printed and the progress bar is finalized on screen. + + Note: The progress bar is currently designed for use cases where the + total progress can be expected to take at least several seconds. + Because of this, the ProgressBar class object won't display + progress that is considered too fast, and progress where the time + between steps is less than a second. + + No printing must happen or the progress bar will be unintentionally + destroyed. + + Example usage:: + + with progressbar(items) as bar: + for item in bar: + do_something_with(item) + + Alternatively, if no iterable is specified, one can manually update the + progress bar through the `update()` method instead of directly + iterating over the progress bar. The update method accepts the number + of steps to increment the bar with:: + + with progressbar(length=chunks.total_bytes) as bar: + for chunk in chunks: + process_chunk(chunk) + bar.update(chunks.bytes) + + The ``update()`` method also takes an optional value specifying the + ``current_item`` at the new position. This is useful when used + together with ``item_show_func`` to customize the output for each + manual step:: + + with click.progressbar( + length=total_size, + label='Unzipping archive', + item_show_func=lambda a: a.filename + ) as bar: + for archive in zip_file: + archive.extract() + bar.update(archive.size, archive) + + :param iterable: an iterable to iterate over. If not provided the length + is required. + :param length: the number of items to iterate over. By default the + progressbar will attempt to ask the iterator about its + length, which might or might not work. If an iterable is + also provided this parameter can be used to override the + length. If an iterable is not provided the progress bar + will iterate over a range of that length. + :param label: the label to show next to the progress bar. + :param show_eta: enables or disables the estimated time display. This is + automatically disabled if the length cannot be + determined. + :param show_percent: enables or disables the percentage display. The + default is `True` if the iterable has a length or + `False` if not. + :param show_pos: enables or disables the absolute position display. The + default is `False`. + :param item_show_func: A function called with the current item which + can return a string to show next to the progress bar. If the + function returns ``None`` nothing is shown. The current item can + be ``None``, such as when entering and exiting the bar. + :param fill_char: the character to use to show the filled part of the + progress bar. + :param empty_char: the character to use to show the non-filled part of + the progress bar. + :param bar_template: the format string to use as template for the bar. + The parameters in it are ``label`` for the label, + ``bar`` for the progress bar and ``info`` for the + info section. + :param info_sep: the separator between multiple info items (eta etc.) + :param width: the width of the progress bar in characters, 0 means full + terminal width + :param file: The file to write to. If this is not a terminal then + only the label is printed. + :param color: controls if the terminal supports ANSI colors or not. The + default is autodetection. This is only needed if ANSI + codes are included anywhere in the progress bar output + which is not the case by default. + :param update_min_steps: Render only when this many updates have + completed. This allows tuning for very fast iterators. + + .. versionchanged:: 8.0 + Output is shown even if execution time is less than 0.5 seconds. + + .. versionchanged:: 8.0 + ``item_show_func`` shows the current item, not the previous one. + + .. versionchanged:: 8.0 + Labels are echoed if the output is not a TTY. Reverts a change + in 7.0 that removed all output. + + .. versionadded:: 8.0 + Added the ``update_min_steps`` parameter. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. Added the ``update`` method to + the object. + + .. versionadded:: 2.0 + """ + from ._termui_impl import ProgressBar + + color = resolve_color_default(color) + return ProgressBar( + iterable=iterable, + length=length, + show_eta=show_eta, + show_percent=show_percent, + show_pos=show_pos, + item_show_func=item_show_func, + fill_char=fill_char, + empty_char=empty_char, + bar_template=bar_template, + info_sep=info_sep, + file=file, + label=label, + width=width, + color=color, + update_min_steps=update_min_steps, + ) + + +def clear() -> None: + """Clears the terminal screen. This will have the effect of clearing + the whole visible space of the terminal and moving the cursor to the + top left. This does not do anything if not connected to a terminal. + + .. versionadded:: 2.0 + """ + if not isatty(sys.stdout): + return + if WIN: + os.system("cls") + else: + sys.stdout.write("\033[2J\033[1;1H") + + +def _interpret_color( + color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 +) -> str: + if isinstance(color, int): + return f"{38 + offset};5;{color:d}" + + if isinstance(color, (tuple, list)): + r, g, b = color + return f"{38 + offset};2;{r:d};{g:d};{b:d}" + + return str(_ansi_colors[color] + offset) + + +def style( + text: t.Any, + fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, + bold: t.Optional[bool] = None, + dim: t.Optional[bool] = None, + underline: t.Optional[bool] = None, + overline: t.Optional[bool] = None, + italic: t.Optional[bool] = None, + blink: t.Optional[bool] = None, + reverse: t.Optional[bool] = None, + strikethrough: t.Optional[bool] = None, + reset: bool = True, +) -> str: + """Styles a text with ANSI styles and returns the new string. By + default the styling is self contained which means that at the end + of the string a reset code is issued. This can be prevented by + passing ``reset=False``. + + Examples:: + + click.echo(click.style('Hello World!', fg='green')) + click.echo(click.style('ATTENTION!', blink=True)) + click.echo(click.style('Some things', reverse=True, fg='cyan')) + click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) + + Supported color names: + + * ``black`` (might be a gray) + * ``red`` + * ``green`` + * ``yellow`` (might be an orange) + * ``blue`` + * ``magenta`` + * ``cyan`` + * ``white`` (might be light gray) + * ``bright_black`` + * ``bright_red`` + * ``bright_green`` + * ``bright_yellow`` + * ``bright_blue`` + * ``bright_magenta`` + * ``bright_cyan`` + * ``bright_white`` + * ``reset`` (reset the color code only) + + If the terminal supports it, color may also be specified as: + + - An integer in the interval [0, 255]. The terminal must support + 8-bit/256-color mode. + - An RGB tuple of three integers in [0, 255]. The terminal must + support 24-bit/true-color mode. + + See https://en.wikipedia.org/wiki/ANSI_color and + https://gist.github.com/XVilka/8346728 for more information. + + :param text: the string to style with ansi codes. + :param fg: if provided this will become the foreground color. + :param bg: if provided this will become the background color. + :param bold: if provided this will enable or disable bold mode. + :param dim: if provided this will enable or disable dim mode. This is + badly supported. + :param underline: if provided this will enable or disable underline. + :param overline: if provided this will enable or disable overline. + :param italic: if provided this will enable or disable italic. + :param blink: if provided this will enable or disable blinking. + :param reverse: if provided this will enable or disable inverse + rendering (foreground becomes background and the + other way round). + :param strikethrough: if provided this will enable or disable + striking through text. + :param reset: by default a reset-all code is added at the end of the + string which means that styles do not carry over. This + can be disabled to compose styles. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. + + .. versionchanged:: 8.0 + Added support for 256 and RGB color codes. + + .. versionchanged:: 8.0 + Added the ``strikethrough``, ``italic``, and ``overline`` + parameters. + + .. versionchanged:: 7.0 + Added support for bright colors. + + .. versionadded:: 2.0 + """ + if not isinstance(text, str): + text = str(text) + + bits = [] + + if fg: + try: + bits.append(f"\033[{_interpret_color(fg)}m") + except KeyError: + raise TypeError(f"Unknown color {fg!r}") from None + + if bg: + try: + bits.append(f"\033[{_interpret_color(bg, 10)}m") + except KeyError: + raise TypeError(f"Unknown color {bg!r}") from None + + if bold is not None: + bits.append(f"\033[{1 if bold else 22}m") + if dim is not None: + bits.append(f"\033[{2 if dim else 22}m") + if underline is not None: + bits.append(f"\033[{4 if underline else 24}m") + if overline is not None: + bits.append(f"\033[{53 if overline else 55}m") + if italic is not None: + bits.append(f"\033[{3 if italic else 23}m") + if blink is not None: + bits.append(f"\033[{5 if blink else 25}m") + if reverse is not None: + bits.append(f"\033[{7 if reverse else 27}m") + if strikethrough is not None: + bits.append(f"\033[{9 if strikethrough else 29}m") + bits.append(text) + if reset: + bits.append(_ansi_reset_all) + return "".join(bits) + + +def unstyle(text: str) -> str: + """Removes ANSI styling information from a string. Usually it's not + necessary to use this function as Click's echo function will + automatically remove styling if necessary. + + .. versionadded:: 2.0 + + :param text: the text to remove style information from. + """ + return strip_ansi(text) + + +def secho( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.AnyStr]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, + **styles: t.Any, +) -> None: + """This function combines :func:`echo` and :func:`style` into one + call. As such the following two calls are the same:: + + click.secho('Hello World!', fg='green') + click.echo(click.style('Hello World!', fg='green')) + + All keyword arguments are forwarded to the underlying functions + depending on which one they go with. + + Non-string types will be converted to :class:`str`. However, + :class:`bytes` are passed directly to :meth:`echo` without applying + style. If you want to style bytes that represent text, call + :meth:`bytes.decode` first. + + .. versionchanged:: 8.0 + A non-string ``message`` is converted to a string. Bytes are + passed through without style applied. + + .. versionadded:: 2.0 + """ + if message is not None and not isinstance(message, (bytes, bytearray)): + message = style(message, **styles) + + return echo(message, file=file, nl=nl, err=err, color=color) + + +def edit( + text: t.Optional[t.AnyStr] = None, + editor: t.Optional[str] = None, + env: t.Optional[t.Mapping[str, str]] = None, + require_save: bool = True, + extension: str = ".txt", + filename: t.Optional[str] = None, +) -> t.Optional[t.AnyStr]: + r"""Edits the given text in the defined editor. If an editor is given + (should be the full path to the executable but the regular operating + system search path is used for finding the executable) it overrides + the detected editor. Optionally, some environment variables can be + used. If the editor is closed without changes, `None` is returned. In + case a file is edited directly the return value is always `None` and + `require_save` and `extension` are ignored. + + If the editor cannot be opened a :exc:`UsageError` is raised. + + Note for Windows: to simplify cross-platform usage, the newlines are + automatically converted from POSIX to Windows and vice versa. As such, + the message here will have ``\n`` as newline markers. + + :param text: the text to edit. + :param editor: optionally the editor to use. Defaults to automatic + detection. + :param env: environment variables to forward to the editor. + :param require_save: if this is true, then not saving in the editor + will make the return value become `None`. + :param extension: the extension to tell the editor about. This defaults + to `.txt` but changing this might change syntax + highlighting. + :param filename: if provided it will edit this file instead of the + provided text contents. It will not use a temporary + file as an indirection in that case. + """ + from ._termui_impl import Editor + + ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) + + if filename is None: + return ed.edit(text) + + ed.edit_file(filename) + return None + + +def launch(url: str, wait: bool = False, locate: bool = False) -> int: + """This function launches the given URL (or filename) in the default + viewer application for this file type. If this is an executable, it + might launch the executable in a new session. The return value is + the exit code of the launched application. Usually, ``0`` indicates + success. + + Examples:: + + click.launch('https://click.palletsprojects.com/') + click.launch('/my/downloaded/file', locate=True) + + .. versionadded:: 2.0 + + :param url: URL or filename of the thing to launch. + :param wait: Wait for the program to exit before returning. This + only works if the launched program blocks. In particular, + ``xdg-open`` on Linux does not block. + :param locate: if this is set to `True` then instead of launching the + application associated with the URL it will attempt to + launch a file manager with the file located. This + might have weird effects if the URL does not point to + the filesystem. + """ + from ._termui_impl import open_url + + return open_url(url, wait=wait, locate=locate) + + +# If this is provided, getchar() calls into this instead. This is used +# for unittesting purposes. +_getchar: t.Optional[t.Callable[[bool], str]] = None + + +def getchar(echo: bool = False) -> str: + """Fetches a single character from the terminal and returns it. This + will always return a unicode character and under certain rare + circumstances this might return more than one character. The + situations which more than one character is returned is when for + whatever reason multiple characters end up in the terminal buffer or + standard input was not actually a terminal. + + Note that this will always read from the terminal, even if something + is piped into the standard input. + + Note for Windows: in rare cases when typing non-ASCII characters, this + function might wait for a second character and then return both at once. + This is because certain Unicode characters look like special-key markers. + + .. versionadded:: 2.0 + + :param echo: if set to `True`, the character read will also show up on + the terminal. The default is to not show it. + """ + global _getchar + + if _getchar is None: + from ._termui_impl import getchar as f + + _getchar = f + + return _getchar(echo) + + +def raw_terminal() -> t.ContextManager[int]: + from ._termui_impl import raw_terminal as f + + return f() + + +def pause(info: t.Optional[str] = None, err: bool = False) -> None: + """This command stops execution and waits for the user to press any + key to continue. This is similar to the Windows batch "pause" + command. If the program is not run through a terminal, this command + will instead do nothing. + + .. versionadded:: 2.0 + + .. versionadded:: 4.0 + Added the `err` parameter. + + :param info: The message to print before pausing. Defaults to + ``"Press any key to continue..."``. + :param err: if set to message goes to ``stderr`` instead of + ``stdout``, the same as with echo. + """ + if not isatty(sys.stdin) or not isatty(sys.stdout): + return + + if info is None: + info = _("Press any key to continue...") + + try: + if info: + echo(info, nl=False, err=err) + try: + getchar() + except (KeyboardInterrupt, EOFError): + pass + finally: + if info: + echo(err=err) diff --git a/flask-server/venv/lib/python3.10/site-packages/click/testing.py b/flask-server/venv/lib/python3.10/site-packages/click/testing.py new file mode 100644 index 00000000..e395c2ed --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/testing.py @@ -0,0 +1,479 @@ +import contextlib +import io +import os +import shlex +import shutil +import sys +import tempfile +import typing as t +from types import TracebackType + +from . import formatting +from . import termui +from . import utils +from ._compat import _find_binary_reader + +if t.TYPE_CHECKING: + from .core import BaseCommand + + +class EchoingStdin: + def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: + self._input = input + self._output = output + self._paused = False + + def __getattr__(self, x: str) -> t.Any: + return getattr(self._input, x) + + def _echo(self, rv: bytes) -> bytes: + if not self._paused: + self._output.write(rv) + + return rv + + def read(self, n: int = -1) -> bytes: + return self._echo(self._input.read(n)) + + def read1(self, n: int = -1) -> bytes: + return self._echo(self._input.read1(n)) # type: ignore + + def readline(self, n: int = -1) -> bytes: + return self._echo(self._input.readline(n)) + + def readlines(self) -> t.List[bytes]: + return [self._echo(x) for x in self._input.readlines()] + + def __iter__(self) -> t.Iterator[bytes]: + return iter(self._echo(x) for x in self._input) + + def __repr__(self) -> str: + return repr(self._input) + + +@contextlib.contextmanager +def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: + if stream is None: + yield + else: + stream._paused = True + yield + stream._paused = False + + +class _NamedTextIOWrapper(io.TextIOWrapper): + def __init__( + self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any + ) -> None: + super().__init__(buffer, **kwargs) + self._name = name + self._mode = mode + + @property + def name(self) -> str: + return self._name + + @property + def mode(self) -> str: + return self._mode + + +def make_input_stream( + input: t.Optional[t.Union[str, bytes, t.IO]], charset: str +) -> t.BinaryIO: + # Is already an input stream. + if hasattr(input, "read"): + rv = _find_binary_reader(t.cast(t.IO, input)) + + if rv is not None: + return rv + + raise TypeError("Could not find binary reader for input stream.") + + if input is None: + input = b"" + elif isinstance(input, str): + input = input.encode(charset) + + return io.BytesIO(t.cast(bytes, input)) + + +class Result: + """Holds the captured result of an invoked CLI script.""" + + def __init__( + self, + runner: "CliRunner", + stdout_bytes: bytes, + stderr_bytes: t.Optional[bytes], + return_value: t.Any, + exit_code: int, + exception: t.Optional[BaseException], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = None, + ): + #: The runner that created the result + self.runner = runner + #: The standard output as bytes. + self.stdout_bytes = stdout_bytes + #: The standard error as bytes, or None if not available + self.stderr_bytes = stderr_bytes + #: The value returned from the invoked command. + #: + #: .. versionadded:: 8.0 + self.return_value = return_value + #: The exit code as integer. + self.exit_code = exit_code + #: The exception that happened if one did. + self.exception = exception + #: The traceback + self.exc_info = exc_info + + @property + def output(self) -> str: + """The (standard) output as unicode string.""" + return self.stdout + + @property + def stdout(self) -> str: + """The standard output as unicode string.""" + return self.stdout_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + @property + def stderr(self) -> str: + """The standard error as unicode string.""" + if self.stderr_bytes is None: + raise ValueError("stderr not separately captured") + return self.stderr_bytes.decode(self.runner.charset, "replace").replace( + "\r\n", "\n" + ) + + def __repr__(self) -> str: + exc_str = repr(self.exception) if self.exception else "okay" + return f"<{type(self).__name__} {exc_str}>" + + +class CliRunner: + """The CLI runner provides functionality to invoke a Click command line + script for unittesting purposes in a isolated environment. This only + works in single-threaded systems without any concurrency as it changes the + global interpreter state. + + :param charset: the character set for the input and output data. + :param env: a dictionary with environment variables for overriding. + :param echo_stdin: if this is set to `True`, then reading from stdin writes + to stdout. This is useful for showing examples in + some circumstances. Note that regular prompts + will automatically echo the input. + :param mix_stderr: if this is set to `False`, then stdout and stderr are + preserved as independent streams. This is useful for + Unix-philosophy apps that have predictable stdout and + noisy stderr, such that each may be measured + independently + """ + + def __init__( + self, + charset: str = "utf-8", + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + echo_stdin: bool = False, + mix_stderr: bool = True, + ) -> None: + self.charset = charset + self.env = env or {} + self.echo_stdin = echo_stdin + self.mix_stderr = mix_stderr + + def get_default_prog_name(self, cli: "BaseCommand") -> str: + """Given a command object it will return the default program name + for it. The default is the `name` attribute or ``"root"`` if not + set. + """ + return cli.name or "root" + + def make_env( + self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None + ) -> t.Mapping[str, t.Optional[str]]: + """Returns the environment overrides for invoking a script.""" + rv = dict(self.env) + if overrides: + rv.update(overrides) + return rv + + @contextlib.contextmanager + def isolation( + self, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + color: bool = False, + ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: + """A context manager that sets up the isolation for invoking of a + command line tool. This sets up stdin with the given input data + and `os.environ` with the overrides from the given dictionary. + This also rebinds some internals in Click to be mocked (like the + prompt functionality). + + This is automatically done in the :meth:`invoke` method. + + :param input: the input stream to put into sys.stdin. + :param env: the environment overrides as dictionary. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + ``stderr`` is opened with ``errors="backslashreplace"`` + instead of the default ``"strict"``. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + """ + bytes_input = make_input_stream(input, self.charset) + echo_input = None + + old_stdin = sys.stdin + old_stdout = sys.stdout + old_stderr = sys.stderr + old_forced_width = formatting.FORCED_WIDTH + formatting.FORCED_WIDTH = 80 + + env = self.make_env(env) + + bytes_output = io.BytesIO() + + if self.echo_stdin: + bytes_input = echo_input = t.cast( + t.BinaryIO, EchoingStdin(bytes_input, bytes_output) + ) + + sys.stdin = text_input = _NamedTextIOWrapper( + bytes_input, encoding=self.charset, name="", mode="r" + ) + + if self.echo_stdin: + # Force unbuffered reads, otherwise TextIOWrapper reads a + # large chunk which is echoed early. + text_input._CHUNK_SIZE = 1 # type: ignore + + sys.stdout = _NamedTextIOWrapper( + bytes_output, encoding=self.charset, name="", mode="w" + ) + + bytes_error = None + if self.mix_stderr: + sys.stderr = sys.stdout + else: + bytes_error = io.BytesIO() + sys.stderr = _NamedTextIOWrapper( + bytes_error, + encoding=self.charset, + name="", + mode="w", + errors="backslashreplace", + ) + + @_pause_echo(echo_input) # type: ignore + def visible_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(prompt or "") + val = text_input.readline().rstrip("\r\n") + sys.stdout.write(f"{val}\n") + sys.stdout.flush() + return val + + @_pause_echo(echo_input) # type: ignore + def hidden_input(prompt: t.Optional[str] = None) -> str: + sys.stdout.write(f"{prompt or ''}\n") + sys.stdout.flush() + return text_input.readline().rstrip("\r\n") + + @_pause_echo(echo_input) # type: ignore + def _getchar(echo: bool) -> str: + char = sys.stdin.read(1) + + if echo: + sys.stdout.write(char) + + sys.stdout.flush() + return char + + default_color = color + + def should_strip_ansi( + stream: t.Optional[t.IO] = None, color: t.Optional[bool] = None + ) -> bool: + if color is None: + return not default_color + return not color + + old_visible_prompt_func = termui.visible_prompt_func + old_hidden_prompt_func = termui.hidden_prompt_func + old__getchar_func = termui._getchar + old_should_strip_ansi = utils.should_strip_ansi # type: ignore + termui.visible_prompt_func = visible_input + termui.hidden_prompt_func = hidden_input + termui._getchar = _getchar + utils.should_strip_ansi = should_strip_ansi # type: ignore + + old_env = {} + try: + for key, value in env.items(): + old_env[key] = os.environ.get(key) + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + yield (bytes_output, bytes_error) + finally: + for key, value in old_env.items(): + if value is None: + try: + del os.environ[key] + except Exception: + pass + else: + os.environ[key] = value + sys.stdout = old_stdout + sys.stderr = old_stderr + sys.stdin = old_stdin + termui.visible_prompt_func = old_visible_prompt_func + termui.hidden_prompt_func = old_hidden_prompt_func + termui._getchar = old__getchar_func + utils.should_strip_ansi = old_should_strip_ansi # type: ignore + formatting.FORCED_WIDTH = old_forced_width + + def invoke( + self, + cli: "BaseCommand", + args: t.Optional[t.Union[str, t.Sequence[str]]] = None, + input: t.Optional[t.Union[str, bytes, t.IO]] = None, + env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, + catch_exceptions: bool = True, + color: bool = False, + **extra: t.Any, + ) -> Result: + """Invokes a command in an isolated environment. The arguments are + forwarded directly to the command line script, the `extra` keyword + arguments are passed to the :meth:`~clickpkg.Command.main` function of + the command. + + This returns a :class:`Result` object. + + :param cli: the command to invoke + :param args: the arguments to invoke. It may be given as an iterable + or a string. When given as string it will be interpreted + as a Unix shell command. More details at + :func:`shlex.split`. + :param input: the input data for `sys.stdin`. + :param env: the environment overrides. + :param catch_exceptions: Whether to catch any other exceptions than + ``SystemExit``. + :param extra: the keyword arguments to pass to :meth:`main`. + :param color: whether the output should contain color codes. The + application can still override this explicitly. + + .. versionchanged:: 8.0 + The result object has the ``return_value`` attribute with + the value returned from the invoked command. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionchanged:: 3.0 + Added the ``catch_exceptions`` parameter. + + .. versionchanged:: 3.0 + The result object has the ``exc_info`` attribute with the + traceback if available. + """ + exc_info = None + with self.isolation(input=input, env=env, color=color) as outstreams: + return_value = None + exception: t.Optional[BaseException] = None + exit_code = 0 + + if isinstance(args, str): + args = shlex.split(args) + + try: + prog_name = extra.pop("prog_name") + except KeyError: + prog_name = self.get_default_prog_name(cli) + + try: + return_value = cli.main(args=args or (), prog_name=prog_name, **extra) + except SystemExit as e: + exc_info = sys.exc_info() + e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) + + if e_code is None: + e_code = 0 + + if e_code != 0: + exception = e + + if not isinstance(e_code, int): + sys.stdout.write(str(e_code)) + sys.stdout.write("\n") + e_code = 1 + + exit_code = e_code + + except Exception as e: + if not catch_exceptions: + raise + exception = e + exit_code = 1 + exc_info = sys.exc_info() + finally: + sys.stdout.flush() + stdout = outstreams[0].getvalue() + if self.mix_stderr: + stderr = None + else: + stderr = outstreams[1].getvalue() # type: ignore + + return Result( + runner=self, + stdout_bytes=stdout, + stderr_bytes=stderr, + return_value=return_value, + exit_code=exit_code, + exception=exception, + exc_info=exc_info, # type: ignore + ) + + @contextlib.contextmanager + def isolated_filesystem( + self, temp_dir: t.Optional[t.Union[str, os.PathLike]] = None + ) -> t.Iterator[str]: + """A context manager that creates a temporary directory and + changes the current working directory to it. This isolates tests + that affect the contents of the CWD to prevent them from + interfering with each other. + + :param temp_dir: Create the temporary directory under this + directory. If given, the created directory is not removed + when exiting. + + .. versionchanged:: 8.0 + Added the ``temp_dir`` parameter. + """ + cwd = os.getcwd() + dt = tempfile.mkdtemp(dir=temp_dir) # type: ignore[type-var] + os.chdir(dt) + + try: + yield t.cast(str, dt) + finally: + os.chdir(cwd) + + if temp_dir is None: + try: + shutil.rmtree(dt) + except OSError: # noqa: B014 + pass diff --git a/flask-server/venv/lib/python3.10/site-packages/click/types.py b/flask-server/venv/lib/python3.10/site-packages/click/types.py new file mode 100644 index 00000000..b45ee53d --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/types.py @@ -0,0 +1,1073 @@ +import os +import stat +import typing as t +from datetime import datetime +from gettext import gettext as _ +from gettext import ngettext + +from ._compat import _get_argv_encoding +from ._compat import get_filesystem_encoding +from ._compat import open_stream +from .exceptions import BadParameter +from .utils import LazyFile +from .utils import safecall + +if t.TYPE_CHECKING: + import typing_extensions as te + from .core import Context + from .core import Parameter + from .shell_completion import CompletionItem + + +class ParamType: + """Represents the type of a parameter. Validates and converts values + from the command line or Python into the correct type. + + To implement a custom type, subclass and implement at least the + following: + + - The :attr:`name` class attribute must be set. + - Calling an instance of the type with ``None`` must return + ``None``. This is already implemented by default. + - :meth:`convert` must convert string values to the correct type. + - :meth:`convert` must accept values that are already the correct + type. + - It must be able to convert a value if the ``ctx`` and ``param`` + arguments are ``None``. This can occur when converting prompt + input. + """ + + is_composite: t.ClassVar[bool] = False + arity: t.ClassVar[int] = 1 + + #: the descriptive name of this type + name: str + + #: if a list of this type is expected and the value is pulled from a + #: string environment variable, this is what splits it up. `None` + #: means any whitespace. For all parameters the general rule is that + #: whitespace splits them up. The exception are paths and files which + #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on + #: Windows). + envvar_list_splitter: t.ClassVar[t.Optional[str]] = None + + def to_info_dict(self) -> t.Dict[str, t.Any]: + """Gather information that could be useful for a tool generating + user-facing documentation. + + Use :meth:`click.Context.to_info_dict` to traverse the entire + CLI structure. + + .. versionadded:: 8.0 + """ + # The class name without the "ParamType" suffix. + param_type = type(self).__name__.partition("ParamType")[0] + param_type = param_type.partition("ParameterType")[0] + + # Custom subclasses might not remember to set a name. + if hasattr(self, "name"): + name = self.name + else: + name = param_type + + return {"param_type": param_type, "name": name} + + def __call__( + self, + value: t.Any, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> t.Any: + if value is not None: + return self.convert(value, param, ctx) + + def get_metavar(self, param: "Parameter") -> t.Optional[str]: + """Returns the metavar default for this param if it provides one.""" + + def get_missing_message(self, param: "Parameter") -> t.Optional[str]: + """Optionally might return extra information about a missing + parameter. + + .. versionadded:: 2.0 + """ + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + """Convert the value to the correct type. This is not called if + the value is ``None`` (the missing value). + + This must accept string values from the command line, as well as + values that are already the correct type. It may also convert + other compatible types. + + The ``param`` and ``ctx`` arguments may be ``None`` in certain + situations, such as when converting prompt input. + + If the value cannot be converted, call :meth:`fail` with a + descriptive message. + + :param value: The value to convert. + :param param: The parameter that is using this type to convert + its value. May be ``None``. + :param ctx: The current context that arrived at this value. May + be ``None``. + """ + return value + + def split_envvar_value(self, rv: str) -> t.Sequence[str]: + """Given a value from an environment variable this splits it up + into small chunks depending on the defined envvar list splitter. + + If the splitter is set to `None`, which means that whitespace splits, + then leading and trailing whitespace is ignored. Otherwise, leading + and trailing splitters usually lead to empty items being included. + """ + return (rv or "").split(self.envvar_list_splitter) + + def fail( + self, + message: str, + param: t.Optional["Parameter"] = None, + ctx: t.Optional["Context"] = None, + ) -> "t.NoReturn": + """Helper method to fail with an invalid value message.""" + raise BadParameter(message, ctx=ctx, param=param) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a list of + :class:`~click.shell_completion.CompletionItem` objects for the + incomplete value. Most types do not provide completions, but + some do, and this allows custom types to provide custom + completions as well. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + return [] + + +class CompositeParamType(ParamType): + is_composite = True + + @property + def arity(self) -> int: # type: ignore + raise NotImplementedError() + + +class FuncParamType(ParamType): + def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: + self.name = func.__name__ + self.func = func + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["func"] = self.func + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self.func(value) + except ValueError: + try: + value = str(value) + except UnicodeError: + value = value.decode("utf-8", "replace") + + self.fail(value, param, ctx) + + +class UnprocessedParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + return value + + def __repr__(self) -> str: + return "UNPROCESSED" + + +class StringParamType(ParamType): + name = "text" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, bytes): + enc = _get_argv_encoding() + try: + value = value.decode(enc) + except UnicodeError: + fs_enc = get_filesystem_encoding() + if fs_enc != enc: + try: + value = value.decode(fs_enc) + except UnicodeError: + value = value.decode("utf-8", "replace") + else: + value = value.decode("utf-8", "replace") + return value + return str(value) + + def __repr__(self) -> str: + return "STRING" + + +class Choice(ParamType): + """The choice type allows a value to be checked against a fixed set + of supported values. All of these values have to be strings. + + You should only pass a list or tuple of choices. Other iterables + (like generators) may lead to surprising results. + + The resulting value will always be one of the originally passed choices + regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` + being specified. + + See :ref:`choice-opts` for an example. + + :param case_sensitive: Set to false to make choices case + insensitive. Defaults to true. + """ + + name = "choice" + + def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: + self.choices = choices + self.case_sensitive = case_sensitive + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["choices"] = self.choices + info_dict["case_sensitive"] = self.case_sensitive + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + choices_str = "|".join(self.choices) + + # Use curly braces to indicate a required argument. + if param.required and param.param_type_name == "argument": + return f"{{{choices_str}}}" + + # Use square braces to indicate an option or optional argument. + return f"[{choices_str}]" + + def get_missing_message(self, param: "Parameter") -> str: + return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + # Match through normalization and case sensitivity + # first do token_normalize_func, then lowercase + # preserve original `value` to produce an accurate message in + # `self.fail` + normed_value = value + normed_choices = {choice: choice for choice in self.choices} + + if ctx is not None and ctx.token_normalize_func is not None: + normed_value = ctx.token_normalize_func(value) + normed_choices = { + ctx.token_normalize_func(normed_choice): original + for normed_choice, original in normed_choices.items() + } + + if not self.case_sensitive: + normed_value = normed_value.casefold() + normed_choices = { + normed_choice.casefold(): original + for normed_choice, original in normed_choices.items() + } + + if normed_value in normed_choices: + return normed_choices[normed_value] + + choices_str = ", ".join(map(repr, self.choices)) + self.fail( + ngettext( + "{value!r} is not {choice}.", + "{value!r} is not one of {choices}.", + len(self.choices), + ).format(value=value, choice=choices_str, choices=choices_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return f"Choice({list(self.choices)})" + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Complete choices that start with the incomplete value. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + str_choices = map(str, self.choices) + + if self.case_sensitive: + matched = (c for c in str_choices if c.startswith(incomplete)) + else: + incomplete = incomplete.lower() + matched = (c for c in str_choices if c.lower().startswith(incomplete)) + + return [CompletionItem(c) for c in matched] + + +class DateTime(ParamType): + """The DateTime type converts date strings into `datetime` objects. + + The format strings which are checked are configurable, but default to some + common (non-timezone aware) ISO 8601 formats. + + When specifying *DateTime* formats, you should only pass a list or a tuple. + Other iterables, like generators, may lead to surprising results. + + The format strings are processed using ``datetime.strptime``, and this + consequently defines the format strings which are allowed. + + Parsing is tried using each format, in order, and the first format which + parses successfully is used. + + :param formats: A list or tuple of date format strings, in the order in + which they should be tried. Defaults to + ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, + ``'%Y-%m-%d %H:%M:%S'``. + """ + + name = "datetime" + + def __init__(self, formats: t.Optional[t.Sequence[str]] = None): + self.formats = formats or ["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S"] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["formats"] = self.formats + return info_dict + + def get_metavar(self, param: "Parameter") -> str: + return f"[{'|'.join(self.formats)}]" + + def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: + try: + return datetime.strptime(value, format) + except ValueError: + return None + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if isinstance(value, datetime): + return value + + for format in self.formats: + converted = self._try_to_convert_date(value, format) + + if converted is not None: + return converted + + formats_str = ", ".join(map(repr, self.formats)) + self.fail( + ngettext( + "{value!r} does not match the format {format}.", + "{value!r} does not match the formats {formats}.", + len(self.formats), + ).format(value=value, format=formats_str, formats=formats_str), + param, + ctx, + ) + + def __repr__(self) -> str: + return "DateTime" + + +class _NumberParamTypeBase(ParamType): + _number_class: t.ClassVar[t.Type] + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + return self._number_class(value) + except ValueError: + self.fail( + _("{value!r} is not a valid {number_type}.").format( + value=value, number_type=self.name + ), + param, + ctx, + ) + + +class _NumberRangeBase(_NumberParamTypeBase): + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + self.min = min + self.max = max + self.min_open = min_open + self.max_open = max_open + self.clamp = clamp + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + min=self.min, + max=self.max, + min_open=self.min_open, + max_open=self.max_open, + clamp=self.clamp, + ) + return info_dict + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import operator + + rv = super().convert(value, param, ctx) + lt_min: bool = self.min is not None and ( + operator.le if self.min_open else operator.lt + )(rv, self.min) + gt_max: bool = self.max is not None and ( + operator.ge if self.max_open else operator.gt + )(rv, self.max) + + if self.clamp: + if lt_min: + return self._clamp(self.min, 1, self.min_open) # type: ignore + + if gt_max: + return self._clamp(self.max, -1, self.max_open) # type: ignore + + if lt_min or gt_max: + self.fail( + _("{value} is not in the range {range}.").format( + value=rv, range=self._describe_range() + ), + param, + ctx, + ) + + return rv + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + """Find the valid value to clamp to bound in the given + direction. + + :param bound: The boundary value. + :param dir: 1 or -1 indicating the direction to move. + :param open: If true, the range does not include the bound. + """ + raise NotImplementedError + + def _describe_range(self) -> str: + """Describe the range for use in help text.""" + if self.min is None: + op = "<" if self.max_open else "<=" + return f"x{op}{self.max}" + + if self.max is None: + op = ">" if self.min_open else ">=" + return f"x{op}{self.min}" + + lop = "<" if self.min_open else "<=" + rop = "<" if self.max_open else "<=" + return f"{self.min}{lop}x{rop}{self.max}" + + def __repr__(self) -> str: + clamp = " clamped" if self.clamp else "" + return f"<{type(self).__name__} {self._describe_range()}{clamp}>" + + +class IntParamType(_NumberParamTypeBase): + name = "integer" + _number_class = int + + def __repr__(self) -> str: + return "INT" + + +class IntRange(_NumberRangeBase, IntParamType): + """Restrict an :data:`click.INT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "integer range" + + def _clamp( # type: ignore + self, bound: int, dir: "te.Literal[1, -1]", open: bool + ) -> int: + if not open: + return bound + + return bound + dir + + +class FloatParamType(_NumberParamTypeBase): + name = "float" + _number_class = float + + def __repr__(self) -> str: + return "FLOAT" + + +class FloatRange(_NumberRangeBase, FloatParamType): + """Restrict a :data:`click.FLOAT` value to a range of accepted + values. See :ref:`ranges`. + + If ``min`` or ``max`` are not passed, any value is accepted in that + direction. If ``min_open`` or ``max_open`` are enabled, the + corresponding boundary is not included in the range. + + If ``clamp`` is enabled, a value outside the range is clamped to the + boundary instead of failing. This is not supported if either + boundary is marked ``open``. + + .. versionchanged:: 8.0 + Added the ``min_open`` and ``max_open`` parameters. + """ + + name = "float range" + + def __init__( + self, + min: t.Optional[float] = None, + max: t.Optional[float] = None, + min_open: bool = False, + max_open: bool = False, + clamp: bool = False, + ) -> None: + super().__init__( + min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp + ) + + if (min_open or max_open) and clamp: + raise TypeError("Clamping is not supported for open bounds.") + + def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: + if not open: + return bound + + # Could use Python 3.9's math.nextafter here, but clamping an + # open float range doesn't seem to be particularly useful. It's + # left up to the user to write a callback to do it if needed. + raise RuntimeError("Clamping is not supported for open bounds.") + + +class BoolParamType(ParamType): + name = "boolean" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + if value in {False, True}: + return bool(value) + + norm = value.strip().lower() + + if norm in {"1", "true", "t", "yes", "y", "on"}: + return True + + if norm in {"0", "false", "f", "no", "n", "off"}: + return False + + self.fail( + _("{value!r} is not a valid boolean.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "BOOL" + + +class UUIDParameterType(ParamType): + name = "uuid" + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + import uuid + + if isinstance(value, uuid.UUID): + return value + + value = value.strip() + + try: + return uuid.UUID(value) + except ValueError: + self.fail( + _("{value!r} is not a valid UUID.").format(value=value), param, ctx + ) + + def __repr__(self) -> str: + return "UUID" + + +class File(ParamType): + """Declares a parameter to be a file for reading or writing. The file + is automatically closed once the context tears down (after the command + finished working). + + Files can be opened for reading or writing. The special value ``-`` + indicates stdin or stdout depending on the mode. + + By default, the file is opened for reading text data, but it can also be + opened in binary mode or for writing. The encoding parameter can be used + to force a specific encoding. + + The `lazy` flag controls if the file should be opened immediately or upon + first IO. The default is to be non-lazy for standard input and output + streams as well as files opened for reading, `lazy` otherwise. When opening a + file lazily for reading, it is still opened temporarily for validation, but + will not be held open until first IO. lazy is mainly useful when opening + for writing to avoid creating the file until it is needed. + + Starting with Click 2.0, files can also be opened atomically in which + case all writes go into a separate file in the same folder and upon + completion the file will be moved over to the original location. This + is useful if a file regularly read by other users is modified. + + See :ref:`file-args` for more information. + """ + + name = "filename" + envvar_list_splitter = os.path.pathsep + + def __init__( + self, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: t.Optional[bool] = None, + atomic: bool = False, + ) -> None: + self.mode = mode + self.encoding = encoding + self.errors = errors + self.lazy = lazy + self.atomic = atomic + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update(mode=self.mode, encoding=self.encoding) + return info_dict + + def resolve_lazy_flag(self, value: t.Any) -> bool: + if self.lazy is not None: + return self.lazy + if value == "-": + return False + elif "w" in self.mode: + return True + return False + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + try: + if hasattr(value, "read") or hasattr(value, "write"): + return value + + lazy = self.resolve_lazy_flag(value) + + if lazy: + f: t.IO = t.cast( + t.IO, + LazyFile( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ), + ) + + if ctx is not None: + ctx.call_on_close(f.close_intelligently) # type: ignore + + return f + + f, should_close = open_stream( + value, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + + # If a context is provided, we automatically close the file + # at the end of the context execution (or flush out). If a + # context does not exist, it's the caller's responsibility to + # properly close the file. This for instance happens when the + # type is used with prompts. + if ctx is not None: + if should_close: + ctx.call_on_close(safecall(f.close)) + else: + ctx.call_on_close(safecall(f.flush)) + + return f + except OSError as e: # noqa: B014 + self.fail(f"'{os.fsdecode(value)}': {e.strerror}", param, ctx) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide file path completions. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + return [CompletionItem(incomplete, type="file")] + + +class Path(ParamType): + """The ``Path`` type is similar to the :class:`File` type, but + returns the filename instead of an open file. Various checks can be + enabled to validate the type of file and permissions. + + :param exists: The file or directory needs to exist for the value to + be valid. If this is not set to ``True``, and the file does not + exist, then all further checks are silently skipped. + :param file_okay: Allow a file as a value. + :param dir_okay: Allow a directory as a value. + :param readable: if true, a readable check is performed. + :param writable: if true, a writable check is performed. + :param executable: if true, an executable check is performed. + :param resolve_path: Make the value absolute and resolve any + symlinks. A ``~`` is not expanded, as this is supposed to be + done by the shell only. + :param allow_dash: Allow a single dash as a value, which indicates + a standard stream (but does not open it). Use + :func:`~click.open_file` to handle opening this value. + :param path_type: Convert the incoming path value to this type. If + ``None``, keep Python's default, which is ``str``. Useful to + convert to :class:`pathlib.Path`. + + .. versionchanged:: 8.1 + Added the ``executable`` parameter. + + .. versionchanged:: 8.0 + Allow passing ``type=pathlib.Path``. + + .. versionchanged:: 6.0 + Added the ``allow_dash`` parameter. + """ + + envvar_list_splitter = os.path.pathsep + + def __init__( + self, + exists: bool = False, + file_okay: bool = True, + dir_okay: bool = True, + writable: bool = False, + readable: bool = True, + resolve_path: bool = False, + allow_dash: bool = False, + path_type: t.Optional[t.Type] = None, + executable: bool = False, + ): + self.exists = exists + self.file_okay = file_okay + self.dir_okay = dir_okay + self.readable = readable + self.writable = writable + self.executable = executable + self.resolve_path = resolve_path + self.allow_dash = allow_dash + self.type = path_type + + if self.file_okay and not self.dir_okay: + self.name = _("file") + elif self.dir_okay and not self.file_okay: + self.name = _("directory") + else: + self.name = _("path") + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict.update( + exists=self.exists, + file_okay=self.file_okay, + dir_okay=self.dir_okay, + writable=self.writable, + readable=self.readable, + allow_dash=self.allow_dash, + ) + return info_dict + + def coerce_path_result(self, rv: t.Any) -> t.Any: + if self.type is not None and not isinstance(rv, self.type): + if self.type is str: + rv = os.fsdecode(rv) + elif self.type is bytes: + rv = os.fsencode(rv) + else: + rv = self.type(rv) + + return rv + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + rv = value + + is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") + + if not is_dash: + if self.resolve_path: + # os.path.realpath doesn't resolve symlinks on Windows + # until Python 3.8. Use pathlib for now. + import pathlib + + rv = os.fsdecode(pathlib.Path(rv).resolve()) + + try: + st = os.stat(rv) + except OSError: + if not self.exists: + return self.coerce_path_result(rv) + self.fail( + _("{name} {filename!r} does not exist.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if not self.file_okay and stat.S_ISREG(st.st_mode): + self.fail( + _("{name} {filename!r} is a file.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + if not self.dir_okay and stat.S_ISDIR(st.st_mode): + self.fail( + _("{name} '{filename}' is a directory.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.readable and not os.access(rv, os.R_OK): + self.fail( + _("{name} {filename!r} is not readable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.writable and not os.access(rv, os.W_OK): + self.fail( + _("{name} {filename!r} is not writable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + if self.executable and not os.access(value, os.X_OK): + self.fail( + _("{name} {filename!r} is not executable.").format( + name=self.name.title(), filename=os.fsdecode(value) + ), + param, + ctx, + ) + + return self.coerce_path_result(rv) + + def shell_complete( + self, ctx: "Context", param: "Parameter", incomplete: str + ) -> t.List["CompletionItem"]: + """Return a special completion marker that tells the completion + system to use the shell to provide path completions for only + directories or any paths. + + :param ctx: Invocation context for this command. + :param param: The parameter that is requesting completion. + :param incomplete: Value being completed. May be empty. + + .. versionadded:: 8.0 + """ + from click.shell_completion import CompletionItem + + type = "dir" if self.dir_okay and not self.file_okay else "file" + return [CompletionItem(incomplete, type=type)] + + +class Tuple(CompositeParamType): + """The default behavior of Click is to apply a type on a value directly. + This works well in most cases, except for when `nargs` is set to a fixed + count and different types should be used for different items. In this + case the :class:`Tuple` type can be used. This type can only be used + if `nargs` is set to a fixed number. + + For more information see :ref:`tuple-type`. + + This can be selected by using a Python tuple literal as a type. + + :param types: a list of types that should be used for the tuple items. + """ + + def __init__(self, types: t.Sequence[t.Union[t.Type, ParamType]]) -> None: + self.types = [convert_type(ty) for ty in types] + + def to_info_dict(self) -> t.Dict[str, t.Any]: + info_dict = super().to_info_dict() + info_dict["types"] = [t.to_info_dict() for t in self.types] + return info_dict + + @property + def name(self) -> str: # type: ignore + return f"<{' '.join(ty.name for ty in self.types)}>" + + @property + def arity(self) -> int: # type: ignore + return len(self.types) + + def convert( + self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] + ) -> t.Any: + len_type = len(self.types) + len_value = len(value) + + if len_value != len_type: + self.fail( + ngettext( + "{len_type} values are required, but {len_value} was given.", + "{len_type} values are required, but {len_value} were given.", + len_value, + ).format(len_type=len_type, len_value=len_value), + param=param, + ctx=ctx, + ) + + return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) + + +def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: + """Find the most appropriate :class:`ParamType` for the given Python + type. If the type isn't provided, it can be inferred from a default + value. + """ + guessed_type = False + + if ty is None and default is not None: + if isinstance(default, (tuple, list)): + # If the default is empty, ty will remain None and will + # return STRING. + if default: + item = default[0] + + # A tuple of tuples needs to detect the inner types. + # Can't call convert recursively because that would + # incorrectly unwind the tuple to a single type. + if isinstance(item, (tuple, list)): + ty = tuple(map(type, item)) + else: + ty = type(item) + else: + ty = type(default) + + guessed_type = True + + if isinstance(ty, tuple): + return Tuple(ty) + + if isinstance(ty, ParamType): + return ty + + if ty is str or ty is None: + return STRING + + if ty is int: + return INT + + if ty is float: + return FLOAT + + if ty is bool: + return BOOL + + if guessed_type: + return STRING + + if __debug__: + try: + if issubclass(ty, ParamType): + raise AssertionError( + f"Attempted to use an uninstantiated parameter type ({ty})." + ) + except TypeError: + # ty is an instance (correct), so issubclass fails. + pass + + return FuncParamType(ty) + + +#: A dummy parameter type that just does nothing. From a user's +#: perspective this appears to just be the same as `STRING` but +#: internally no string conversion takes place if the input was bytes. +#: This is usually useful when working with file paths as they can +#: appear in bytes and unicode. +#: +#: For path related uses the :class:`Path` type is a better choice but +#: there are situations where an unprocessed type is useful which is why +#: it is is provided. +#: +#: .. versionadded:: 4.0 +UNPROCESSED = UnprocessedParamType() + +#: A unicode string parameter type which is the implicit default. This +#: can also be selected by using ``str`` as type. +STRING = StringParamType() + +#: An integer parameter. This can also be selected by using ``int`` as +#: type. +INT = IntParamType() + +#: A floating point value parameter. This can also be selected by using +#: ``float`` as type. +FLOAT = FloatParamType() + +#: A boolean parameter. This is the default for boolean flags. This can +#: also be selected by using ``bool`` as a type. +BOOL = BoolParamType() + +#: A UUID parameter. +UUID = UUIDParameterType() diff --git a/flask-server/venv/lib/python3.10/site-packages/click/utils.py b/flask-server/venv/lib/python3.10/site-packages/click/utils.py new file mode 100644 index 00000000..8283788a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/click/utils.py @@ -0,0 +1,580 @@ +import os +import re +import sys +import typing as t +from functools import update_wrapper +from types import ModuleType + +from ._compat import _default_text_stderr +from ._compat import _default_text_stdout +from ._compat import _find_binary_writer +from ._compat import auto_wrap_for_ansi +from ._compat import binary_streams +from ._compat import get_filesystem_encoding +from ._compat import open_stream +from ._compat import should_strip_ansi +from ._compat import strip_ansi +from ._compat import text_streams +from ._compat import WIN +from .globals import resolve_color_default + +if t.TYPE_CHECKING: + import typing_extensions as te + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def _posixify(name: str) -> str: + return "-".join(name.split()).lower() + + +def safecall(func: F) -> F: + """Wraps a function so that it swallows exceptions.""" + + def wrapper(*args, **kwargs): # type: ignore + try: + return func(*args, **kwargs) + except Exception: + pass + + return update_wrapper(t.cast(F, wrapper), func) + + +def make_str(value: t.Any) -> str: + """Converts a value into a valid string.""" + if isinstance(value, bytes): + try: + return value.decode(get_filesystem_encoding()) + except UnicodeError: + return value.decode("utf-8", "replace") + return str(value) + + +def make_default_short_help(help: str, max_length: int = 45) -> str: + """Returns a condensed version of help string.""" + # Consider only the first paragraph. + paragraph_end = help.find("\n\n") + + if paragraph_end != -1: + help = help[:paragraph_end] + + # Collapse newlines, tabs, and spaces. + words = help.split() + + if not words: + return "" + + # The first paragraph started with a "no rewrap" marker, ignore it. + if words[0] == "\b": + words = words[1:] + + total_length = 0 + last_index = len(words) - 1 + + for i, word in enumerate(words): + total_length += len(word) + (i > 0) + + if total_length > max_length: # too long, truncate + break + + if word[-1] == ".": # sentence end, truncate without "..." + return " ".join(words[: i + 1]) + + if total_length == max_length and i != last_index: + break # not at sentence end, truncate with "..." + else: + return " ".join(words) # no truncation needed + + # Account for the length of the suffix. + total_length += len("...") + + # remove words until the length is short enough + while i > 0: + total_length -= len(words[i]) + (i > 0) + + if total_length <= max_length: + break + + i -= 1 + + return " ".join(words[:i]) + "..." + + +class LazyFile: + """A lazy file works like a regular file but it does not fully open + the file but it does perform some basic checks early to see if the + filename parameter does make sense. This is useful for safely opening + files for writing. + """ + + def __init__( + self, + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + atomic: bool = False, + ): + self.name = filename + self.mode = mode + self.encoding = encoding + self.errors = errors + self.atomic = atomic + self._f: t.Optional[t.IO] + + if filename == "-": + self._f, self.should_close = open_stream(filename, mode, encoding, errors) + else: + if "r" in mode: + # Open and close the file in case we're opening it for + # reading so that we can catch at least some errors in + # some cases early. + open(filename, mode).close() + self._f = None + self.should_close = True + + def __getattr__(self, name: str) -> t.Any: + return getattr(self.open(), name) + + def __repr__(self) -> str: + if self._f is not None: + return repr(self._f) + return f"" + + def open(self) -> t.IO: + """Opens the file if it's not yet open. This call might fail with + a :exc:`FileError`. Not handling this error will produce an error + that Click shows. + """ + if self._f is not None: + return self._f + try: + rv, self.should_close = open_stream( + self.name, self.mode, self.encoding, self.errors, atomic=self.atomic + ) + except OSError as e: # noqa: E402 + from .exceptions import FileError + + raise FileError(self.name, hint=e.strerror) from e + self._f = rv + return rv + + def close(self) -> None: + """Closes the underlying file, no matter what.""" + if self._f is not None: + self._f.close() + + def close_intelligently(self) -> None: + """This function only closes the file if it was opened by the lazy + file wrapper. For instance this will never close stdin. + """ + if self.should_close: + self.close() + + def __enter__(self) -> "LazyFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close_intelligently() + + def __iter__(self) -> t.Iterator[t.AnyStr]: + self.open() + return iter(self._f) # type: ignore + + +class KeepOpenFile: + def __init__(self, file: t.IO) -> None: + self._file = file + + def __getattr__(self, name: str) -> t.Any: + return getattr(self._file, name) + + def __enter__(self) -> "KeepOpenFile": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + pass + + def __repr__(self) -> str: + return repr(self._file) + + def __iter__(self) -> t.Iterator[t.AnyStr]: + return iter(self._file) + + +def echo( + message: t.Optional[t.Any] = None, + file: t.Optional[t.IO[t.Any]] = None, + nl: bool = True, + err: bool = False, + color: t.Optional[bool] = None, +) -> None: + """Print a message and newline to stdout or a file. This should be + used instead of :func:`print` because it provides better support + for different data, files, and environments. + + Compared to :func:`print`, this does the following: + + - Ensures that the output encoding is not misconfigured on Linux. + - Supports Unicode in the Windows console. + - Supports writing to binary outputs, and supports writing bytes + to text outputs. + - Supports colors and styles on Windows. + - Removes ANSI color and style codes if the output does not look + like an interactive terminal. + - Always flushes the output. + + :param message: The string or bytes to output. Other objects are + converted to strings. + :param file: The file to write to. Defaults to ``stdout``. + :param err: Write to ``stderr`` instead of ``stdout``. + :param nl: Print a newline after the message. Enabled by default. + :param color: Force showing or hiding colors and other styles. By + default Click will remove color if the output does not look like + an interactive terminal. + + .. versionchanged:: 6.0 + Support Unicode output on the Windows console. Click does not + modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` + will still not support Unicode. + + .. versionchanged:: 4.0 + Added the ``color`` parameter. + + .. versionadded:: 3.0 + Added the ``err`` parameter. + + .. versionchanged:: 2.0 + Support colors on Windows if colorama is installed. + """ + if file is None: + if err: + file = _default_text_stderr() + else: + file = _default_text_stdout() + + # Convert non bytes/text into the native string type. + if message is not None and not isinstance(message, (str, bytes, bytearray)): + out: t.Optional[t.Union[str, bytes]] = str(message) + else: + out = message + + if nl: + out = out or "" + if isinstance(out, str): + out += "\n" + else: + out += b"\n" + + if not out: + file.flush() + return + + # If there is a message and the value looks like bytes, we manually + # need to find the binary stream and write the message in there. + # This is done separately so that most stream types will work as you + # would expect. Eg: you can write to StringIO for other cases. + if isinstance(out, (bytes, bytearray)): + binary_file = _find_binary_writer(file) + + if binary_file is not None: + file.flush() + binary_file.write(out) + binary_file.flush() + return + + # ANSI style code support. For no message or bytes, nothing happens. + # When outputting to a file instead of a terminal, strip codes. + else: + color = resolve_color_default(color) + + if should_strip_ansi(file, color): + out = strip_ansi(out) + elif WIN: + if auto_wrap_for_ansi is not None: + file = auto_wrap_for_ansi(file) # type: ignore + elif not color: + out = strip_ansi(out) + + file.write(out) # type: ignore + file.flush() + + +def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: + """Returns a system stream for byte processing. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + """ + opener = binary_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener() + + +def get_text_stream( + name: "te.Literal['stdin', 'stdout', 'stderr']", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", +) -> t.TextIO: + """Returns a system stream for text processing. This usually returns + a wrapped stream around a binary stream returned from + :func:`get_binary_stream` but it also can take shortcuts for already + correctly configured streams. + + :param name: the name of the stream to open. Valid names are ``'stdin'``, + ``'stdout'`` and ``'stderr'`` + :param encoding: overrides the detected default encoding. + :param errors: overrides the default error mode. + """ + opener = text_streams.get(name) + if opener is None: + raise TypeError(f"Unknown standard stream '{name}'") + return opener(encoding, errors) + + +def open_file( + filename: str, + mode: str = "r", + encoding: t.Optional[str] = None, + errors: t.Optional[str] = "strict", + lazy: bool = False, + atomic: bool = False, +) -> t.IO: + """Open a file, with extra behavior to handle ``'-'`` to indicate + a standard stream, lazy open on write, and atomic write. Similar to + the behavior of the :class:`~click.File` param type. + + If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is + wrapped so that using it in a context manager will not close it. + This makes it possible to use the function without accidentally + closing a standard stream: + + .. code-block:: python + + with open_file(filename) as f: + ... + + :param filename: The name of the file to open, or ``'-'`` for + ``stdin``/``stdout``. + :param mode: The mode in which to open the file. + :param encoding: The encoding to decode or encode a file opened in + text mode. + :param errors: The error handling mode. + :param lazy: Wait to open the file until it is accessed. For read + mode, the file is temporarily opened to raise access errors + early, then closed until it is read again. + :param atomic: Write to a temporary file and replace the given file + on close. + + .. versionadded:: 3.0 + """ + if lazy: + return t.cast(t.IO, LazyFile(filename, mode, encoding, errors, atomic=atomic)) + + f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) + + if not should_close: + f = t.cast(t.IO, KeepOpenFile(f)) + + return f + + +def format_filename( + filename: t.Union[str, bytes, os.PathLike], shorten: bool = False +) -> str: + """Formats a filename for user display. The main purpose of this + function is to ensure that the filename can be displayed at all. This + will decode the filename to unicode if necessary in a way that it will + not fail. Optionally, it can shorten the filename to not include the + full path to the filename. + + :param filename: formats a filename for UI display. This will also convert + the filename into unicode without failing. + :param shorten: this optionally shortens the filename to strip of the + path that leads up to it. + """ + if shorten: + filename = os.path.basename(filename) + + return os.fsdecode(filename) + + +def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: + r"""Returns the config folder for the application. The default behavior + is to return whatever is most appropriate for the operating system. + + To give you an idea, for an app called ``"Foo Bar"``, something like + the following folders could be returned: + + Mac OS X: + ``~/Library/Application Support/Foo Bar`` + Mac OS X (POSIX): + ``~/.foo-bar`` + Unix: + ``~/.config/foo-bar`` + Unix (POSIX): + ``~/.foo-bar`` + Windows (roaming): + ``C:\Users\\AppData\Roaming\Foo Bar`` + Windows (not roaming): + ``C:\Users\\AppData\Local\Foo Bar`` + + .. versionadded:: 2.0 + + :param app_name: the application name. This should be properly capitalized + and can contain whitespace. + :param roaming: controls if the folder should be roaming or not on Windows. + Has no affect otherwise. + :param force_posix: if this is set to `True` then on any POSIX system the + folder will be stored in the home folder with a leading + dot instead of the XDG config home or darwin's + application support folder. + """ + if WIN: + key = "APPDATA" if roaming else "LOCALAPPDATA" + folder = os.environ.get(key) + if folder is None: + folder = os.path.expanduser("~") + return os.path.join(folder, app_name) + if force_posix: + return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) + if sys.platform == "darwin": + return os.path.join( + os.path.expanduser("~/Library/Application Support"), app_name + ) + return os.path.join( + os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), + _posixify(app_name), + ) + + +class PacifyFlushWrapper: + """This wrapper is used to catch and suppress BrokenPipeErrors resulting + from ``.flush()`` being called on broken pipe during the shutdown/final-GC + of the Python interpreter. Notably ``.flush()`` is always called on + ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any + other cleanup code, and the case where the underlying file is not a broken + pipe, all calls and attributes are proxied. + """ + + def __init__(self, wrapped: t.IO) -> None: + self.wrapped = wrapped + + def flush(self) -> None: + try: + self.wrapped.flush() + except OSError as e: + import errno + + if e.errno != errno.EPIPE: + raise + + def __getattr__(self, attr: str) -> t.Any: + return getattr(self.wrapped, attr) + + +def _detect_program_name( + path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None +) -> str: + """Determine the command used to run the program, for use in help + text. If a file or entry point was executed, the file name is + returned. If ``python -m`` was used to execute a module or package, + ``python -m name`` is returned. + + This doesn't try to be too precise, the goal is to give a concise + name for help text. Files are only shown as their name without the + path. ``python`` is only shown for modules, and the full path to + ``sys.executable`` is not shown. + + :param path: The Python file being executed. Python puts this in + ``sys.argv[0]``, which is used by default. + :param _main: The ``__main__`` module. This should only be passed + during internal testing. + + .. versionadded:: 8.0 + Based on command args detection in the Werkzeug reloader. + + :meta private: + """ + if _main is None: + _main = sys.modules["__main__"] + + if not path: + path = sys.argv[0] + + # The value of __package__ indicates how Python was called. It may + # not exist if a setuptools script is installed as an egg. It may be + # set incorrectly for entry points created with pip on Windows. + if getattr(_main, "__package__", None) is None or ( + os.name == "nt" + and _main.__package__ == "" + and not os.path.exists(path) + and os.path.exists(f"{path}.exe") + ): + # Executed a file, like "python app.py". + return os.path.basename(path) + + # Executed a module, like "python -m example". + # Rewritten by Python from "-m script" to "/path/to/script.py". + # Need to look at main module to determine how it was executed. + py_module = t.cast(str, _main.__package__) + name = os.path.splitext(os.path.basename(path))[0] + + # A submodule like "example.cli". + if name != "__main__": + py_module = f"{py_module}.{name}" + + return f"python -m {py_module.lstrip('.')}" + + +def _expand_args( + args: t.Iterable[str], + *, + user: bool = True, + env: bool = True, + glob_recursive: bool = True, +) -> t.List[str]: + """Simulate Unix shell expansion with Python functions. + + See :func:`glob.glob`, :func:`os.path.expanduser`, and + :func:`os.path.expandvars`. + + This is intended for use on Windows, where the shell does not do any + expansion. It may not exactly match what a Unix shell would do. + + :param args: List of command line arguments to expand. + :param user: Expand user home directory. + :param env: Expand environment variables. + :param glob_recursive: ``**`` matches directories recursively. + + .. versionchanged:: 8.1 + Invalid glob patterns are treated as empty expansions rather + than raising an error. + + .. versionadded:: 8.0 + + :meta private: + """ + from glob import glob + + out = [] + + for arg in args: + if user: + arg = os.path.expanduser(arg) + + if env: + arg = os.path.expandvars(arg) + + try: + matches = glob(arg, recursive=glob_recursive) + except re.error: + matches = [] + + if not matches: + out.append(arg) + else: + out.extend(matches) + + return out diff --git a/flask-server/venv/lib/python3.10/site-packages/distutils-precedence.pth b/flask-server/venv/lib/python3.10/site-packages/distutils-precedence.pth new file mode 100644 index 00000000..7f009fe9 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/distutils-precedence.pth @@ -0,0 +1 @@ +import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__init__.py b/flask-server/venv/lib/python3.10/site-packages/flask/__init__.py new file mode 100644 index 00000000..463f55f2 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/__init__.py @@ -0,0 +1,71 @@ +from markupsafe import escape +from markupsafe import Markup + +from . import json as json +from .app import Flask as Flask +from .app import Request as Request +from .app import Response as Response +from .blueprints import Blueprint as Blueprint +from .config import Config as Config +from .ctx import after_this_request as after_this_request +from .ctx import copy_current_request_context as copy_current_request_context +from .ctx import has_app_context as has_app_context +from .ctx import has_request_context as has_request_context +from .globals import current_app as current_app +from .globals import g as g +from .globals import request as request +from .globals import session as session +from .helpers import abort as abort +from .helpers import flash as flash +from .helpers import get_flashed_messages as get_flashed_messages +from .helpers import get_template_attribute as get_template_attribute +from .helpers import make_response as make_response +from .helpers import redirect as redirect +from .helpers import send_file as send_file +from .helpers import send_from_directory as send_from_directory +from .helpers import stream_with_context as stream_with_context +from .helpers import url_for as url_for +from .json import jsonify as jsonify +from .signals import appcontext_popped as appcontext_popped +from .signals import appcontext_pushed as appcontext_pushed +from .signals import appcontext_tearing_down as appcontext_tearing_down +from .signals import before_render_template as before_render_template +from .signals import got_request_exception as got_request_exception +from .signals import message_flashed as message_flashed +from .signals import request_finished as request_finished +from .signals import request_started as request_started +from .signals import request_tearing_down as request_tearing_down +from .signals import signals_available as signals_available +from .signals import template_rendered as template_rendered +from .templating import render_template as render_template +from .templating import render_template_string as render_template_string +from .templating import stream_template as stream_template +from .templating import stream_template_string as stream_template_string + +__version__ = "2.2.3" + + +def __getattr__(name): + if name == "_app_ctx_stack": + import warnings + from .globals import __app_ctx_stack + + warnings.warn( + "'_app_ctx_stack' is deprecated and will be removed in Flask 2.3.", + DeprecationWarning, + stacklevel=2, + ) + return __app_ctx_stack + + if name == "_request_ctx_stack": + import warnings + from .globals import __request_ctx_stack + + warnings.warn( + "'_request_ctx_stack' is deprecated and will be removed in Flask 2.3.", + DeprecationWarning, + stacklevel=2, + ) + return __request_ctx_stack + + raise AttributeError(name) diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__main__.py b/flask-server/venv/lib/python3.10/site-packages/flask/__main__.py new file mode 100644 index 00000000..4e28416e --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/__main__.py @@ -0,0 +1,3 @@ +from .cli import main + +main() diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..fe1399b6 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__main__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__main__.cpython-310.pyc new file mode 100644 index 00000000..9aa931c8 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/__main__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/app.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/app.cpython-310.pyc new file mode 100644 index 00000000..952a2d9f Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/app.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/blueprints.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/blueprints.cpython-310.pyc new file mode 100644 index 00000000..96ea77e6 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/blueprints.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc new file mode 100644 index 00000000..0724359a Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/cli.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc new file mode 100644 index 00000000..7c42a4e2 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/config.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/ctx.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/ctx.cpython-310.pyc new file mode 100644 index 00000000..dff2e6f8 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/ctx.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc new file mode 100644 index 00000000..afa90b76 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/globals.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/globals.cpython-310.pyc new file mode 100644 index 00000000..748075fc Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/globals.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/helpers.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/helpers.cpython-310.pyc new file mode 100644 index 00000000..8e64d6a4 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/helpers.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc new file mode 100644 index 00000000..139634d0 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/logging.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/scaffold.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/scaffold.cpython-310.pyc new file mode 100644 index 00000000..dbda4897 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/scaffold.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc new file mode 100644 index 00000000..4f49dd6f Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/sessions.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc new file mode 100644 index 00000000..3e491cce Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/signals.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/templating.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/templating.cpython-310.pyc new file mode 100644 index 00000000..6eb3648f Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/templating.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc new file mode 100644 index 00000000..a3fe0e46 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/testing.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/typing.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/typing.cpython-310.pyc new file mode 100644 index 00000000..98bbc5e4 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/typing.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc new file mode 100644 index 00000000..e01bb0b7 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/views.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc new file mode 100644 index 00000000..ccfb9c68 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/flask/__pycache__/wrappers.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/app.py b/flask-server/venv/lib/python3.10/site-packages/flask/app.py new file mode 100644 index 00000000..0ac4bbb5 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/app.py @@ -0,0 +1,2551 @@ +import functools +import inspect +import json +import logging +import os +import sys +import typing as t +import weakref +from collections.abc import Iterator as _abc_Iterator +from datetime import timedelta +from itertools import chain +from threading import Lock +from types import TracebackType + +import click +from werkzeug.datastructures import Headers +from werkzeug.datastructures import ImmutableDict +from werkzeug.exceptions import Aborter +from werkzeug.exceptions import BadRequest +from werkzeug.exceptions import BadRequestKeyError +from werkzeug.exceptions import HTTPException +from werkzeug.exceptions import InternalServerError +from werkzeug.routing import BuildError +from werkzeug.routing import Map +from werkzeug.routing import MapAdapter +from werkzeug.routing import RequestRedirect +from werkzeug.routing import RoutingException +from werkzeug.routing import Rule +from werkzeug.serving import is_running_from_reloader +from werkzeug.urls import url_quote +from werkzeug.utils import redirect as _wz_redirect +from werkzeug.wrappers import Response as BaseResponse + +from . import cli +from . import typing as ft +from .config import Config +from .config import ConfigAttribute +from .ctx import _AppCtxGlobals +from .ctx import AppContext +from .ctx import RequestContext +from .globals import _cv_app +from .globals import _cv_request +from .globals import g +from .globals import request +from .globals import request_ctx +from .globals import session +from .helpers import _split_blueprint_path +from .helpers import get_debug_flag +from .helpers import get_flashed_messages +from .helpers import get_load_dotenv +from .helpers import locked_cached_property +from .json.provider import DefaultJSONProvider +from .json.provider import JSONProvider +from .logging import create_logger +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import find_package +from .scaffold import Scaffold +from .scaffold import setupmethod +from .sessions import SecureCookieSessionInterface +from .sessions import SessionInterface +from .signals import appcontext_tearing_down +from .signals import got_request_exception +from .signals import request_finished +from .signals import request_started +from .signals import request_tearing_down +from .templating import DispatchingJinjaLoader +from .templating import Environment +from .wrappers import Request +from .wrappers import Response + +if t.TYPE_CHECKING: # pragma: no cover + import typing_extensions as te + from .blueprints import Blueprint + from .testing import FlaskClient + from .testing import FlaskCliRunner + +T_before_first_request = t.TypeVar( + "T_before_first_request", bound=ft.BeforeFirstRequestCallable +) +T_shell_context_processor = t.TypeVar( + "T_shell_context_processor", bound=ft.ShellContextProcessorCallable +) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) + +if sys.version_info >= (3, 8): + iscoroutinefunction = inspect.iscoroutinefunction +else: + + def iscoroutinefunction(func: t.Any) -> bool: + while inspect.ismethod(func): + func = func.__func__ + + while isinstance(func, functools.partial): + func = func.func + + return inspect.iscoroutinefunction(func) + + +def _make_timedelta(value: t.Union[timedelta, int, None]) -> t.Optional[timedelta]: + if value is None or isinstance(value, timedelta): + return value + + return timedelta(seconds=value) + + +class Flask(Scaffold): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the :file:`__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea of what + belongs to your application. This name is used to find resources + on the filesystem, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in :file:`yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + .. versionadded:: 0.11 + The `root_path` parameter was added. + + .. versionadded:: 1.0 + The ``host_matching`` and ``static_host`` parameters were added. + + .. versionadded:: 1.0 + The ``subdomain_matching`` parameter was added. Subdomain + matching needs to be enabled manually now. Setting + :data:`SERVER_NAME` does not implicitly enable it. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: The folder with static files that is served at + ``static_url_path``. Relative to the application ``root_path`` + or an absolute path. Defaults to ``'static'``. + :param static_host: the host to use when adding the static route. + Defaults to None. Required when using ``host_matching=True`` + with a ``static_folder`` configured. + :param host_matching: set ``url_map.host_matching`` attribute. + Defaults to False. + :param subdomain_matching: consider the subdomain relative to + :data:`SERVER_NAME` when matching routes. Defaults to False. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to ``True`` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + :param root_path: The path to the root of the application files. + This should only be set manually when it can't be detected + automatically, such as for namespace packages. + """ + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class = Response + + #: The class of the object assigned to :attr:`aborter`, created by + #: :meth:`create_aborter`. That object is called by + #: :func:`flask.abort` to raise HTTP errors, and can be + #: called directly as well. + #: + #: Defaults to :class:`werkzeug.exceptions.Aborter`. + #: + #: .. versionadded:: 2.2 + aborter_class = Aborter + + #: The class that is used for the Jinja environment. + #: + #: .. versionadded:: 0.11 + jinja_environment = Environment + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on unexpected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is now application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + #: The class that is used for the ``config`` attribute of this app. + #: Defaults to :class:`~flask.Config`. + #: + #: Example use cases for a custom class: + #: + #: 1. Default values for certain config options. + #: 2. Access to config values through attributes in addition to keys. + #: + #: .. versionadded:: 0.11 + config_class = Config + + #: The testing flag. Set this to ``True`` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate test helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: ``TESTING`` configuration key. Defaults to ``False``. + testing = ConfigAttribute("TESTING") + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. + secret_key = ConfigAttribute("SECRET_KEY") + + @property + def session_cookie_name(self) -> str: + """The name of the cookie set by the session interface. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use ``app.config["SESSION_COOKIE_NAME"]`` + instead. + """ + import warnings + + warnings.warn( + "'session_cookie_name' is deprecated and will be removed in Flask 2.3. Use" + " 'SESSION_COOKIE_NAME' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self.config["SESSION_COOKIE_NAME"] + + @session_cookie_name.setter + def session_cookie_name(self, value: str) -> None: + import warnings + + warnings.warn( + "'session_cookie_name' is deprecated and will be removed in Flask 2.3. Use" + " 'SESSION_COOKIE_NAME' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.config["SESSION_COOKIE_NAME"] = value + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute( + "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta + ) + + @property + def send_file_max_age_default(self) -> t.Optional[timedelta]: + """The default value for ``max_age`` for :func:`~flask.send_file`. The default + is ``None``, which tells the browser to use conditional requests instead of a + timed cache. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use + ``app.config["SEND_FILE_MAX_AGE_DEFAULT"]`` instead. + + .. versionchanged:: 2.0 + Defaults to ``None`` instead of 12 hours. + """ + import warnings + + warnings.warn( + "'send_file_max_age_default' is deprecated and will be removed in Flask" + " 2.3. Use 'SEND_FILE_MAX_AGE_DEFAULT' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + return _make_timedelta(self.config["SEND_FILE_MAX_AGE_DEFAULT"]) + + @send_file_max_age_default.setter + def send_file_max_age_default(self, value: t.Union[int, timedelta, None]) -> None: + import warnings + + warnings.warn( + "'send_file_max_age_default' is deprecated and will be removed in Flask" + " 2.3. Use 'SEND_FILE_MAX_AGE_DEFAULT' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.config["SEND_FILE_MAX_AGE_DEFAULT"] = _make_timedelta(value) + + @property + def use_x_sendfile(self) -> bool: + """Enable this to use the ``X-Sendfile`` feature, assuming the server supports + it, from :func:`~flask.send_file`. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use ``app.config["USE_X_SENDFILE"]`` instead. + """ + import warnings + + warnings.warn( + "'use_x_sendfile' is deprecated and will be removed in Flask 2.3. Use" + " 'USE_X_SENDFILE' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self.config["USE_X_SENDFILE"] + + @use_x_sendfile.setter + def use_x_sendfile(self, value: bool) -> None: + import warnings + + warnings.warn( + "'use_x_sendfile' is deprecated and will be removed in Flask 2.3. Use" + " 'USE_X_SENDFILE' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.config["USE_X_SENDFILE"] = value + + _json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None + _json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None + + @property # type: ignore[override] + def json_encoder(self) -> t.Type[json.JSONEncoder]: + """The JSON encoder class to use. Defaults to + :class:`~flask.json.JSONEncoder`. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Customize + :attr:`json_provider_class` instead. + + .. versionadded:: 0.10 + """ + import warnings + + warnings.warn( + "'app.json_encoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + + if self._json_encoder is None: + from . import json + + return json.JSONEncoder + + return self._json_encoder + + @json_encoder.setter + def json_encoder(self, value: t.Type[json.JSONEncoder]) -> None: + import warnings + + warnings.warn( + "'app.json_encoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + self._json_encoder = value + + @property # type: ignore[override] + def json_decoder(self) -> t.Type[json.JSONDecoder]: + """The JSON decoder class to use. Defaults to + :class:`~flask.json.JSONDecoder`. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Customize + :attr:`json_provider_class` instead. + + .. versionadded:: 0.10 + """ + import warnings + + warnings.warn( + "'app.json_decoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + + if self._json_decoder is None: + from . import json + + return json.JSONDecoder + + return self._json_decoder + + @json_decoder.setter + def json_decoder(self, value: t.Type[json.JSONDecoder]) -> None: + import warnings + + warnings.warn( + "'app.json_decoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + self._json_decoder = value + + json_provider_class: t.Type[JSONProvider] = DefaultJSONProvider + """A subclass of :class:`~flask.json.provider.JSONProvider`. An + instance is created and assigned to :attr:`app.json` when creating + the app. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses + Python's built-in :mod:`json` library. A different provider can use + a different JSON library. + + .. versionadded:: 2.2 + """ + + #: Options that are passed to the Jinja environment in + #: :meth:`create_jinja_environment`. Changing these options after + #: the environment is created (accessing :attr:`jinja_env`) will + #: have no effect. + #: + #: .. versionchanged:: 1.1.0 + #: This is a ``dict`` instead of an ``ImmutableDict`` to allow + #: easier configuration. + #: + jinja_options: dict = {} + + #: Default configuration parameters. + default_config = ImmutableDict( + { + "ENV": None, + "DEBUG": None, + "TESTING": False, + "PROPAGATE_EXCEPTIONS": None, + "SECRET_KEY": None, + "PERMANENT_SESSION_LIFETIME": timedelta(days=31), + "USE_X_SENDFILE": False, + "SERVER_NAME": None, + "APPLICATION_ROOT": "/", + "SESSION_COOKIE_NAME": "session", + "SESSION_COOKIE_DOMAIN": None, + "SESSION_COOKIE_PATH": None, + "SESSION_COOKIE_HTTPONLY": True, + "SESSION_COOKIE_SECURE": False, + "SESSION_COOKIE_SAMESITE": None, + "SESSION_REFRESH_EACH_REQUEST": True, + "MAX_CONTENT_LENGTH": None, + "SEND_FILE_MAX_AGE_DEFAULT": None, + "TRAP_BAD_REQUEST_ERRORS": None, + "TRAP_HTTP_EXCEPTIONS": False, + "EXPLAIN_TEMPLATE_LOADING": False, + "PREFERRED_URL_SCHEME": "http", + "JSON_AS_ASCII": None, + "JSON_SORT_KEYS": None, + "JSONIFY_PRETTYPRINT_REGULAR": None, + "JSONIFY_MIMETYPE": None, + "TEMPLATES_AUTO_RELOAD": None, + "MAX_COOKIE_SIZE": 4093, + } + ) + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: The map object to use for storing the URL rules and routing + #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. + #: + #: .. versionadded:: 1.1.0 + url_map_class = Map + + #: The :meth:`test_client` method creates an instance of this test + #: client class. Defaults to :class:`~flask.testing.FlaskClient`. + #: + #: .. versionadded:: 0.7 + test_client_class: t.Optional[t.Type["FlaskClient"]] = None + + #: The :class:`~click.testing.CliRunner` subclass, by default + #: :class:`~flask.testing.FlaskCliRunner` that is used by + #: :meth:`test_cli_runner`. Its ``__init__`` method should take a + #: Flask app object as the first argument. + #: + #: .. versionadded:: 1.0 + test_cli_runner_class: t.Optional[t.Type["FlaskCliRunner"]] = None + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface: SessionInterface = SecureCookieSessionInterface() + + def __init__( + self, + import_name: str, + static_url_path: t.Optional[str] = None, + static_folder: t.Optional[t.Union[str, os.PathLike]] = "static", + static_host: t.Optional[str] = None, + host_matching: bool = False, + subdomain_matching: bool = False, + template_folder: t.Optional[t.Union[str, os.PathLike]] = "templates", + instance_path: t.Optional[str] = None, + instance_relative_config: bool = False, + root_path: t.Optional[str] = None, + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError( + "If an instance path is provided it must be absolute." + " A relative path was given instead." + ) + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + #: An instance of :attr:`aborter_class` created by + #: :meth:`make_aborter`. This is called by :func:`flask.abort` + #: to raise HTTP errors, and can be called directly as well. + #: + #: .. versionadded:: 2.2 + #: Moved from ``flask.abort``, which calls this object. + self.aborter = self.make_aborter() + + self.json: JSONProvider = self.json_provider_class(self) + """Provides access to JSON methods. Functions in ``flask.json`` + will call methods on this provider when the application context + is active. Used for handling JSON requests and responses. + + An instance of :attr:`json_provider_class`. Can be customized by + changing that attribute on a subclass, or by assigning to this + attribute afterwards. + + The default, :class:`~flask.json.provider.DefaultJSONProvider`, + uses Python's built-in :mod:`json` library. A different provider + can use a different JSON library. + + .. versionadded:: 2.2 + """ + + #: A list of functions that are called by + #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function is called + #: with ``error``, ``endpoint`` and ``values``. If a function + #: returns ``None`` or raises a ``BuildError``, it is skipped. + #: Otherwise, its return value is returned by ``url_for``. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers: t.List[ + t.Callable[[Exception, str, t.Dict[str, t.Any]], str] + ] = [] + + #: A list of functions that will be called at the beginning of the + #: first request to this instance. To register a function, use the + #: :meth:`before_first_request` decorator. + #: + #: .. deprecated:: 2.2 + #: Will be removed in Flask 2.3. Run setup code when + #: creating the application instead. + #: + #: .. versionadded:: 0.8 + self.before_first_request_funcs: t.List[ft.BeforeFirstRequestCallable] = [] + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs: t.List[ft.TeardownCallable] = [] + + #: A list of shell context processor functions that should be run + #: when a shell context is created. + #: + #: .. versionadded:: 0.11 + self.shell_context_processors: t.List[ft.ShellContextProcessorCallable] = [] + + #: Maps registered blueprint names to blueprint objects. The + #: dict retains the order the blueprints were registered in. + #: Blueprints can be registered multiple times, this dict does + #: not track how often they were attached. + #: + #: .. versionadded:: 0.7 + self.blueprints: t.Dict[str, "Blueprint"] = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. + #: + #: The key must match the name of the extension module. For example in + #: case of a "Flask-Foo" extension in `flask_foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions: dict = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(super(ListConverter, self).to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = self.url_map_class() + + self.url_map.host_matching = host_matching + self.subdomain_matching = subdomain_matching + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + self._before_request_lock = Lock() + + # Add a static route using the provided static_url_path, static_host, + # and static_folder if there is a configured static_folder. + # Note we do this without checking if static_folder exists. + # For one, it might be created while the server is running (e.g. during + # development). Also, Google App Engine stores static files somewhere + if self.has_static_folder: + assert ( + bool(static_host) == host_matching + ), "Invalid static_host/host_matching combination" + # Use a weakref to avoid creating a reference cycle between the app + # and the view function (see #3761). + self_ref = weakref.ref(self) + self.add_url_rule( + f"{self.static_url_path}/", + endpoint="static", + host=static_host, + view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 + ) + + # Set the name of the Click group in case someone wants to add + # the app's commands to another CLI tool. + self.cli.name = self.name + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_first_request: + raise AssertionError( + f"The setup method '{f_name}' can no longer be called" + " on the application. It has already handled its first" + " request, any changes will not be applied" + " consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the application are done before" + " running it." + ) + + @locked_cached_property + def name(self) -> str: # type: ignore + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == "__main__": + fn = getattr(sys.modules["__main__"], "__file__", None) + if fn is None: + return "__main__" + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @property + def propagate_exceptions(self) -> bool: + """Returns the value of the ``PROPAGATE_EXCEPTIONS`` configuration + value in case it's set, otherwise a sensible default is returned. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. + + .. versionadded:: 0.7 + """ + import warnings + + warnings.warn( + "'propagate_exceptions' is deprecated and will be removed in Flask 2.3.", + DeprecationWarning, + stacklevel=2, + ) + rv = self.config["PROPAGATE_EXCEPTIONS"] + if rv is not None: + return rv + return self.testing or self.debug + + @locked_cached_property + def logger(self) -> logging.Logger: + """A standard Python :class:`~logging.Logger` for the app, with + the same name as :attr:`name`. + + In debug mode, the logger's :attr:`~logging.Logger.level` will + be set to :data:`~logging.DEBUG`. + + If there are no handlers configured, a default handler will be + added. See :doc:`/logging` for more information. + + .. versionchanged:: 1.1.0 + The logger takes the same name as :attr:`name` rather than + hard-coding ``"flask.app"``. + + .. versionchanged:: 1.0.0 + Behavior was simplified. The logger is always named + ``"flask.app"``. The level is only set during configuration, + it doesn't check ``app.debug`` each time. Only one format is + used, not different ones depending on ``app.debug``. No + handlers are removed, and a handler is only added if no + handlers are already configured. + + .. versionadded:: 0.3 + """ + return create_logger(self) + + @locked_cached_property + def jinja_env(self) -> Environment: + """The Jinja environment used to load templates. + + The environment is created the first time this property is + accessed. Changing :attr:`jinja_options` after that will have no + effect. + """ + return self.create_jinja_environment() + + @property + def got_first_request(self) -> bool: + """This attribute is set to ``True`` if the application started + handling the first request. + + .. versionadded:: 0.8 + """ + return self._got_first_request + + def make_config(self, instance_relative: bool = False) -> Config: + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + defaults = dict(self.default_config) + defaults["ENV"] = os.environ.get("FLASK_ENV") or "production" + defaults["DEBUG"] = get_debug_flag() + return self.config_class(root_path, defaults) + + def make_aborter(self) -> Aborter: + """Create the object to assign to :attr:`aborter`. That object + is called by :func:`flask.abort` to raise HTTP errors, and can + be called directly as well. + + By default, this creates an instance of :attr:`aborter_class`, + which defaults to :class:`werkzeug.exceptions.Aborter`. + + .. versionadded:: 2.2 + """ + return self.aborter_class() + + def auto_find_instance_path(self) -> str: + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, "instance") + return os.path.join(prefix, "var", f"{self.name}-instance") + + def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + @property + def templates_auto_reload(self) -> bool: + """Reload templates when they are changed. Used by + :meth:`create_jinja_environment`. It is enabled by default in debug mode. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use ``app.config["TEMPLATES_AUTO_RELOAD"]`` + instead. + + .. versionadded:: 1.0 + This property was added but the underlying config and behavior + already existed. + """ + import warnings + + warnings.warn( + "'templates_auto_reload' is deprecated and will be removed in Flask 2.3." + " Use 'TEMPLATES_AUTO_RELOAD' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + rv = self.config["TEMPLATES_AUTO_RELOAD"] + return rv if rv is not None else self.debug + + @templates_auto_reload.setter + def templates_auto_reload(self, value: bool) -> None: + import warnings + + warnings.warn( + "'templates_auto_reload' is deprecated and will be removed in Flask 2.3." + " Use 'TEMPLATES_AUTO_RELOAD' in 'app.config' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.config["TEMPLATES_AUTO_RELOAD"] = value + + def create_jinja_environment(self) -> Environment: + """Create the Jinja environment based on :attr:`jinja_options` + and the various Jinja-related methods of the app. Changing + :attr:`jinja_options` after this will have no effect. Also adds + Flask-related globals and filters to the environment. + + .. versionchanged:: 0.11 + ``Environment.auto_reload`` set in accordance with + ``TEMPLATES_AUTO_RELOAD`` configuration option. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + + if "autoescape" not in options: + options["autoescape"] = self.select_jinja_autoescape + + if "auto_reload" not in options: + auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] + + if auto_reload is None: + auto_reload = self.debug + + options["auto_reload"] = auto_reload + + rv = self.jinja_environment(self, **options) + rv.globals.update( + url_for=self.url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g, + ) + rv.policies["json.dumps_function"] = self.json.dumps + return rv + + def create_global_jinja_loader(self) -> DispatchingJinjaLoader: + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def select_jinja_autoescape(self, filename: str) -> bool: + """Returns ``True`` if autoescaping should be active for the given + template name. If no template name is given, returns `True`. + + .. versionchanged:: 2.2 + Autoescaping is now enabled by default for ``.svg`` files. + + .. versionadded:: 0.5 + """ + if filename is None: + return True + return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) + + def update_template_context(self, context: dict) -> None: + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + names: t.Iterable[t.Optional[str]] = (None,) + + # A template may be rendered outside a request context. + if request: + names = chain(names, reversed(request.blueprints)) + + # The values passed to render_template take precedence. Keep a + # copy to re-apply after all context functions. + orig_ctx = context.copy() + + for name in names: + if name in self.template_context_processors: + for func in self.template_context_processors[name]: + context.update(func()) + + context.update(orig_ctx) + + def make_shell_context(self) -> dict: + """Returns the shell context for an interactive shell for this + application. This runs all the registered shell context + processors. + + .. versionadded:: 0.11 + """ + rv = {"app": self, "g": g} + for processor in self.shell_context_processors: + rv.update(processor()) + return rv + + @property + def env(self) -> str: + """What environment the app is running in. This maps to the :data:`ENV` config + key. + + **Do not enable development when deploying in production.** + + Default: ``'production'`` + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. + """ + import warnings + + warnings.warn( + "'app.env' is deprecated and will be removed in Flask 2.3." + " Use 'app.debug' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self.config["ENV"] + + @env.setter + def env(self, value: str) -> None: + import warnings + + warnings.warn( + "'app.env' is deprecated and will be removed in Flask 2.3." + " Use 'app.debug' instead.", + DeprecationWarning, + stacklevel=2, + ) + self.config["ENV"] = value + + @property + def debug(self) -> bool: + """Whether debug mode is enabled. When using ``flask run`` to start the + development server, an interactive debugger will be shown for unhandled + exceptions, and the server will be reloaded when code changes. This maps to the + :data:`DEBUG` config key. It may not behave as expected if set late. + + **Do not enable debug mode when deploying in production.** + + Default: ``False`` + """ + return self.config["DEBUG"] + + @debug.setter + def debug(self, value: bool) -> None: + self.config["DEBUG"] = value + + if self.config["TEMPLATES_AUTO_RELOAD"] is None: + self.jinja_env.auto_reload = value + + def run( + self, + host: t.Optional[str] = None, + port: t.Optional[int] = None, + debug: t.Optional[bool] = None, + load_dotenv: bool = True, + **options: t.Any, + ) -> None: + """Runs the application on a local development server. + + Do not use ``run()`` in a production setting. It is not intended to + meet security and performance requirements for a production server. + Instead, see :doc:`/deploying/index` for WSGI server recommendations. + + If the :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + It is not recommended to use this function for development with + automatic reloading as this is badly supported. Instead you should + be using the :command:`flask` command line script's ``run`` support. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to ``True`` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable + if present. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if present. + :param debug: if given, enable or disable debug mode. See + :attr:`debug`. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param options: the options to be forwarded to the underlying Werkzeug + server. See :func:`werkzeug.serving.run_simple` for more + information. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment + variables from :file:`.env` and :file:`.flaskenv` files. + + The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. + + Threaded mode is enabled by default. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` + variable. + """ + # Ignore this call so that it doesn't start another server if + # the 'flask run' command is used. + if os.environ.get("FLASK_RUN_FROM_CLI") == "true": + if not is_running_from_reloader(): + click.secho( + " * Ignoring a call to 'app.run()' that would block" + " the current 'flask' CLI command.\n" + " Only call 'app.run()' in an 'if __name__ ==" + ' "__main__"\' guard.', + fg="red", + ) + + return + + if get_load_dotenv(load_dotenv): + cli.load_dotenv() + + # if set, let env vars override previous values + if "FLASK_ENV" in os.environ: + print( + "'FLASK_ENV' is deprecated and will not be used in" + " Flask 2.3. Use 'FLASK_DEBUG' instead.", + file=sys.stderr, + ) + self.config["ENV"] = os.environ.get("FLASK_ENV") or "production" + self.debug = get_debug_flag() + elif "FLASK_DEBUG" in os.environ: + self.debug = get_debug_flag() + + # debug passed to method overrides all other sources + if debug is not None: + self.debug = bool(debug) + + server_name = self.config.get("SERVER_NAME") + sn_host = sn_port = None + + if server_name: + sn_host, _, sn_port = server_name.partition(":") + + if not host: + if sn_host: + host = sn_host + else: + host = "127.0.0.1" + + if port or port == 0: + port = int(port) + elif sn_port: + port = int(sn_port) + else: + port = 5000 + + options.setdefault("use_reloader", self.debug) + options.setdefault("use_debugger", self.debug) + options.setdefault("threaded", True) + + cli.show_server_banner(self.debug, self.name) + + from werkzeug.serving import run_simple + + try: + run_simple(t.cast(str, host), port, self, **options) + finally: + # reset the first request information if the development server + # reset normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> "FlaskClient": + """Creates a test client for this application. For information + about unit testing head over to :doc:`/testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a ``with`` block to defer the closing down + of the context until the end of the ``with`` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + Additionally, you may pass optional keyword arguments that will then + be passed to the application's :attr:`test_client_class` constructor. + For example:: + + from flask.testing import FlaskClient + + class CustomClient(FlaskClient): + def __init__(self, *args, **kwargs): + self._authentication = kwargs.pop("authentication") + super(CustomClient,self).__init__( *args, **kwargs) + + app.test_client_class = CustomClient + client = app.test_client(authentication='Basic ....') + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for ``with`` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + + .. versionchanged:: 0.11 + Added `**kwargs` to support passing additional keyword arguments to + the constructor of :attr:`test_client_class`. + """ + cls = self.test_client_class + if cls is None: + from .testing import FlaskClient as cls # type: ignore + return cls( # type: ignore + self, self.response_class, use_cookies=use_cookies, **kwargs + ) + + def test_cli_runner(self, **kwargs: t.Any) -> "FlaskCliRunner": + """Create a CLI runner for testing CLI commands. + See :ref:`testing-cli`. + + Returns an instance of :attr:`test_cli_runner_class`, by default + :class:`~flask.testing.FlaskCliRunner`. The Flask app object is + passed as the first argument. + + .. versionadded:: 1.0 + """ + cls = self.test_cli_runner_class + + if cls is None: + from .testing import FlaskCliRunner as cls # type: ignore + + return cls(self, **kwargs) # type: ignore + + @setupmethod + def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on the application. Keyword + arguments passed to this method will override the defaults set on the + blueprint. + + Calls the blueprint's :meth:`~flask.Blueprint.register` method after + recording the blueprint in the application's :attr:`blueprints`. + + :param blueprint: The blueprint to register. + :param url_prefix: Blueprint routes will be prefixed with this. + :param subdomain: Blueprint routes will match on this subdomain. + :param url_defaults: Blueprint routes will use these default values for + view arguments. + :param options: Additional keyword arguments are passed to + :class:`~flask.blueprints.BlueprintSetupState`. They can be + accessed in :meth:`~flask.Blueprint.record` callbacks. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 0.7 + """ + blueprint.register(self, options) + + def iter_blueprints(self) -> t.ValuesView["Blueprint"]: + """Iterates over all blueprints by the order they were registered. + + .. versionadded:: 0.11 + """ + return self.blueprints.values() + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[ft.RouteCallable] = None, + provide_automatic_options: t.Optional[bool] = None, + **options: t.Any, + ) -> None: + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + options["endpoint"] = endpoint + methods = options.pop("methods", None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only ``GET`` as default. + if methods is None: + methods = getattr(view_func, "methods", None) or ("GET",) + if isinstance(methods, str): + raise TypeError( + "Allowed methods must be a list of strings, for" + ' example: @app.route(..., methods=["POST"])' + ) + methods = {item.upper() for item in methods} + + # Methods that should always be added + required_methods = set(getattr(view_func, "required_methods", ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + if provide_automatic_options is None: + provide_automatic_options = getattr( + view_func, "provide_automatic_options", None + ) + + if provide_automatic_options is None: + if "OPTIONS" not in methods: + provide_automatic_options = True + required_methods.add("OPTIONS") + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + rule = self.url_rule_class(rule, methods=methods, **options) + rule.provide_automatic_options = provide_automatic_options # type: ignore + + self.url_map.add(rule) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError( + "View function mapping is overwriting an existing" + f" endpoint function: {endpoint}" + ) + self.view_functions[endpoint] = view_func + + @setupmethod + def template_filter( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_filter( + self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_test], T_template_test]: + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_test( + self, f: ft.TemplateTestCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + @setupmethod + def template_global( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_global], T_template_global]: + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_template_global( + self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None + ) -> None: + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def before_first_request(self, f: T_before_first_request) -> T_before_first_request: + """Registers a function to be run before the first request to this + instance of the application. + + The function will be called without any arguments and its return + value is ignored. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Run setup code when creating + the application instead. + + .. versionadded:: 0.8 + """ + import warnings + + warnings.warn( + "'before_first_request' is deprecated and will be removed" + " in Flask 2.3. Run setup code while creating the" + " application instead.", + DeprecationWarning, + stacklevel=2, + ) + self.before_first_request_funcs.append(f) + return f + + @setupmethod + def teardown_appcontext(self, f: T_teardown) -> T_teardown: + """Registers a function to be called when the application + context is popped. The application context is typically popped + after the request context for each request, at the end of CLI + commands, or after a manually pushed context ends. + + .. code-block:: python + + with app.app_context(): + ... + + When the ``with`` block exits (or ``ctx.pop()`` is called), the + teardown functions are called just before the app context is + made inactive. Since a request context typically also manages an + application context it would also be called when you pop a + request context. + + When a teardown function was called because of an unhandled + exception it will be passed an error object. If an + :meth:`errorhandler` is registered, it will handle the exception + and the teardown will not receive it. + + Teardown functions must avoid raising exceptions. If they + execute code that might fail they must surround that code with a + ``try``/``except`` block and log any errors. + + The return values of teardown functions are ignored. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def shell_context_processor( + self, f: T_shell_context_processor + ) -> T_shell_context_processor: + """Registers a shell context processor function. + + .. versionadded:: 0.11 + """ + self.shell_context_processors.append(f) + return f + + def _find_error_handler(self, e: Exception) -> t.Optional[ft.ErrorHandlerCallable]: + """Return a registered error handler for an exception in this order: + blueprint handler for a specific code, app handler for a specific code, + blueprint handler for an exception class, app handler for an exception + class, or ``None`` if a suitable handler is not found. + """ + exc_class, code = self._get_exc_class_and_code(type(e)) + names = (*request.blueprints, None) + + for c in (code, None) if code is not None else (None,): + for name in names: + handler_map = self.error_handler_spec[name][c] + + if not handler_map: + continue + + for cls in exc_class.__mro__: + handler = handler_map.get(cls) + + if handler is not None: + return handler + return None + + def handle_http_exception( + self, e: HTTPException + ) -> t.Union[HTTPException, ft.ResponseReturnValue]: + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionchanged:: 1.0.3 + ``RoutingException``, used internally for actions such as + slash redirects during routing, is not passed to error + handlers. + + .. versionchanged:: 1.0 + Exceptions are looked up by code *and* by MRO, so + ``HTTPException`` subclasses can be handled with a catch-all + handler for the base ``HTTPException``. + + .. versionadded:: 0.3 + """ + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + + # RoutingExceptions are used internally to trigger routing + # actions, such as slash redirects raising RequestRedirect. They + # are not raised or handled in user code. + if isinstance(e, RoutingException): + return e + + handler = self._find_error_handler(e) + if handler is None: + return e + return self.ensure_sync(handler)(e) + + def trap_http_exception(self, e: Exception) -> bool: + """Checks if an HTTP exception should be trapped or not. By default + this will return ``False`` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It + also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. + + This is called for all HTTP exceptions raised by a view function. + If it returns ``True`` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionchanged:: 1.0 + Bad request errors are not trapped by default in debug mode. + + .. versionadded:: 0.8 + """ + if self.config["TRAP_HTTP_EXCEPTIONS"]: + return True + + trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] + + # if unset, trap key errors in debug mode + if ( + trap_bad_request is None + and self.debug + and isinstance(e, BadRequestKeyError) + ): + return True + + if trap_bad_request: + return isinstance(e, BadRequest) + + return False + + def handle_user_exception( + self, e: Exception + ) -> t.Union[HTTPException, ft.ResponseReturnValue]: + """This method is called whenever an exception occurs that + should be handled. A special case is :class:`~werkzeug + .exceptions.HTTPException` which is forwarded to the + :meth:`handle_http_exception` method. This function will either + return a response value or reraise the exception with the same + traceback. + + .. versionchanged:: 1.0 + Key errors raised from request data like ``form`` show the + bad key in debug mode rather than a generic bad request + message. + + .. versionadded:: 0.7 + """ + if isinstance(e, BadRequestKeyError) and ( + self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] + ): + e.show_exception = True + + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + handler = self._find_error_handler(e) + + if handler is None: + raise + + return self.ensure_sync(handler)(e) + + def handle_exception(self, e: Exception) -> Response: + """Handle an exception that did not have an error handler + associated with it, or that was raised from an error handler. + This always causes a 500 ``InternalServerError``. + + Always sends the :data:`got_request_exception` signal. + + If :attr:`propagate_exceptions` is ``True``, such as in debug + mode, the error will be re-raised so that the debugger can + display it. Otherwise, the original exception is logged, and + an :exc:`~werkzeug.exceptions.InternalServerError` is returned. + + If an error handler is registered for ``InternalServerError`` or + ``500``, it will be used. For consistency, the handler will + always receive the ``InternalServerError``. The original + unhandled exception is available as ``e.original_exception``. + + .. versionchanged:: 1.1.0 + Always passes the ``InternalServerError`` instance to the + handler, setting ``original_exception`` to the unhandled + error. + + .. versionchanged:: 1.1.0 + ``after_request`` functions and other finalization is done + even for the default 500 response when there is no handler. + + .. versionadded:: 0.3 + """ + exc_info = sys.exc_info() + got_request_exception.send(self, exception=e) + propagate = self.config["PROPAGATE_EXCEPTIONS"] + + if propagate is None: + propagate = self.testing or self.debug + + if propagate: + # Re-raise if called with an active exception, otherwise + # raise the passed in exception. + if exc_info[1] is e: + raise + + raise e + + self.log_exception(exc_info) + server_error: t.Union[InternalServerError, ft.ResponseReturnValue] + server_error = InternalServerError(original_exception=e) + handler = self._find_error_handler(server_error) + + if handler is not None: + server_error = self.ensure_sync(handler)(server_error) + + return self.finalize_request(server_error, from_error_handler=True) + + def log_exception( + self, + exc_info: t.Union[ + t.Tuple[type, BaseException, TracebackType], t.Tuple[None, None, None] + ], + ) -> None: + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error( + f"Exception on {request.path} [{request.method}]", exc_info=exc_info + ) + + def raise_routing_exception(self, request: Request) -> "te.NoReturn": + """Intercept routing exceptions and possibly do something else. + + In debug mode, intercept a routing redirect and replace it with + an error if the body will be discarded. + + With modern Werkzeug this shouldn't occur, since it now uses a + 308 status which tells the browser to resend the method and + body. + + .. versionchanged:: 2.1 + Don't intercept 307 and 308 redirects. + + :meta private: + :internal: + """ + if ( + not self.debug + or not isinstance(request.routing_exception, RequestRedirect) + or request.routing_exception.code in {307, 308} + or request.method in {"GET", "HEAD", "OPTIONS"} + ): + raise request.routing_exception # type: ignore + + from .debughelpers import FormDataRoutingRedirect + + raise FormDataRoutingRedirect(request) + + def dispatch_request(self) -> ft.ResponseReturnValue: + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = request_ctx.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule: Rule = req.url_rule # type: ignore[assignment] + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if ( + getattr(rule, "provide_automatic_options", False) + and req.method == "OPTIONS" + ): + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + view_args: t.Dict[str, t.Any] = req.view_args # type: ignore[assignment] + return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) + + def full_dispatch_request(self) -> Response: + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + # Run before_first_request functions if this is the thread's first request. + # Inlined to avoid a method call on subsequent requests. + # This is deprecated, will be removed in Flask 2.3. + if not self._got_first_request: + with self._before_request_lock: + if not self._got_first_request: + for func in self.before_first_request_funcs: + self.ensure_sync(func)() + + self._got_first_request = True + + try: + request_started.send(self) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + return self.finalize_request(rv) + + def finalize_request( + self, + rv: t.Union[ft.ResponseReturnValue, HTTPException], + from_error_handler: bool = False, + ) -> Response: + """Given the return value from a view function this finalizes + the request by converting it into a response and invoking the + postprocessing functions. This is invoked for both normal + request dispatching as well as error handlers. + + Because this means that it might be called as a result of a + failure a special safe mode is available which can be enabled + with the `from_error_handler` flag. If enabled, failures in + response processing will be logged and otherwise ignored. + + :internal: + """ + response = self.make_response(rv) + try: + response = self.process_response(response) + request_finished.send(self, response=response) + except Exception: + if not from_error_handler: + raise + self.logger.exception( + "Request finalizing failed with an error while handling an error" + ) + return response + + def make_default_options_response(self) -> Response: + """This method is called to create the default ``OPTIONS`` response. + This can be changed through subclassing to change the default + behavior of ``OPTIONS`` responses. + + .. versionadded:: 0.7 + """ + adapter = request_ctx.url_adapter + methods = adapter.allowed_methods() # type: ignore[union-attr] + rv = self.response_class() + rv.allow.update(methods) + return rv + + def should_ignore_error(self, error: t.Optional[BaseException]) -> bool: + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns ``True`` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def ensure_sync(self, func: t.Callable) -> t.Callable: + """Ensure that the function is synchronous for WSGI workers. + Plain ``def`` functions are returned as-is. ``async def`` + functions are wrapped to run and wait for the response. + + Override this method to change how the app runs async views. + + .. versionadded:: 2.0 + """ + if iscoroutinefunction(func): + return self.async_to_sync(func) + + return func + + def async_to_sync( + self, func: t.Callable[..., t.Coroutine] + ) -> t.Callable[..., t.Any]: + """Return a sync function that will run the coroutine function. + + .. code-block:: python + + result = app.async_to_sync(func)(*args, **kwargs) + + Override this method to change how the app converts async code + to be synchronously callable. + + .. versionadded:: 2.0 + """ + try: + from asgiref.sync import async_to_sync as asgiref_async_to_sync + except ImportError: + raise RuntimeError( + "Install Flask with the 'async' extra in order to use async views." + ) from None + + return asgiref_async_to_sync(func) + + def url_for( + self, + endpoint: str, + *, + _anchor: t.Optional[str] = None, + _method: t.Optional[str] = None, + _scheme: t.Optional[str] = None, + _external: t.Optional[bool] = None, + **values: t.Any, + ) -> str: + """Generate a URL to the given endpoint with the given values. + + This is called by :func:`flask.url_for`, and can be called + directly as well. + + An *endpoint* is the name of a URL rule, usually added with + :meth:`@app.route() `, and usually the same name as the + view function. A route defined in a :class:`~flask.Blueprint` + will prepend the blueprint's name separated by a ``.`` to the + endpoint. + + In some cases, such as email messages, you want URLs to include + the scheme and domain, like ``https://example.com/hello``. When + not in an active request, URLs will be external by default, but + this requires setting :data:`SERVER_NAME` so Flask knows what + domain to use. :data:`APPLICATION_ROOT` and + :data:`PREFERRED_URL_SCHEME` should also be configured as + needed. This config is only used when not in an active request. + + Functions can be decorated with :meth:`url_defaults` to modify + keyword arguments before the URL is built. + + If building fails for some reason, such as an unknown endpoint + or incorrect values, the app's :meth:`handle_url_build_error` + method is called. If that returns a string, that is returned, + otherwise a :exc:`~werkzeug.routing.BuildError` is raised. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it + is external. + :param _external: If given, prefer the URL to be internal + (False) or require it to be external (True). External URLs + include the scheme and domain. When not in an active + request, URLs are external by default. + :param values: Values to use for the variable parts of the URL + rule. Unknown keys are appended as query string arguments, + like ``?a=b&c=d``. + + .. versionadded:: 2.2 + Moved from ``flask.url_for``, which calls this method. + """ + req_ctx = _cv_request.get(None) + + if req_ctx is not None: + url_adapter = req_ctx.url_adapter + blueprint_name = req_ctx.request.blueprint + + # If the endpoint starts with "." and the request matches a + # blueprint, the endpoint is relative to the blueprint. + if endpoint[:1] == ".": + if blueprint_name is not None: + endpoint = f"{blueprint_name}{endpoint}" + else: + endpoint = endpoint[1:] + + # When in a request, generate a URL without scheme and + # domain by default, unless a scheme is given. + if _external is None: + _external = _scheme is not None + else: + app_ctx = _cv_app.get(None) + + # If called by helpers.url_for, an app context is active, + # use its url_adapter. Otherwise, app.url_for was called + # directly, build an adapter. + if app_ctx is not None: + url_adapter = app_ctx.url_adapter + else: + url_adapter = self.create_url_adapter(None) + + if url_adapter is None: + raise RuntimeError( + "Unable to build URLs outside an active request" + " without 'SERVER_NAME' configured. Also configure" + " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" + " needed." + ) + + # When outside a request, generate a URL with scheme and + # domain by default. + if _external is None: + _external = True + + # It is an error to set _scheme when _external=False, in order + # to avoid accidental insecure URLs. + if _scheme is not None and not _external: + raise ValueError("When specifying '_scheme', '_external' must be True.") + + self.inject_url_defaults(endpoint, values) + + try: + rv = url_adapter.build( # type: ignore[union-attr] + endpoint, + values, + method=_method, + url_scheme=_scheme, + force_external=_external, + ) + except BuildError as error: + values.update( + _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external + ) + return self.handle_url_build_error(error, endpoint, values) + + if _anchor is not None: + rv = f"{rv}#{url_quote(_anchor)}" + + return rv + + def redirect(self, location: str, code: int = 302) -> BaseResponse: + """Create a redirect response object. + + This is called by :func:`flask.redirect`, and can be called + directly as well. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + + .. versionadded:: 2.2 + Moved from ``flask.redirect``, which calls this method. + """ + return _wz_redirect(location, code=code, Response=self.response_class) + + def make_response(self, rv: ft.ResponseReturnValue) -> Response: + """Convert the return value from a view function to an instance of + :attr:`response_class`. + + :param rv: the return value from the view function. The view function + must return a response. Returning ``None``, or the view ending + without returning, is not allowed. The following types are allowed + for ``view_rv``: + + ``str`` + A response object is created with the string encoded to UTF-8 + as the body. + + ``bytes`` + A response object is created with the bytes as the body. + + ``dict`` + A dictionary that will be jsonify'd before being returned. + + ``list`` + A list that will be jsonify'd before being returned. + + ``generator`` or ``iterator`` + A generator that returns ``str`` or ``bytes`` to be + streamed as the response. + + ``tuple`` + Either ``(body, status, headers)``, ``(body, status)``, or + ``(body, headers)``, where ``body`` is any of the other types + allowed here, ``status`` is a string or an integer, and + ``headers`` is a dictionary or a list of ``(key, value)`` + tuples. If ``body`` is a :attr:`response_class` instance, + ``status`` overwrites the exiting value and ``headers`` are + extended. + + :attr:`response_class` + The object is returned unchanged. + + other :class:`~werkzeug.wrappers.Response` class + The object is coerced to :attr:`response_class`. + + :func:`callable` + The function is called as a WSGI application. The result is + used to create a response object. + + .. versionchanged:: 2.2 + A generator will be converted to a streaming response. + A list will be converted to a JSON response. + + .. versionchanged:: 1.1 + A dict will be converted to a JSON response. + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + + status = headers = None + + # unpack tuple returns + if isinstance(rv, tuple): + len_rv = len(rv) + + # a 3-tuple is unpacked directly + if len_rv == 3: + rv, status, headers = rv # type: ignore[misc] + # decide if a 2-tuple has status or headers + elif len_rv == 2: + if isinstance(rv[1], (Headers, dict, tuple, list)): + rv, headers = rv + else: + rv, status = rv # type: ignore[assignment,misc] + # other sized tuples are not allowed + else: + raise TypeError( + "The view function did not return a valid response tuple." + " The tuple must have the form (body, status, headers)," + " (body, status), or (body, headers)." + ) + + # the body must not be None + if rv is None: + raise TypeError( + f"The view function for {request.endpoint!r} did not" + " return a valid response. The function either returned" + " None or ended without a return statement." + ) + + # make sure the body is an instance of the response class + if not isinstance(rv, self.response_class): + if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, _abc_Iterator): + # let the response class set the status and headers instead of + # waiting to do it manually, so that the class can handle any + # special logic + rv = self.response_class( + rv, + status=status, + headers=headers, # type: ignore[arg-type] + ) + status = headers = None + elif isinstance(rv, (dict, list)): + rv = self.json.response(rv) + elif isinstance(rv, BaseResponse) or callable(rv): + # evaluate a WSGI callable, or coerce a different response + # class to the correct type + try: + rv = self.response_class.force_type( + rv, request.environ # type: ignore[arg-type] + ) + except TypeError as e: + raise TypeError( + f"{e}\nThe view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it" + f" was a {type(rv).__name__}." + ).with_traceback(sys.exc_info()[2]) from None + else: + raise TypeError( + "The view function did not return a valid" + " response. The return type must be a string," + " dict, list, tuple with headers or status," + " Response instance, or WSGI callable, but it was a" + f" {type(rv).__name__}." + ) + + rv = t.cast(Response, rv) + # prefer the status if it was provided + if status is not None: + if isinstance(status, (str, bytes, bytearray)): + rv.status = status + else: + rv.status_code = status + + # extend existing headers with provided headers + if headers: + rv.headers.update(headers) # type: ignore[arg-type] + + return rv + + def create_url_adapter( + self, request: t.Optional[Request] + ) -> t.Optional[MapAdapter]: + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set + up so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + + .. versionchanged:: 1.0 + :data:`SERVER_NAME` no longer implicitly enables subdomain + matching. Use :attr:`subdomain_matching` instead. + """ + if request is not None: + # If subdomain matching is disabled (the default), use the + # default subdomain in all cases. This should be the default + # in Werkzeug but it currently does not have that feature. + if not self.subdomain_matching: + subdomain = self.url_map.default_subdomain or None + else: + subdomain = None + + return self.url_map.bind_to_environ( + request.environ, + server_name=self.config["SERVER_NAME"], + subdomain=subdomain, + ) + # We need at the very least the server name to be set for this + # to work. + if self.config["SERVER_NAME"] is not None: + return self.url_map.bind( + self.config["SERVER_NAME"], + script_name=self.config["APPLICATION_ROOT"], + url_scheme=self.config["PREFERRED_URL_SCHEME"], + ) + + return None + + def inject_url_defaults(self, endpoint: str, values: dict) -> None: + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + names: t.Iterable[t.Optional[str]] = (None,) + + # url_for may be called outside a request context, parse the + # passed endpoint instead of using request.blueprints. + if "." in endpoint: + names = chain( + names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) + ) + + for name in names: + if name in self.url_default_functions: + for func in self.url_default_functions[name]: + func(endpoint, values) + + def handle_url_build_error( + self, error: BuildError, endpoint: str, values: t.Dict[str, t.Any] + ) -> str: + """Called by :meth:`.url_for` if a + :exc:`~werkzeug.routing.BuildError` was raised. If this returns + a value, it will be returned by ``url_for``, otherwise the error + will be re-raised. + + Each function in :attr:`url_build_error_handlers` is called with + ``error``, ``endpoint`` and ``values``. If a function returns + ``None`` or raises a ``BuildError``, it is skipped. Otherwise, + its return value is returned by ``url_for``. + + :param error: The active ``BuildError`` being handled. + :param endpoint: The endpoint being built. + :param values: The keyword arguments passed to ``url_for``. + """ + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + except BuildError as e: + # make error available outside except block + error = e + else: + if rv is not None: + return rv + + # Re-raise if called with an active exception, otherwise raise + # the passed in exception. + if error is sys.exc_info()[1]: + raise + + raise error + + def preprocess_request(self) -> t.Optional[ft.ResponseReturnValue]: + """Called before the request is dispatched. Calls + :attr:`url_value_preprocessors` registered with the app and the + current blueprint (if any). Then calls :attr:`before_request_funcs` + registered with the app and the blueprint. + + If any :meth:`before_request` handler returns a non-None value, the + value is handled as if it was the return value from the view, and + further request handling is stopped. + """ + names = (None, *reversed(request.blueprints)) + + for name in names: + if name in self.url_value_preprocessors: + for url_func in self.url_value_preprocessors[name]: + url_func(request.endpoint, request.view_args) + + for name in names: + if name in self.before_request_funcs: + for before_func in self.before_request_funcs[name]: + rv = self.ensure_sync(before_func)() + + if rv is not None: + return rv + + return None + + def process_response(self, response: Response) -> Response: + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = request_ctx._get_current_object() # type: ignore[attr-defined] + + for func in ctx._after_request_functions: + response = self.ensure_sync(func)(response) + + for name in chain(request.blueprints, (None,)): + if name in self.after_request_funcs: + for func in reversed(self.after_request_funcs[name]): + response = self.ensure_sync(func)(response) + + if not self.session_interface.is_null_session(ctx.session): + self.session_interface.save_session(self, ctx.session, response) + + return response + + def do_teardown_request( + self, exc: t.Optional[BaseException] = _sentinel # type: ignore + ) -> None: + """Called after the request is dispatched and the response is + returned, right before the request context is popped. + + This calls all functions decorated with + :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` + if a blueprint handled the request. Finally, the + :data:`request_tearing_down` signal is sent. + + This is called by + :meth:`RequestContext.pop() `, + which may be delayed during testing to maintain access to + resources. + + :param exc: An unhandled exception raised while dispatching the + request. Detected from the current exception information if + not passed. Passed to each teardown function. + + .. versionchanged:: 0.9 + Added the ``exc`` argument. + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for name in chain(request.blueprints, (None,)): + if name in self.teardown_request_funcs: + for func in reversed(self.teardown_request_funcs[name]): + self.ensure_sync(func)(exc) + + request_tearing_down.send(self, exc=exc) + + def do_teardown_appcontext( + self, exc: t.Optional[BaseException] = _sentinel # type: ignore + ) -> None: + """Called right before the application context is popped. + + When handling a request, the application context is popped + after the request context. See :meth:`do_teardown_request`. + + This calls all functions decorated with + :meth:`teardown_appcontext`. Then the + :data:`appcontext_tearing_down` signal is sent. + + This is called by + :meth:`AppContext.pop() `. + + .. versionadded:: 0.9 + """ + if exc is _sentinel: + exc = sys.exc_info()[1] + + for func in reversed(self.teardown_appcontext_funcs): + self.ensure_sync(func)(exc) + + appcontext_tearing_down.send(self, exc=exc) + + def app_context(self) -> AppContext: + """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` + block to push the context, which will make :data:`current_app` + point at this application. + + An application context is automatically pushed by + :meth:`RequestContext.push() ` + when handling a request, and when running a CLI command. Use + this to manually create a context outside of these situations. + + :: + + with app.app_context(): + init_db() + + See :doc:`/appcontext`. + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ: dict) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` representing a + WSGI environment. Use a ``with`` block to push the context, + which will make :data:`request` point at this request. + + See :doc:`/reqcontext`. + + Typically you should not call this from your own code. A request + context is automatically pushed by the :meth:`wsgi_app` when + handling a request. Use :meth:`test_request_context` to create + an environment and context instead of this method. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: + """Create a :class:`~flask.ctx.RequestContext` for a WSGI + environment created from the given values. This is mostly useful + during testing, where you may want to run a function that uses + request data without dispatching a full request. + + See :doc:`/reqcontext`. + + Use a ``with`` block to push the context, which will make + :data:`request` point at the request for the created + environment. :: + + with test_request_context(...): + generate_report() + + When using the shell, it may be easier to push and pop the + context manually to avoid indentation. :: + + ctx = app.test_request_context(...) + ctx.push() + ... + ctx.pop() + + Takes the same arguments as Werkzeug's + :class:`~werkzeug.test.EnvironBuilder`, with some defaults from + the application. See the linked Werkzeug docs for most of the + available arguments. Flask-specific behavior is listed here. + + :param path: URL path being requested. + :param base_url: Base URL where the app is being served, which + ``path`` is relative to. If not given, built from + :data:`PREFERRED_URL_SCHEME`, ``subdomain``, + :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. + :param subdomain: Subdomain name to append to + :data:`SERVER_NAME`. + :param url_scheme: Scheme to use instead of + :data:`PREFERRED_URL_SCHEME`. + :param data: The request body, either as a string or a dict of + form keys and values. + :param json: If given, this is serialized as JSON and passed as + ``data``. Also defaults ``content_type`` to + ``application/json``. + :param args: other positional arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + :param kwargs: other keyword arguments passed to + :class:`~werkzeug.test.EnvironBuilder`. + """ + from .testing import EnvironBuilder + + builder = EnvironBuilder(self, *args, **kwargs) + + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any: + """The actual WSGI application. This is not implemented in + :meth:`__call__` so that middlewares can be applied without + losing a reference to the app object. Instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + Teardown events for the request and app contexts are called + even if an unhandled error occurs. Other events may not be + called depending on when an error occurs during dispatch. + See :ref:`callbacks-and-errors`. + + :param environ: A WSGI environment. + :param start_response: A callable accepting a status code, + a list of headers, and an optional exception context to + start the response. + """ + ctx = self.request_context(environ) + error: t.Optional[BaseException] = None + try: + try: + ctx.push() + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.handle_exception(e) + except: # noqa: B001 + error = sys.exc_info()[1] + raise + return response(environ, start_response) + finally: + if "werkzeug.debug.preserve_context" in environ: + environ["werkzeug.debug.preserve_context"](_cv_app.get()) + environ["werkzeug.debug.preserve_context"](_cv_request.get()) + + if error is not None and self.should_ignore_error(error): + error = None + + ctx.pop(error) + + def __call__(self, environ: dict, start_response: t.Callable) -> t.Any: + """The WSGI server calls the Flask application object as the + WSGI application. This calls :meth:`wsgi_app`, which can be + wrapped to apply middleware. + """ + return self.wsgi_app(environ, start_response) diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/blueprints.py b/flask-server/venv/lib/python3.10/site-packages/flask/blueprints.py new file mode 100644 index 00000000..eb664235 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/blueprints.py @@ -0,0 +1,712 @@ +import json +import os +import typing as t +from collections import defaultdict +from functools import update_wrapper + +from . import typing as ft +from .scaffold import _endpoint_from_view_func +from .scaffold import _sentinel +from .scaffold import Scaffold +from .scaffold import setupmethod + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + +DeferredSetupFunction = t.Callable[["BlueprintSetupState"], t.Callable] +T_after_request = t.TypeVar("T_after_request", bound=ft.AfterRequestCallable) +T_before_first_request = t.TypeVar( + "T_before_first_request", bound=ft.BeforeFirstRequestCallable +) +T_before_request = t.TypeVar("T_before_request", bound=ft.BeforeRequestCallable) +T_error_handler = t.TypeVar("T_error_handler", bound=ft.ErrorHandlerCallable) +T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) +T_template_context_processor = t.TypeVar( + "T_template_context_processor", bound=ft.TemplateContextProcessorCallable +) +T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) +T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) +T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) +T_url_defaults = t.TypeVar("T_url_defaults", bound=ft.URLDefaultCallable) +T_url_value_preprocessor = t.TypeVar( + "T_url_value_preprocessor", bound=ft.URLValuePreprocessorCallable +) + + +class BlueprintSetupState: + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__( + self, + blueprint: "Blueprint", + app: "Flask", + options: t.Any, + first_registration: bool, + ) -> None: + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get("subdomain") + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, ``None`` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get("url_prefix") + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + self.name = self.options.get("name", blueprint.name) + self.name_prefix = self.options.get("name_prefix", "") + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get("url_defaults", ())) + + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[t.Callable] = None, + **options: t.Any, + ) -> None: + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix is not None: + if rule: + rule = "/".join((self.url_prefix.rstrip("/"), rule.lstrip("/"))) + else: + rule = self.url_prefix + options.setdefault("subdomain", self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) # type: ignore + defaults = self.url_defaults + if "defaults" in options: + defaults = dict(defaults, **options.pop("defaults")) + + self.app.add_url_rule( + rule, + f"{self.name_prefix}.{self.name}.{endpoint}".lstrip("."), + view_func, + defaults=defaults, + **options, + ) + + +class Blueprint(Scaffold): + """Represents a blueprint, a collection of routes and other + app-related functions that can be registered on a real application + later. + + A blueprint is an object that allows defining application functions + without requiring an application object ahead of time. It uses the + same decorators as :class:`~flask.Flask`, but defers the need for an + application by recording them for later registration. + + Decorating a function with a blueprint creates a deferred function + that is called with :class:`~flask.blueprints.BlueprintSetupState` + when the blueprint is registered on an application. + + See :doc:`/blueprints` for more information. + + :param name: The name of the blueprint. Will be prepended to each + endpoint name. + :param import_name: The name of the blueprint package, usually + ``__name__``. This helps locate the ``root_path`` for the + blueprint. + :param static_folder: A folder with static files that should be + served by the blueprint's static route. The path is relative to + the blueprint's root path. Blueprint static files are disabled + by default. + :param static_url_path: The url to serve static files from. + Defaults to ``static_folder``. If the blueprint does not have + a ``url_prefix``, the app's static route will take precedence, + and the blueprint's static files won't be accessible. + :param template_folder: A folder with templates that should be added + to the app's template search path. The path is relative to the + blueprint's root path. Blueprint templates are disabled by + default. Blueprint templates have a lower precedence than those + in the app's templates folder. + :param url_prefix: A path to prepend to all of the blueprint's URLs, + to make them distinct from the rest of the app's routes. + :param subdomain: A subdomain that blueprint routes will match on by + default. + :param url_defaults: A dict of default values that blueprint routes + will receive by default. + :param root_path: By default, the blueprint will automatically set + this based on ``import_name``. In certain situations this + automatic detection can fail, so the path can be specified + manually instead. + + .. versionchanged:: 1.1.0 + Blueprints have a ``cli`` group to register nested CLI commands. + The ``cli_group`` parameter controls the name of the group under + the ``flask`` command. + + .. versionadded:: 0.7 + """ + + _got_registered_once = False + + _json_encoder: t.Union[t.Type[json.JSONEncoder], None] = None + _json_decoder: t.Union[t.Type[json.JSONDecoder], None] = None + + @property + def json_encoder( + self, + ) -> t.Union[t.Type[json.JSONEncoder], None]: + """Blueprint-local JSON encoder class to use. Set to ``None`` to use the app's. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Customize + :attr:`json_provider_class` instead. + + .. versionadded:: 0.10 + """ + import warnings + + warnings.warn( + "'bp.json_encoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self._json_encoder + + @json_encoder.setter + def json_encoder(self, value: t.Union[t.Type[json.JSONEncoder], None]) -> None: + import warnings + + warnings.warn( + "'bp.json_encoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + self._json_encoder = value + + @property + def json_decoder( + self, + ) -> t.Union[t.Type[json.JSONDecoder], None]: + """Blueprint-local JSON decoder class to use. Set to ``None`` to use the app's. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Customize + :attr:`json_provider_class` instead. + + .. versionadded:: 0.10 + """ + import warnings + + warnings.warn( + "'bp.json_decoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + return self._json_decoder + + @json_decoder.setter + def json_decoder(self, value: t.Union[t.Type[json.JSONDecoder], None]) -> None: + import warnings + + warnings.warn( + "'bp.json_decoder' is deprecated and will be removed in Flask 2.3." + " Customize 'app.json_provider_class' or 'app.json' instead.", + DeprecationWarning, + stacklevel=2, + ) + self._json_decoder = value + + def __init__( + self, + name: str, + import_name: str, + static_folder: t.Optional[t.Union[str, os.PathLike]] = None, + static_url_path: t.Optional[str] = None, + template_folder: t.Optional[t.Union[str, os.PathLike]] = None, + url_prefix: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + url_defaults: t.Optional[dict] = None, + root_path: t.Optional[str] = None, + cli_group: t.Optional[str] = _sentinel, # type: ignore + ): + super().__init__( + import_name=import_name, + static_folder=static_folder, + static_url_path=static_url_path, + template_folder=template_folder, + root_path=root_path, + ) + + if "." in name: + raise ValueError("'name' may not contain a dot '.' character.") + + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.deferred_functions: t.List[DeferredSetupFunction] = [] + + if url_defaults is None: + url_defaults = {} + + self.url_values_defaults = url_defaults + self.cli_group = cli_group + self._blueprints: t.List[t.Tuple["Blueprint", dict]] = [] + + def _check_setup_finished(self, f_name: str) -> None: + if self._got_registered_once: + import warnings + + warnings.warn( + f"The setup method '{f_name}' can no longer be called on" + f" the blueprint '{self.name}'. It has already been" + " registered at least once, any changes will not be" + " applied consistently.\n" + "Make sure all imports, decorators, functions, etc." + " needed to set up the blueprint are done before" + " registering it.\n" + "This warning will become an exception in Flask 2.3.", + UserWarning, + stacklevel=3, + ) + + @setupmethod + def record(self, func: t.Callable) -> None: + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + self.deferred_functions.append(func) + + @setupmethod + def record_once(self, func: t.Callable) -> None: + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + + def wrapper(state: BlueprintSetupState) -> None: + if state.first_registration: + func(state) + + self.record(update_wrapper(wrapper, func)) + + def make_setup_state( + self, app: "Flask", options: dict, first_registration: bool = False + ) -> BlueprintSetupState: + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + @setupmethod + def register_blueprint(self, blueprint: "Blueprint", **options: t.Any) -> None: + """Register a :class:`~flask.Blueprint` on this blueprint. Keyword + arguments passed to this method will override the defaults set + on the blueprint. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionadded:: 2.0 + """ + if blueprint is self: + raise ValueError("Cannot register a blueprint on itself") + self._blueprints.append((blueprint, options)) + + def register(self, app: "Flask", options: dict) -> None: + """Called by :meth:`Flask.register_blueprint` to register all + views and callbacks registered on the blueprint with the + application. Creates a :class:`.BlueprintSetupState` and calls + each :meth:`record` callback with it. + + :param app: The application this blueprint is being registered + with. + :param options: Keyword arguments forwarded from + :meth:`~Flask.register_blueprint`. + + .. versionchanged:: 2.0.1 + Nested blueprints are registered with their dotted name. + This allows different blueprints with the same name to be + nested at different locations. + + .. versionchanged:: 2.0.1 + The ``name`` option can be used to change the (pre-dotted) + name the blueprint is registered with. This allows the same + blueprint to be registered multiple times with unique names + for ``url_for``. + + .. versionchanged:: 2.0.1 + Registering the same blueprint with the same name multiple + times is deprecated and will become an error in Flask 2.1. + """ + name_prefix = options.get("name_prefix", "") + self_name = options.get("name", self.name) + name = f"{name_prefix}.{self_name}".lstrip(".") + + if name in app.blueprints: + bp_desc = "this" if app.blueprints[name] is self else "a different" + existing_at = f" '{name}'" if self_name != name else "" + + raise ValueError( + f"The name '{self_name}' is already registered for" + f" {bp_desc} blueprint{existing_at}. Use 'name=' to" + f" provide a unique name." + ) + + first_bp_registration = not any(bp is self for bp in app.blueprints.values()) + first_name_registration = name not in app.blueprints + + app.blueprints[name] = self + self._got_registered_once = True + state = self.make_setup_state(app, options, first_bp_registration) + + if self.has_static_folder: + state.add_url_rule( + f"{self.static_url_path}/", + view_func=self.send_static_file, + endpoint="static", + ) + + # Merge blueprint data into parent. + if first_bp_registration or first_name_registration: + + def extend(bp_dict, parent_dict): + for key, values in bp_dict.items(): + key = name if key is None else f"{name}.{key}" + parent_dict[key].extend(values) + + for key, value in self.error_handler_spec.items(): + key = name if key is None else f"{name}.{key}" + value = defaultdict( + dict, + { + code: { + exc_class: func for exc_class, func in code_values.items() + } + for code, code_values in value.items() + }, + ) + app.error_handler_spec[key] = value + + for endpoint, func in self.view_functions.items(): + app.view_functions[endpoint] = func + + extend(self.before_request_funcs, app.before_request_funcs) + extend(self.after_request_funcs, app.after_request_funcs) + extend( + self.teardown_request_funcs, + app.teardown_request_funcs, + ) + extend(self.url_default_functions, app.url_default_functions) + extend(self.url_value_preprocessors, app.url_value_preprocessors) + extend(self.template_context_processors, app.template_context_processors) + + for deferred in self.deferred_functions: + deferred(state) + + cli_resolved_group = options.get("cli_group", self.cli_group) + + if self.cli.commands: + if cli_resolved_group is None: + app.cli.commands.update(self.cli.commands) + elif cli_resolved_group is _sentinel: + self.cli.name = name + app.cli.add_command(self.cli) + else: + self.cli.name = cli_resolved_group + app.cli.add_command(self.cli) + + for blueprint, bp_options in self._blueprints: + bp_options = bp_options.copy() + bp_url_prefix = bp_options.get("url_prefix") + + if bp_url_prefix is None: + bp_url_prefix = blueprint.url_prefix + + if state.url_prefix is not None and bp_url_prefix is not None: + bp_options["url_prefix"] = ( + state.url_prefix.rstrip("/") + "/" + bp_url_prefix.lstrip("/") + ) + elif bp_url_prefix is not None: + bp_options["url_prefix"] = bp_url_prefix + elif state.url_prefix is not None: + bp_options["url_prefix"] = state.url_prefix + + bp_options["name_prefix"] = name + blueprint.register(app, bp_options) + + @setupmethod + def add_url_rule( + self, + rule: str, + endpoint: t.Optional[str] = None, + view_func: t.Optional[ft.RouteCallable] = None, + provide_automatic_options: t.Optional[bool] = None, + **options: t.Any, + ) -> None: + """Register a URL rule with the blueprint. See :meth:`.Flask.add_url_rule` for + full documentation. + + The URL rule is prefixed with the blueprint's URL prefix. The endpoint name, + used with :func:`url_for`, is prefixed with the blueprint's name. + """ + if endpoint and "." in endpoint: + raise ValueError("'endpoint' may not contain a dot '.' character.") + + if view_func and hasattr(view_func, "__name__") and "." in view_func.__name__: + raise ValueError("'view_func' name may not contain a dot '.' character.") + + self.record( + lambda s: s.add_url_rule( + rule, + endpoint, + view_func, + provide_automatic_options=provide_automatic_options, + **options, + ) + ) + + @setupmethod + def app_template_filter( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_filter], T_template_filter]: + """Register a template filter, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def decorator(f: T_template_filter) -> T_template_filter: + self.add_app_template_filter(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_filter( + self, f: ft.TemplateFilterCallable, name: t.Optional[str] = None + ) -> None: + """Register a template filter, available in any template rendered by the + application. Works like the :meth:`app_template_filter` decorator. Equivalent to + :meth:`.Flask.add_template_filter`. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.filters[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_test( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_test], T_template_test]: + """Register a template test, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def decorator(f: T_template_test) -> T_template_test: + self.add_app_template_test(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_test( + self, f: ft.TemplateTestCallable, name: t.Optional[str] = None + ) -> None: + """Register a template test, available in any template rendered by the + application. Works like the :meth:`app_template_test` decorator. Equivalent to + :meth:`.Flask.add_template_test`. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.tests[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def app_template_global( + self, name: t.Optional[str] = None + ) -> t.Callable[[T_template_global], T_template_global]: + """Register a template global, available in any template rendered by the + application. Equivalent to :meth:`.Flask.template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def decorator(f: T_template_global) -> T_template_global: + self.add_app_template_global(f, name=name) + return f + + return decorator + + @setupmethod + def add_app_template_global( + self, f: ft.TemplateGlobalCallable, name: t.Optional[str] = None + ) -> None: + """Register a template global, available in any template rendered by the + application. Works like the :meth:`app_template_global` decorator. Equivalent to + :meth:`.Flask.add_template_global`. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + + def register_template(state: BlueprintSetupState) -> None: + state.app.jinja_env.globals[name or f.__name__] = f + + self.record_once(register_template) + + @setupmethod + def before_app_request(self, f: T_before_request) -> T_before_request: + """Like :meth:`before_request`, but before every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.before_request`. + """ + self.record_once( + lambda s: s.app.before_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def before_app_first_request( + self, f: T_before_first_request + ) -> T_before_first_request: + """Register a function to run before the first request to the application is + handled by the worker. Equivalent to :meth:`.Flask.before_first_request`. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Run setup code when creating + the application instead. + """ + import warnings + + warnings.warn( + "'before_app_first_request' is deprecated and will be" + " removed in Flask 2.3. Use 'record_once' instead to run" + " setup code when registering the blueprint.", + DeprecationWarning, + stacklevel=2, + ) + self.record_once(lambda s: s.app.before_first_request_funcs.append(f)) + return f + + @setupmethod + def after_app_request(self, f: T_after_request) -> T_after_request: + """Like :meth:`after_request`, but after every request, not only those handled + by the blueprint. Equivalent to :meth:`.Flask.after_request`. + """ + self.record_once( + lambda s: s.app.after_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def teardown_app_request(self, f: T_teardown) -> T_teardown: + """Like :meth:`teardown_request`, but after every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.teardown_request`. + """ + self.record_once( + lambda s: s.app.teardown_request_funcs.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_context_processor( + self, f: T_template_context_processor + ) -> T_template_context_processor: + """Like :meth:`context_processor`, but for templates rendered by every view, not + only by the blueprint. Equivalent to :meth:`.Flask.context_processor`. + """ + self.record_once( + lambda s: s.app.template_context_processors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_errorhandler( + self, code: t.Union[t.Type[Exception], int] + ) -> t.Callable[[T_error_handler], T_error_handler]: + """Like :meth:`errorhandler`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.errorhandler`. + """ + + def decorator(f: T_error_handler) -> T_error_handler: + self.record_once(lambda s: s.app.errorhandler(code)(f)) + return f + + return decorator + + @setupmethod + def app_url_value_preprocessor( + self, f: T_url_value_preprocessor + ) -> T_url_value_preprocessor: + """Like :meth:`url_value_preprocessor`, but for every request, not only those + handled by the blueprint. Equivalent to :meth:`.Flask.url_value_preprocessor`. + """ + self.record_once( + lambda s: s.app.url_value_preprocessors.setdefault(None, []).append(f) + ) + return f + + @setupmethod + def app_url_defaults(self, f: T_url_defaults) -> T_url_defaults: + """Like :meth:`url_defaults`, but for every request, not only those handled by + the blueprint. Equivalent to :meth:`.Flask.url_defaults`. + """ + self.record_once( + lambda s: s.app.url_default_functions.setdefault(None, []).append(f) + ) + return f diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/cli.py b/flask-server/venv/lib/python3.10/site-packages/flask/cli.py new file mode 100644 index 00000000..37a15ff2 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/cli.py @@ -0,0 +1,1054 @@ +from __future__ import annotations + +import ast +import inspect +import os +import platform +import re +import sys +import traceback +import typing as t +from functools import update_wrapper +from operator import attrgetter + +import click +from click.core import ParameterSource +from werkzeug import run_simple +from werkzeug.serving import is_running_from_reloader +from werkzeug.utils import import_string + +from .globals import current_app +from .helpers import get_debug_flag +from .helpers import get_load_dotenv + +if t.TYPE_CHECKING: + from .app import Flask + + +class NoAppException(click.UsageError): + """Raised if an application cannot be found or loaded.""" + + +def find_best_app(module): + """Given a module instance this tries to find the best possible + application in the module or raises an exception. + """ + from . import Flask + + # Search for the most common names first. + for attr_name in ("app", "application"): + app = getattr(module, attr_name, None) + + if isinstance(app, Flask): + return app + + # Otherwise find the only object that is a Flask instance. + matches = [v for v in module.__dict__.values() if isinstance(v, Flask)] + + if len(matches) == 1: + return matches[0] + elif len(matches) > 1: + raise NoAppException( + "Detected multiple Flask applications in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify the correct one." + ) + + # Search for app factory functions. + for attr_name in ("create_app", "make_app"): + app_factory = getattr(module, attr_name, None) + + if inspect.isfunction(app_factory): + try: + app = app_factory() + + if isinstance(app, Flask): + return app + except TypeError as e: + if not _called_with_wrong_args(app_factory): + raise + + raise NoAppException( + f"Detected factory '{attr_name}' in module '{module.__name__}'," + " but could not call it without arguments. Use" + f" '{module.__name__}:{attr_name}(args)'" + " to specify arguments." + ) from e + + raise NoAppException( + "Failed to find Flask application or factory in module" + f" '{module.__name__}'. Use '{module.__name__}:name'" + " to specify one." + ) + + +def _called_with_wrong_args(f): + """Check whether calling a function raised a ``TypeError`` because + the call failed or because something in the factory raised the + error. + + :param f: The function that was called. + :return: ``True`` if the call failed. + """ + tb = sys.exc_info()[2] + + try: + while tb is not None: + if tb.tb_frame.f_code is f.__code__: + # In the function, it was called successfully. + return False + + tb = tb.tb_next + + # Didn't reach the function. + return True + finally: + # Delete tb to break a circular reference. + # https://docs.python.org/2/library/sys.html#sys.exc_info + del tb + + +def find_app_by_string(module, app_name): + """Check if the given string is a variable name or a function. Call + a function to get the app instance, or return the variable directly. + """ + from . import Flask + + # Parse app_name as a single expression to determine if it's a valid + # attribute name or function call. + try: + expr = ast.parse(app_name.strip(), mode="eval").body + except SyntaxError: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) from None + + if isinstance(expr, ast.Name): + name = expr.id + args = [] + kwargs = {} + elif isinstance(expr, ast.Call): + # Ensure the function name is an attribute name only. + if not isinstance(expr.func, ast.Name): + raise NoAppException( + f"Function reference must be a simple name: {app_name!r}." + ) + + name = expr.func.id + + # Parse the positional and keyword arguments as literals. + try: + args = [ast.literal_eval(arg) for arg in expr.args] + kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in expr.keywords} + except ValueError: + # literal_eval gives cryptic error messages, show a generic + # message with the full expression instead. + raise NoAppException( + f"Failed to parse arguments as literal values: {app_name!r}." + ) from None + else: + raise NoAppException( + f"Failed to parse {app_name!r} as an attribute name or function call." + ) + + try: + attr = getattr(module, name) + except AttributeError as e: + raise NoAppException( + f"Failed to find attribute {name!r} in {module.__name__!r}." + ) from e + + # If the attribute is a function, call it with any args and kwargs + # to get the real application. + if inspect.isfunction(attr): + try: + app = attr(*args, **kwargs) + except TypeError as e: + if not _called_with_wrong_args(attr): + raise + + raise NoAppException( + f"The factory {app_name!r} in module" + f" {module.__name__!r} could not be called with the" + " specified arguments." + ) from e + else: + app = attr + + if isinstance(app, Flask): + return app + + raise NoAppException( + "A valid Flask application was not obtained from" + f" '{module.__name__}:{app_name}'." + ) + + +def prepare_import(path): + """Given a filename this will try to calculate the python path, add it + to the search path and return the actual module name that is expected. + """ + path = os.path.realpath(path) + + fname, ext = os.path.splitext(path) + if ext == ".py": + path = fname + + if os.path.basename(path) == "__init__": + path = os.path.dirname(path) + + module_name = [] + + # move up until outside package structure (no __init__.py) + while True: + path, name = os.path.split(path) + module_name.append(name) + + if not os.path.exists(os.path.join(path, "__init__.py")): + break + + if sys.path[0] != path: + sys.path.insert(0, path) + + return ".".join(module_name[::-1]) + + +def locate_app(module_name, app_name, raise_if_not_found=True): + try: + __import__(module_name) + except ImportError: + # Reraise the ImportError if it occurred within the imported module. + # Determine this by checking whether the trace has a depth > 1. + if sys.exc_info()[2].tb_next: + raise NoAppException( + f"While importing {module_name!r}, an ImportError was" + f" raised:\n\n{traceback.format_exc()}" + ) from None + elif raise_if_not_found: + raise NoAppException(f"Could not import {module_name!r}.") from None + else: + return + + module = sys.modules[module_name] + + if app_name is None: + return find_best_app(module) + else: + return find_app_by_string(module, app_name) + + +def get_version(ctx, param, value): + if not value or ctx.resilient_parsing: + return + + import werkzeug + from . import __version__ + + click.echo( + f"Python {platform.python_version()}\n" + f"Flask {__version__}\n" + f"Werkzeug {werkzeug.__version__}", + color=ctx.color, + ) + ctx.exit() + + +version_option = click.Option( + ["--version"], + help="Show the Flask version.", + expose_value=False, + callback=get_version, + is_flag=True, + is_eager=True, +) + + +class ScriptInfo: + """Helper object to deal with Flask applications. This is usually not + necessary to interface with as it's used internally in the dispatching + to click. In future versions of Flask this object will most likely play + a bigger role. Typically it's created automatically by the + :class:`FlaskGroup` but you can also manually create it and pass it + onwards as click object. + """ + + def __init__( + self, + app_import_path: str | None = None, + create_app: t.Callable[..., Flask] | None = None, + set_debug_flag: bool = True, + ) -> None: + #: Optionally the import path for the Flask application. + self.app_import_path = app_import_path + #: Optionally a function that is passed the script info to create + #: the instance of the application. + self.create_app = create_app + #: A dictionary with arbitrary data that can be associated with + #: this script info. + self.data: t.Dict[t.Any, t.Any] = {} + self.set_debug_flag = set_debug_flag + self._loaded_app: Flask | None = None + + def load_app(self) -> Flask: + """Loads the Flask app (if not yet loaded) and returns it. Calling + this multiple times will just result in the already loaded app to + be returned. + """ + if self._loaded_app is not None: + return self._loaded_app + + if self.create_app is not None: + app = self.create_app() + else: + if self.app_import_path: + path, name = ( + re.split(r":(?![\\/])", self.app_import_path, 1) + [None] + )[:2] + import_name = prepare_import(path) + app = locate_app(import_name, name) + else: + for path in ("wsgi.py", "app.py"): + import_name = prepare_import(path) + app = locate_app(import_name, None, raise_if_not_found=False) + + if app: + break + + if not app: + raise NoAppException( + "Could not locate a Flask application. Use the" + " 'flask --app' option, 'FLASK_APP' environment" + " variable, or a 'wsgi.py' or 'app.py' file in the" + " current directory." + ) + + if self.set_debug_flag: + # Update the app's debug flag through the descriptor so that + # other values repopulate as well. + app.debug = get_debug_flag() + + self._loaded_app = app + return app + + +pass_script_info = click.make_pass_decorator(ScriptInfo, ensure=True) + + +def with_appcontext(f): + """Wraps a callback so that it's guaranteed to be executed with the + script's application context. + + Custom commands (and their options) registered under ``app.cli`` or + ``blueprint.cli`` will always have an app context available, this + decorator is not required in that case. + + .. versionchanged:: 2.2 + The app context is active for subcommands as well as the + decorated callback. The app context is always available to + ``app.cli`` command and parameter callbacks. + """ + + @click.pass_context + def decorator(__ctx, *args, **kwargs): + if not current_app: + app = __ctx.ensure_object(ScriptInfo).load_app() + __ctx.with_resource(app.app_context()) + + return __ctx.invoke(f, *args, **kwargs) + + return update_wrapper(decorator, f) + + +class AppGroup(click.Group): + """This works similar to a regular click :class:`~click.Group` but it + changes the behavior of the :meth:`command` decorator so that it + automatically wraps the functions in :func:`with_appcontext`. + + Not to be confused with :class:`FlaskGroup`. + """ + + def command(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it wraps callbacks in :func:`with_appcontext` + unless it's disabled by passing ``with_appcontext=False``. + """ + wrap_for_ctx = kwargs.pop("with_appcontext", True) + + def decorator(f): + if wrap_for_ctx: + f = with_appcontext(f) + return click.Group.command(self, *args, **kwargs)(f) + + return decorator + + def group(self, *args, **kwargs): + """This works exactly like the method of the same name on a regular + :class:`click.Group` but it defaults the group class to + :class:`AppGroup`. + """ + kwargs.setdefault("cls", AppGroup) + return click.Group.group(self, *args, **kwargs) + + +def _set_app(ctx: click.Context, param: click.Option, value: str | None) -> str | None: + if value is None: + return None + + info = ctx.ensure_object(ScriptInfo) + info.app_import_path = value + return value + + +# This option is eager so the app will be available if --help is given. +# --help is also eager, so --app must be before it in the param list. +# no_args_is_help bypasses eager processing, so this option must be +# processed manually in that case to ensure FLASK_APP gets picked up. +_app_option = click.Option( + ["-A", "--app"], + metavar="IMPORT", + help=( + "The Flask application or factory function to load, in the form 'module:name'." + " Module can be a dotted import or file path. Name is not required if it is" + " 'app', 'application', 'create_app', or 'make_app', and can be 'name(args)' to" + " pass arguments." + ), + is_eager=True, + expose_value=False, + callback=_set_app, +) + + +def _set_debug(ctx: click.Context, param: click.Option, value: bool) -> bool | None: + # If the flag isn't provided, it will default to False. Don't use + # that, let debug be set by env in that case. + source = ctx.get_parameter_source(param.name) # type: ignore[arg-type] + + if source is not None and source in ( + ParameterSource.DEFAULT, + ParameterSource.DEFAULT_MAP, + ): + return None + + # Set with env var instead of ScriptInfo.load so that it can be + # accessed early during a factory function. + os.environ["FLASK_DEBUG"] = "1" if value else "0" + return value + + +_debug_option = click.Option( + ["--debug/--no-debug"], + help="Set debug mode.", + expose_value=False, + callback=_set_debug, +) + + +def _env_file_callback( + ctx: click.Context, param: click.Option, value: str | None +) -> str | None: + if value is None: + return None + + import importlib + + try: + importlib.import_module("dotenv") + except ImportError: + raise click.BadParameter( + "python-dotenv must be installed to load an env file.", + ctx=ctx, + param=param, + ) from None + + # Don't check FLASK_SKIP_DOTENV, that only disables automatically + # loading .env and .flaskenv files. + load_dotenv(value) + return value + + +# This option is eager so env vars are loaded as early as possible to be +# used by other options. +_env_file_option = click.Option( + ["-e", "--env-file"], + type=click.Path(exists=True, dir_okay=False), + help="Load environment variables from this file. python-dotenv must be installed.", + is_eager=True, + expose_value=False, + callback=_env_file_callback, +) + + +class FlaskGroup(AppGroup): + """Special subclass of the :class:`AppGroup` group that supports + loading more commands from the configured Flask app. Normally a + developer does not have to interface with this class but there are + some very advanced use cases for which it makes sense to create an + instance of this. see :ref:`custom-scripts`. + + :param add_default_commands: if this is True then the default run and + shell commands will be added. + :param add_version_option: adds the ``--version`` option. + :param create_app: an optional callback that is passed the script info and + returns the loaded app. + :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` + files to set environment variables. Will also change the working + directory to the directory containing the first file found. + :param set_debug_flag: Set the app's debug flag. + + .. versionchanged:: 2.2 + Added the ``-A/--app``, ``--debug/--no-debug``, ``-e/--env-file`` options. + + .. versionchanged:: 2.2 + An app context is pushed when running ``app.cli`` commands, so + ``@with_appcontext`` is no longer required for those commands. + + .. versionchanged:: 1.0 + If installed, python-dotenv will be used to load environment variables + from :file:`.env` and :file:`.flaskenv` files. + """ + + def __init__( + self, + add_default_commands: bool = True, + create_app: t.Callable[..., Flask] | None = None, + add_version_option: bool = True, + load_dotenv: bool = True, + set_debug_flag: bool = True, + **extra: t.Any, + ) -> None: + params = list(extra.pop("params", None) or ()) + # Processing is done with option callbacks instead of a group + # callback. This allows users to make a custom group callback + # without losing the behavior. --env-file must come first so + # that it is eagerly evaluated before --app. + params.extend((_env_file_option, _app_option, _debug_option)) + + if add_version_option: + params.append(version_option) + + if "context_settings" not in extra: + extra["context_settings"] = {} + + extra["context_settings"].setdefault("auto_envvar_prefix", "FLASK") + + super().__init__(params=params, **extra) + + self.create_app = create_app + self.load_dotenv = load_dotenv + self.set_debug_flag = set_debug_flag + + if add_default_commands: + self.add_command(run_command) + self.add_command(shell_command) + self.add_command(routes_command) + + self._loaded_plugin_commands = False + + def _load_plugin_commands(self): + if self._loaded_plugin_commands: + return + + if sys.version_info >= (3, 10): + from importlib import metadata + else: + # Use a backport on Python < 3.10. We technically have + # importlib.metadata on 3.8+, but the API changed in 3.10, + # so use the backport for consistency. + import importlib_metadata as metadata + + for ep in metadata.entry_points(group="flask.commands"): + self.add_command(ep.load(), ep.name) + + self._loaded_plugin_commands = True + + def get_command(self, ctx, name): + self._load_plugin_commands() + # Look up built-in and plugin commands, which should be + # available even if the app fails to load. + rv = super().get_command(ctx, name) + + if rv is not None: + return rv + + info = ctx.ensure_object(ScriptInfo) + + # Look up commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + app = info.load_app() + except NoAppException as e: + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + return None + + # Push an app context for the loaded app unless it is already + # active somehow. This makes the context available to parameter + # and command callbacks without needing @with_appcontext. + if not current_app or current_app._get_current_object() is not app: + ctx.with_resource(app.app_context()) + + return app.cli.get_command(ctx, name) + + def list_commands(self, ctx): + self._load_plugin_commands() + # Start with the built-in and plugin commands. + rv = set(super().list_commands(ctx)) + info = ctx.ensure_object(ScriptInfo) + + # Add commands provided by the app, showing an error and + # continuing if the app couldn't be loaded. + try: + rv.update(info.load_app().cli.list_commands(ctx)) + except NoAppException as e: + # When an app couldn't be loaded, show the error message + # without the traceback. + click.secho(f"Error: {e.format_message()}\n", err=True, fg="red") + except Exception: + # When any other errors occurred during loading, show the + # full traceback. + click.secho(f"{traceback.format_exc()}\n", err=True, fg="red") + + return sorted(rv) + + def make_context( + self, + info_name: str | None, + args: list[str], + parent: click.Context | None = None, + **extra: t.Any, + ) -> click.Context: + # Set a flag to tell app.run to become a no-op. If app.run was + # not in a __name__ == __main__ guard, it would start the server + # when importing, blocking whatever command is being called. + os.environ["FLASK_RUN_FROM_CLI"] = "true" + + # Attempt to load .env and .flask env files. The --env-file + # option can cause another file to be loaded. + if get_load_dotenv(self.load_dotenv): + load_dotenv() + + if "obj" not in extra and "obj" not in self.context_settings: + extra["obj"] = ScriptInfo( + create_app=self.create_app, set_debug_flag=self.set_debug_flag + ) + + return super().make_context(info_name, args, parent=parent, **extra) + + def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]: + if not args and self.no_args_is_help: + # Attempt to load --env-file and --app early in case they + # were given as env vars. Otherwise no_args_is_help will not + # see commands from app.cli. + _env_file_option.handle_parse_result(ctx, {}, []) + _app_option.handle_parse_result(ctx, {}, []) + + return super().parse_args(ctx, args) + + +def _path_is_ancestor(path, other): + """Take ``other`` and remove the length of ``path`` from it. Then join it + to ``path``. If it is the original value, ``path`` is an ancestor of + ``other``.""" + return os.path.join(path, other[len(path) :].lstrip(os.sep)) == other + + +def load_dotenv(path: str | os.PathLike | None = None) -> bool: + """Load "dotenv" files in order of precedence to set environment variables. + + If an env var is already set it is not overwritten, so earlier files in the + list are preferred over later files. + + This is a no-op if `python-dotenv`_ is not installed. + + .. _python-dotenv: https://github.com/theskumar/python-dotenv#readme + + :param path: Load the file at this location instead of searching. + :return: ``True`` if a file was loaded. + + .. versionchanged:: 2.0 + The current directory is not changed to the location of the + loaded file. + + .. versionchanged:: 2.0 + When loading the env files, set the default encoding to UTF-8. + + .. versionchanged:: 1.1.0 + Returns ``False`` when python-dotenv is not installed, or when + the given path isn't a file. + + .. versionadded:: 1.0 + """ + try: + import dotenv + except ImportError: + if path or os.path.isfile(".env") or os.path.isfile(".flaskenv"): + click.secho( + " * Tip: There are .env or .flaskenv files present." + ' Do "pip install python-dotenv" to use them.', + fg="yellow", + err=True, + ) + + return False + + # Always return after attempting to load a given path, don't load + # the default files. + if path is not None: + if os.path.isfile(path): + return dotenv.load_dotenv(path, encoding="utf-8") + + return False + + loaded = False + + for name in (".env", ".flaskenv"): + path = dotenv.find_dotenv(name, usecwd=True) + + if not path: + continue + + dotenv.load_dotenv(path, encoding="utf-8") + loaded = True + + return loaded # True if at least one file was located and loaded. + + +def show_server_banner(debug, app_import_path): + """Show extra startup messages the first time the server is run, + ignoring the reloader. + """ + if is_running_from_reloader(): + return + + if app_import_path is not None: + click.echo(f" * Serving Flask app '{app_import_path}'") + + if debug is not None: + click.echo(f" * Debug mode: {'on' if debug else 'off'}") + + +class CertParamType(click.ParamType): + """Click option type for the ``--cert`` option. Allows either an + existing file, the string ``'adhoc'``, or an import for a + :class:`~ssl.SSLContext` object. + """ + + name = "path" + + def __init__(self): + self.path_type = click.Path(exists=True, dir_okay=False, resolve_path=True) + + def convert(self, value, param, ctx): + try: + import ssl + except ImportError: + raise click.BadParameter( + 'Using "--cert" requires Python to be compiled with SSL support.', + ctx, + param, + ) from None + + try: + return self.path_type(value, param, ctx) + except click.BadParameter: + value = click.STRING(value, param, ctx).lower() + + if value == "adhoc": + try: + import cryptography # noqa: F401 + except ImportError: + raise click.BadParameter( + "Using ad-hoc certificates requires the cryptography library.", + ctx, + param, + ) from None + + return value + + obj = import_string(value, silent=True) + + if isinstance(obj, ssl.SSLContext): + return obj + + raise + + +def _validate_key(ctx, param, value): + """The ``--key`` option must be specified when ``--cert`` is a file. + Modifies the ``cert`` param to be a ``(cert, key)`` pair if needed. + """ + cert = ctx.params.get("cert") + is_adhoc = cert == "adhoc" + + try: + import ssl + except ImportError: + is_context = False + else: + is_context = isinstance(cert, ssl.SSLContext) + + if value is not None: + if is_adhoc: + raise click.BadParameter( + 'When "--cert" is "adhoc", "--key" is not used.', ctx, param + ) + + if is_context: + raise click.BadParameter( + 'When "--cert" is an SSLContext object, "--key is not used.', ctx, param + ) + + if not cert: + raise click.BadParameter('"--cert" must also be specified.', ctx, param) + + ctx.params["cert"] = cert, value + + else: + if cert and not (is_adhoc or is_context): + raise click.BadParameter('Required when using "--cert".', ctx, param) + + return value + + +class SeparatedPathType(click.Path): + """Click option type that accepts a list of values separated by the + OS's path separator (``:``, ``;`` on Windows). Each value is + validated as a :class:`click.Path` type. + """ + + def convert(self, value, param, ctx): + items = self.split_envvar_value(value) + super_convert = super().convert + return [super_convert(item, param, ctx) for item in items] + + +@click.command("run", short_help="Run a development server.") +@click.option("--host", "-h", default="127.0.0.1", help="The interface to bind to.") +@click.option("--port", "-p", default=5000, help="The port to bind to.") +@click.option( + "--cert", + type=CertParamType(), + help="Specify a certificate file to use HTTPS.", + is_eager=True, +) +@click.option( + "--key", + type=click.Path(exists=True, dir_okay=False, resolve_path=True), + callback=_validate_key, + expose_value=False, + help="The key file to use when specifying a certificate.", +) +@click.option( + "--reload/--no-reload", + default=None, + help="Enable or disable the reloader. By default the reloader " + "is active if debug is enabled.", +) +@click.option( + "--debugger/--no-debugger", + default=None, + help="Enable or disable the debugger. By default the debugger " + "is active if debug is enabled.", +) +@click.option( + "--with-threads/--without-threads", + default=True, + help="Enable or disable multithreading.", +) +@click.option( + "--extra-files", + default=None, + type=SeparatedPathType(), + help=( + "Extra files that trigger a reload on change. Multiple paths" + f" are separated by {os.path.pathsep!r}." + ), +) +@click.option( + "--exclude-patterns", + default=None, + type=SeparatedPathType(), + help=( + "Files matching these fnmatch patterns will not trigger a reload" + " on change. Multiple patterns are separated by" + f" {os.path.pathsep!r}." + ), +) +@pass_script_info +def run_command( + info, + host, + port, + reload, + debugger, + with_threads, + cert, + extra_files, + exclude_patterns, +): + """Run a local development server. + + This server is for development purposes only. It does not provide + the stability, security, or performance of production WSGI servers. + + The reloader and debugger are enabled by default with the '--debug' + option. + """ + try: + app = info.load_app() + except Exception as e: + if is_running_from_reloader(): + # When reloading, print out the error immediately, but raise + # it later so the debugger or server can handle it. + traceback.print_exc() + err = e + + def app(environ, start_response): + raise err from None + + else: + # When not reloading, raise the error immediately so the + # command fails. + raise e from None + + debug = get_debug_flag() + + if reload is None: + reload = debug + + if debugger is None: + debugger = debug + + show_server_banner(debug, info.app_import_path) + + run_simple( + host, + port, + app, + use_reloader=reload, + use_debugger=debugger, + threaded=with_threads, + ssl_context=cert, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + ) + + +run_command.params.insert(0, _debug_option) + + +@click.command("shell", short_help="Run a shell in the app context.") +@with_appcontext +def shell_command() -> None: + """Run an interactive Python shell in the context of a given + Flask application. The application will populate the default + namespace of this shell according to its configuration. + + This is useful for executing small snippets of management code + without having to manually configure the application. + """ + import code + + banner = ( + f"Python {sys.version} on {sys.platform}\n" + f"App: {current_app.import_name}\n" + f"Instance: {current_app.instance_path}" + ) + ctx: dict = {} + + # Support the regular Python interpreter startup script if someone + # is using it. + startup = os.environ.get("PYTHONSTARTUP") + if startup and os.path.isfile(startup): + with open(startup) as f: + eval(compile(f.read(), startup, "exec"), ctx) + + ctx.update(current_app.make_shell_context()) + + # Site, customize, or startup script can set a hook to call when + # entering interactive mode. The default one sets up readline with + # tab and history completion. + interactive_hook = getattr(sys, "__interactivehook__", None) + + if interactive_hook is not None: + try: + import readline + from rlcompleter import Completer + except ImportError: + pass + else: + # rlcompleter uses __main__.__dict__ by default, which is + # flask.__main__. Use the shell context instead. + readline.set_completer(Completer(ctx).complete) + + interactive_hook() + + code.interact(banner=banner, local=ctx) + + +@click.command("routes", short_help="Show the routes for the app.") +@click.option( + "--sort", + "-s", + type=click.Choice(("endpoint", "methods", "rule", "match")), + default="endpoint", + help=( + 'Method to sort routes by. "match" is the order that Flask will match ' + "routes when dispatching a request." + ), +) +@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.") +@with_appcontext +def routes_command(sort: str, all_methods: bool) -> None: + """Show all registered routes with endpoints and methods.""" + + rules = list(current_app.url_map.iter_rules()) + if not rules: + click.echo("No routes were registered.") + return + + ignored_methods = set(() if all_methods else ("HEAD", "OPTIONS")) + + if sort in ("endpoint", "rule"): + rules = sorted(rules, key=attrgetter(sort)) + elif sort == "methods": + rules = sorted(rules, key=lambda rule: sorted(rule.methods)) # type: ignore + + rule_methods = [ + ", ".join(sorted(rule.methods - ignored_methods)) # type: ignore + for rule in rules + ] + + headers = ("Endpoint", "Methods", "Rule") + widths = ( + max(len(rule.endpoint) for rule in rules), + max(len(methods) for methods in rule_methods), + max(len(rule.rule) for rule in rules), + ) + widths = [max(len(h), w) for h, w in zip(headers, widths)] + row = "{{0:<{0}}} {{1:<{1}}} {{2:<{2}}}".format(*widths) + + click.echo(row.format(*headers).strip()) + click.echo(row.format(*("-" * width for width in widths))) + + for rule, methods in zip(rules, rule_methods): + click.echo(row.format(rule.endpoint, methods, rule.rule).rstrip()) + + +cli = FlaskGroup( + name="flask", + help="""\ +A general utility script for Flask applications. + +An application to load must be given with the '--app' option, +'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file +in the current directory. +""", +) + + +def main() -> None: + cli.main() + + +if __name__ == "__main__": + main() diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/config.py b/flask-server/venv/lib/python3.10/site-packages/flask/config.py new file mode 100644 index 00000000..d4fc310f --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/config.py @@ -0,0 +1,338 @@ +import errno +import json +import os +import types +import typing as t + +from werkzeug.utils import import_string + + +class ConfigAttribute: + """Makes an attribute forward to the config""" + + def __init__(self, name: str, get_converter: t.Optional[t.Callable] = None) -> None: + self.__name__ = name + self.get_converter = get_converter + + def __get__(self, obj: t.Any, owner: t.Any = None) -> t.Any: + if obj is None: + return self + rv = obj.config[self.__name__] + if self.get_converter is not None: + rv = self.get_converter(rv) + return rv + + def __set__(self, obj: t.Any, value: t.Any) -> None: + obj.config[self.__name__] = value + + +class Config(dict): + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__(self, root_path: str, defaults: t.Optional[dict] = None) -> None: + super().__init__(defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name: str, silent: bool = False) -> bool: + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError( + f"The environment variable {variable_name!r} is not set" + " and as such configuration could not be loaded. Set" + " this variable and make it point to a configuration" + " file" + ) + return self.from_pyfile(rv, silent=silent) + + def from_prefixed_env( + self, prefix: str = "FLASK", *, loads: t.Callable[[str], t.Any] = json.loads + ) -> bool: + """Load any environment variables that start with ``FLASK_``, + dropping the prefix from the env key for the config key. Values + are passed through a loading function to attempt to convert them + to more specific types than strings. + + Keys are loaded in :func:`sorted` order. + + The default loading function attempts to parse values as any + valid JSON type, including dicts and lists. + + Specific items in nested dicts can be set by separating the + keys with double underscores (``__``). If an intermediate key + doesn't exist, it will be initialized to an empty dict. + + :param prefix: Load env vars that start with this prefix, + separated with an underscore (``_``). + :param loads: Pass each string value to this function and use + the returned value as the config value. If any error is + raised it is ignored and the value remains a string. The + default is :func:`json.loads`. + + .. versionadded:: 2.1 + """ + prefix = f"{prefix}_" + len_prefix = len(prefix) + + for key in sorted(os.environ): + if not key.startswith(prefix): + continue + + value = os.environ[key] + + try: + value = loads(value) + except Exception: + # Keep the value as a string if loading failed. + pass + + # Change to key.removeprefix(prefix) on Python >= 3.9. + key = key[len_prefix:] + + if "__" not in key: + # A non-nested key, set directly. + self[key] = value + continue + + # Traverse nested dictionaries with keys separated by "__". + current = self + *parts, tail = key.split("__") + + for part in parts: + # If an intermediate dict does not exist, create it. + if part not in current: + current[part] = {} + + current = current[part] + + current[tail] = value + + return True + + def from_pyfile(self, filename: str, silent: bool = False) -> bool: + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to ``True`` if you want silent failure for missing + files. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = types.ModuleType("config") + d.__file__ = filename + try: + with open(filename, mode="rb") as config_file: + exec(compile(config_file.read(), filename, "exec"), d.__dict__) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR, errno.ENOTDIR): + return False + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + self.from_object(d) + return True + + def from_object(self, obj: t.Union[object, str]) -> None: + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. :meth:`from_object` + loads only the uppercase attributes of the module/class. A ``dict`` + object will not work with :meth:`from_object` because the keys of a + ``dict`` are not attributes of the ``dict`` class. + + Example of module-based configuration:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + Nothing is done to the object before loading. If the object is a + class and has ``@property`` attributes, it needs to be + instantiated before being passed to this method. + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + See :ref:`config-dev-prod` for an example of class-based configuration + using :meth:`from_object`. + + :param obj: an import name or object + """ + if isinstance(obj, str): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def from_file( + self, + filename: str, + load: t.Callable[[t.IO[t.Any]], t.Mapping], + silent: bool = False, + ) -> bool: + """Update the values in the config from a file that is loaded + using the ``load`` parameter. The loaded data is passed to the + :meth:`from_mapping` method. + + .. code-block:: python + + import json + app.config.from_file("config.json", load=json.load) + + import toml + app.config.from_file("config.toml", load=toml.load) + + :param filename: The path to the data file. This can be an + absolute path or relative to the config root path. + :param load: A callable that takes a file handle and returns a + mapping of loaded data from the file. + :type load: ``Callable[[Reader], Mapping]`` where ``Reader`` + implements a ``read`` method. + :param silent: Ignore the file if it doesn't exist. + :return: ``True`` if the file was loaded successfully. + + .. versionadded:: 2.0 + """ + filename = os.path.join(self.root_path, filename) + + try: + with open(filename) as f: + obj = load(f) + except OSError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + + e.strerror = f"Unable to load configuration file ({e.strerror})" + raise + + return self.from_mapping(obj) + + def from_mapping( + self, mapping: t.Optional[t.Mapping[str, t.Any]] = None, **kwargs: t.Any + ) -> bool: + """Updates the config like :meth:`update` ignoring items with + non-upper keys. + + :return: Always returns ``True``. + + .. versionadded:: 0.11 + """ + mappings: t.Dict[str, t.Any] = {} + if mapping is not None: + mappings.update(mapping) + mappings.update(kwargs) + for key, value in mappings.items(): + if key.isupper(): + self[key] = value + return True + + def get_namespace( + self, namespace: str, lowercase: bool = True, trim_namespace: bool = True + ) -> t.Dict[str, t.Any]: + """Returns a dictionary containing a subset of configuration options + that match the specified namespace/prefix. Example usage:: + + app.config['IMAGE_STORE_TYPE'] = 'fs' + app.config['IMAGE_STORE_PATH'] = '/var/app/images' + app.config['IMAGE_STORE_BASE_URL'] = 'http://img.website.com' + image_store_config = app.config.get_namespace('IMAGE_STORE_') + + The resulting dictionary `image_store_config` would look like:: + + { + 'type': 'fs', + 'path': '/var/app/images', + 'base_url': 'http://img.website.com' + } + + This is often useful when configuration options map directly to + keyword arguments in functions or class constructors. + + :param namespace: a configuration namespace + :param lowercase: a flag indicating if the keys of the resulting + dictionary should be lowercase + :param trim_namespace: a flag indicating if the keys of the resulting + dictionary should not include the namespace + + .. versionadded:: 0.11 + """ + rv = {} + for k, v in self.items(): + if not k.startswith(namespace): + continue + if trim_namespace: + key = k[len(namespace) :] + else: + key = k + if lowercase: + key = key.lower() + rv[key] = v + return rv + + def __repr__(self) -> str: + return f"<{type(self).__name__} {dict.__repr__(self)}>" diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/ctx.py b/flask-server/venv/lib/python3.10/site-packages/flask/ctx.py new file mode 100644 index 00000000..c79c26dc --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/ctx.py @@ -0,0 +1,438 @@ +import contextvars +import sys +import typing as t +from functools import update_wrapper +from types import TracebackType + +from werkzeug.exceptions import HTTPException + +from . import typing as ft +from .globals import _cv_app +from .globals import _cv_request +from .signals import appcontext_popped +from .signals import appcontext_pushed + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .sessions import SessionMixin + from .wrappers import Request + + +# a singleton sentinel value for parameter defaults +_sentinel = object() + + +class _AppCtxGlobals: + """A plain object. Used as a namespace for storing data during an + application context. + + Creating an app context automatically creates this object, which is + made available as the :data:`g` proxy. + + .. describe:: 'key' in g + + Check whether an attribute is present. + + .. versionadded:: 0.10 + + .. describe:: iter(g) + + Return an iterator over the attribute names. + + .. versionadded:: 0.10 + """ + + # Define attr methods to let mypy know this is a namespace object + # that has arbitrary attributes. + + def __getattr__(self, name: str) -> t.Any: + try: + return self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def __setattr__(self, name: str, value: t.Any) -> None: + self.__dict__[name] = value + + def __delattr__(self, name: str) -> None: + try: + del self.__dict__[name] + except KeyError: + raise AttributeError(name) from None + + def get(self, name: str, default: t.Optional[t.Any] = None) -> t.Any: + """Get an attribute by name, or a default value. Like + :meth:`dict.get`. + + :param name: Name of attribute to get. + :param default: Value to return if the attribute is not present. + + .. versionadded:: 0.10 + """ + return self.__dict__.get(name, default) + + def pop(self, name: str, default: t.Any = _sentinel) -> t.Any: + """Get and remove an attribute by name. Like :meth:`dict.pop`. + + :param name: Name of attribute to pop. + :param default: Value to return if the attribute is not present, + instead of raising a ``KeyError``. + + .. versionadded:: 0.11 + """ + if default is _sentinel: + return self.__dict__.pop(name) + else: + return self.__dict__.pop(name, default) + + def setdefault(self, name: str, default: t.Any = None) -> t.Any: + """Get the value of an attribute if it is present, otherwise + set and return a default value. Like :meth:`dict.setdefault`. + + :param name: Name of attribute to get. + :param default: Value to set and return if the attribute is not + present. + + .. versionadded:: 0.11 + """ + return self.__dict__.setdefault(name, default) + + def __contains__(self, item: str) -> bool: + return item in self.__dict__ + + def __iter__(self) -> t.Iterator[str]: + return iter(self.__dict__) + + def __repr__(self) -> str: + ctx = _cv_app.get(None) + if ctx is not None: + return f"" + return object.__repr__(self) + + +def after_this_request(f: ft.AfterRequestCallable) -> ft.AfterRequestCallable: + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'after_this_request' can only be used when a request" + " context is active, such as in a view function." + ) + + ctx._after_request_functions.append(f) + return f + + +def copy_current_request_context(f: t.Callable) -> t.Callable: + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. The current session is also + included in the copied request context. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request or + # flask.session like you would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + ctx = _cv_request.get(None) + + if ctx is None: + raise RuntimeError( + "'copy_current_request_context' can only be used when a" + " request context is active, such as in a view function." + ) + + ctx = ctx.copy() + + def wrapper(*args, **kwargs): + with ctx: + return ctx.app.ensure_sync(f)(*args, **kwargs) + + return update_wrapper(wrapper, f) + + +def has_request_context() -> bool: + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g`) for truthness:: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _cv_request.get(None) is not None + + +def has_app_context() -> bool: + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _cv_app.get(None) is not None + + +class AppContext: + """The app context contains application-specific information. An app + context is created and pushed at the beginning of each request if + one is not already active. An app context is also pushed when + running CLI commands. + """ + + def __init__(self, app: "Flask") -> None: + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g: _AppCtxGlobals = app.app_ctx_globals_class() + self._cv_tokens: t.List[contextvars.Token] = [] + + def push(self) -> None: + """Binds the app context to the current context.""" + self._cv_tokens.append(_cv_app.set(self)) + appcontext_pushed.send(self.app) + + def pop(self, exc: t.Optional[BaseException] = _sentinel) -> None: # type: ignore + """Pops the app context.""" + try: + if len(self._cv_tokens) == 1: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + finally: + ctx = _cv_app.get() + _cv_app.reset(self._cv_tokens.pop()) + + if ctx is not self: + raise AssertionError( + f"Popped wrong app context. ({ctx!r} instead of {self!r})" + ) + + appcontext_popped.send(self.app) + + def __enter__(self) -> "AppContext": + self.push() + return self + + def __exit__( + self, + exc_type: t.Optional[type], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.pop(exc_value) + + +class RequestContext: + """The request context contains per-request information. The Flask + app creates and pushes it at the beginning of the request, then pops + it at the end of the request. It will create the URL adapter and + request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the + request. When using the interactive debugger, the context will be + restored so ``request`` is still accessible. Similarly, the test + client can preserve the context after the request ends. However, + teardown functions may already have closed some resources such as + database connections. + """ + + def __init__( + self, + app: "Flask", + environ: dict, + request: t.Optional["Request"] = None, + session: t.Optional["SessionMixin"] = None, + ) -> None: + self.app = app + if request is None: + request = app.request_class(environ) + request.json_module = app.json + self.request: Request = request + self.url_adapter = None + try: + self.url_adapter = app.create_url_adapter(self.request) + except HTTPException as e: + self.request.routing_exception = e + self.flashes: t.Optional[t.List[t.Tuple[str, str]]] = None + self.session: t.Optional["SessionMixin"] = session + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions: t.List[ft.AfterRequestCallable] = [] + + self._cv_tokens: t.List[t.Tuple[contextvars.Token, t.Optional[AppContext]]] = [] + + def copy(self) -> "RequestContext": + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + + .. versionchanged:: 1.1 + The current session object is used instead of reloading the original + data. This prevents `flask.session` pointing to an out-of-date object. + """ + return self.__class__( + self.app, + environ=self.request.environ, + request=self.request, + session=self.session, + ) + + def match_request(self) -> None: + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + result = self.url_adapter.match(return_rule=True) # type: ignore + self.request.url_rule, self.request.view_args = result # type: ignore + except HTTPException as e: + self.request.routing_exception = e + + def push(self) -> None: + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _cv_app.get(None) + + if app_ctx is None or app_ctx.app is not self.app: + app_ctx = self.app.app_context() + app_ctx.push() + else: + app_ctx = None + + self._cv_tokens.append((_cv_request.set(self), app_ctx)) + + # Open the session at the moment that the request context is available. + # This allows a custom open_session method to use the request context. + # Only open a new session if this is the first time the request was + # pushed, otherwise stream_with_context loses the session. + if self.session is None: + session_interface = self.app.session_interface + self.session = session_interface.open_session(self.app, self.request) + + if self.session is None: + self.session = session_interface.make_null_session(self.app) + + # Match the request URL after loading the session, so that the + # session is available in custom URL converters. + if self.url_adapter is not None: + self.match_request() + + def pop(self, exc: t.Optional[BaseException] = _sentinel) -> None: # type: ignore + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + clear_request = len(self._cv_tokens) == 1 + + try: + if clear_request: + if exc is _sentinel: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + request_close = getattr(self.request, "close", None) + if request_close is not None: + request_close() + finally: + ctx = _cv_request.get() + token, app_ctx = self._cv_tokens.pop() + _cv_request.reset(token) + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + ctx.request.environ["werkzeug.request"] = None + + if app_ctx is not None: + app_ctx.pop(exc) + + if ctx is not self: + raise AssertionError( + f"Popped wrong request context. ({ctx!r} instead of {self!r})" + ) + + def __enter__(self) -> "RequestContext": + self.push() + return self + + def __exit__( + self, + exc_type: t.Optional[type], + exc_value: t.Optional[BaseException], + tb: t.Optional[TracebackType], + ) -> None: + self.pop(exc_value) + + def __repr__(self) -> str: + return ( + f"<{type(self).__name__} {self.request.url!r}" + f" [{self.request.method}] of {self.app.name}>" + ) diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/debughelpers.py b/flask-server/venv/lib/python3.10/site-packages/flask/debughelpers.py new file mode 100644 index 00000000..b0639892 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/debughelpers.py @@ -0,0 +1,158 @@ +import typing as t + +from .app import Flask +from .blueprints import Blueprint +from .globals import request_ctx + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request, key): + form_matches = request.form.getlist(key) + buf = [ + f"You tried to access the file {key!r} in the request.files" + " dictionary but it does not exist. The mimetype for the" + f" request is {request.mimetype!r} instead of" + " 'multipart/form-data' which means that no file contents" + " were transmitted. To fix this error you should provide" + ' enctype="multipart/form-data" in your form.' + ] + if form_matches: + names = ", ".join(repr(x) for x in form_matches) + buf.append( + "\n\nThe browser instead transmitted some file names. " + f"This was submitted: {names}" + ) + self.msg = "".join(buf) + + def __str__(self): + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised in debug mode if a routing redirect + would cause the browser to drop the method or body. This happens + when method is not GET, HEAD or OPTIONS and the status code is not + 307 or 308. + """ + + def __init__(self, request): + exc = request.routing_exception + buf = [ + f"A request was sent to '{request.url}', but routing issued" + f" a redirect to the canonical URL '{exc.new_url}'." + ] + + if f"{request.base_url}/" == exc.new_url.partition("?")[0]: + buf.append( + " The URL was defined with a trailing slash. Flask" + " will redirect to the URL with a trailing slash if it" + " was accessed without one." + ) + + buf.append( + " Send requests to the canonical URL, or use 307 or 308 for" + " routing redirects. Otherwise, browsers will drop form" + " data.\n\n" + "This exception is only raised in debug mode." + ) + super().__init__("".join(buf)) + + +def attach_enctype_error_multidict(request): + """Patch ``request.files.__getitem__`` to raise a descriptive error + about ``enctype=multipart/form-data``. + + :param request: The request to patch. + :meta private: + """ + oldcls = request.files.__class__ + + class newcls(oldcls): + def __getitem__(self, key): + try: + return super().__getitem__(key) + except KeyError as e: + if key not in request.form: + raise + + raise DebugFilesKeyError(request, key).with_traceback( + e.__traceback__ + ) from None + + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls + + +def _dump_loader_info(loader) -> t.Generator: + yield f"class: {type(loader).__module__}.{type(loader).__name__}" + for key, value in sorted(loader.__dict__.items()): + if key.startswith("_"): + continue + if isinstance(value, (tuple, list)): + if not all(isinstance(x, str) for x in value): + continue + yield f"{key}:" + for item in value: + yield f" - {item}" + continue + elif not isinstance(value, (str, int, float, bool)): + continue + yield f"{key}: {value!r}" + + +def explain_template_loading_attempts(app: Flask, template, attempts) -> None: + """This should help developers understand what failed""" + info = [f"Locating template {template!r}:"] + total_found = 0 + blueprint = None + if request_ctx and request_ctx.request.blueprint is not None: + blueprint = request_ctx.request.blueprint + + for idx, (loader, srcobj, triple) in enumerate(attempts): + if isinstance(srcobj, Flask): + src_info = f"application {srcobj.import_name!r}" + elif isinstance(srcobj, Blueprint): + src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})" + else: + src_info = repr(srcobj) + + info.append(f"{idx + 1:5}: trying loader of {src_info}") + + for line in _dump_loader_info(loader): + info.append(f" {line}") + + if triple is None: + detail = "no match" + else: + detail = f"found ({triple[1] or ''!r})" + total_found += 1 + info.append(f" -> {detail}") + + seems_fishy = False + if total_found == 0: + info.append("Error: the template could not be found.") + seems_fishy = True + elif total_found > 1: + info.append("Warning: multiple loaders returned a match for the template.") + seems_fishy = True + + if blueprint is not None and seems_fishy: + info.append( + " The template was looked up from an endpoint that belongs" + f" to the blueprint {blueprint!r}." + ) + info.append(" Maybe you did not place a template in the right folder?") + info.append(" See https://flask.palletsprojects.com/blueprints/#templates") + + app.logger.info("\n".join(info)) diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/globals.py b/flask-server/venv/lib/python3.10/site-packages/flask/globals.py new file mode 100644 index 00000000..254da42b --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/globals.py @@ -0,0 +1,107 @@ +import typing as t +from contextvars import ContextVar + +from werkzeug.local import LocalProxy + +if t.TYPE_CHECKING: # pragma: no cover + from .app import Flask + from .ctx import _AppCtxGlobals + from .ctx import AppContext + from .ctx import RequestContext + from .sessions import SessionMixin + from .wrappers import Request + + +class _FakeStack: + def __init__(self, name: str, cv: ContextVar[t.Any]) -> None: + self.name = name + self.cv = cv + + def _warn(self): + import warnings + + warnings.warn( + f"'_{self.name}_ctx_stack' is deprecated and will be" + " removed in Flask 2.3. Use 'g' to store data, or" + f" '{self.name}_ctx' to access the current context.", + DeprecationWarning, + stacklevel=3, + ) + + def push(self, obj: t.Any) -> None: + self._warn() + self.cv.set(obj) + + def pop(self) -> t.Any: + self._warn() + ctx = self.cv.get(None) + self.cv.set(None) + return ctx + + @property + def top(self) -> t.Optional[t.Any]: + self._warn() + return self.cv.get(None) + + +_no_app_msg = """\ +Working outside of application context. + +This typically means that you attempted to use functionality that needed +the current application. To solve this, set up an application context +with app.app_context(). See the documentation for more information.\ +""" +_cv_app: ContextVar["AppContext"] = ContextVar("flask.app_ctx") +__app_ctx_stack = _FakeStack("app", _cv_app) +app_ctx: "AppContext" = LocalProxy( # type: ignore[assignment] + _cv_app, unbound_message=_no_app_msg +) +current_app: "Flask" = LocalProxy( # type: ignore[assignment] + _cv_app, "app", unbound_message=_no_app_msg +) +g: "_AppCtxGlobals" = LocalProxy( # type: ignore[assignment] + _cv_app, "g", unbound_message=_no_app_msg +) + +_no_req_msg = """\ +Working outside of request context. + +This typically means that you attempted to use functionality that needed +an active HTTP request. Consult the documentation on testing for +information about how to avoid this problem.\ +""" +_cv_request: ContextVar["RequestContext"] = ContextVar("flask.request_ctx") +__request_ctx_stack = _FakeStack("request", _cv_request) +request_ctx: "RequestContext" = LocalProxy( # type: ignore[assignment] + _cv_request, unbound_message=_no_req_msg +) +request: "Request" = LocalProxy( # type: ignore[assignment] + _cv_request, "request", unbound_message=_no_req_msg +) +session: "SessionMixin" = LocalProxy( # type: ignore[assignment] + _cv_request, "session", unbound_message=_no_req_msg +) + + +def __getattr__(name: str) -> t.Any: + if name == "_app_ctx_stack": + import warnings + + warnings.warn( + "'_app_ctx_stack' is deprecated and will be removed in Flask 2.3.", + DeprecationWarning, + stacklevel=2, + ) + return __app_ctx_stack + + if name == "_request_ctx_stack": + import warnings + + warnings.warn( + "'_request_ctx_stack' is deprecated and will be removed in Flask 2.3.", + DeprecationWarning, + stacklevel=2, + ) + return __request_ctx_stack + + raise AttributeError(name) diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/helpers.py b/flask-server/venv/lib/python3.10/site-packages/flask/helpers.py new file mode 100644 index 00000000..3833cb8a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/helpers.py @@ -0,0 +1,705 @@ +import os +import pkgutil +import socket +import sys +import typing as t +from datetime import datetime +from functools import lru_cache +from functools import update_wrapper +from threading import RLock + +import werkzeug.utils +from werkzeug.exceptions import abort as _wz_abort +from werkzeug.utils import redirect as _wz_redirect + +from .globals import _cv_request +from .globals import current_app +from .globals import request +from .globals import request_ctx +from .globals import session +from .signals import message_flashed + +if t.TYPE_CHECKING: # pragma: no cover + from werkzeug.wrappers import Response as BaseResponse + from .wrappers import Response + import typing_extensions as te + + +def get_env() -> str: + """Get the environment the app is running in, indicated by the + :envvar:`FLASK_ENV` environment variable. The default is + ``'production'``. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. + """ + import warnings + + warnings.warn( + "'FLASK_ENV' and 'get_env' are deprecated and will be removed" + " in Flask 2.3. Use 'FLASK_DEBUG' instead.", + DeprecationWarning, + stacklevel=2, + ) + return os.environ.get("FLASK_ENV") or "production" + + +def get_debug_flag() -> bool: + """Get whether debug mode should be enabled for the app, indicated by the + :envvar:`FLASK_DEBUG` environment variable. The default is ``False``. + """ + val = os.environ.get("FLASK_DEBUG") + + if not val: + env = os.environ.get("FLASK_ENV") + + if env is not None: + print( + "'FLASK_ENV' is deprecated and will not be used in" + " Flask 2.3. Use 'FLASK_DEBUG' instead.", + file=sys.stderr, + ) + return env == "development" + + return False + + return val.lower() not in {"0", "false", "no"} + + +def get_load_dotenv(default: bool = True) -> bool: + """Get whether the user has disabled loading default dotenv files by + setting :envvar:`FLASK_SKIP_DOTENV`. The default is ``True``, load + the files. + + :param default: What to return if the env var isn't set. + """ + val = os.environ.get("FLASK_SKIP_DOTENV") + + if not val: + return default + + return val.lower() in ("0", "false", "no") + + +def stream_with_context( + generator_or_function: t.Union[ + t.Iterator[t.AnyStr], t.Callable[..., t.Iterator[t.AnyStr]] + ] +) -> t.Iterator[t.AnyStr]: + """Request contexts disappear when the response is started on the server. + This is done for efficiency reasons and to make it less likely to encounter + memory leaks with badly written WSGI middlewares. The downside is that if + you are using streamed responses, the generator cannot access request bound + information any more. + + This function however can help you keep the context around for longer:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + @stream_with_context + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(generate()) + + Alternatively it can also be used around a specific generator:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) # type: ignore + except TypeError: + + def decorator(*args: t.Any, **kwargs: t.Any) -> t.Any: + gen = generator_or_function(*args, **kwargs) # type: ignore + return stream_with_context(gen) + + return update_wrapper(decorator, generator_or_function) # type: ignore + + def generator() -> t.Generator: + ctx = _cv_request.get(None) + if ctx is None: + raise RuntimeError( + "'stream_with_context' can only be used when a request" + " context is active, such as in a view function." + ) + with ctx: + # Dummy sentinel. Has to be inside the context block or we're + # not actually keeping the context around. + yield None + + # The try/finally is here so that if someone passes a WSGI level + # iterator in we're still running the cleanup logic. Generators + # don't need that because they are closed on their destruction + # automatically. + try: + yield from gen + finally: + if hasattr(gen, "close"): + gen.close() + + # The trick is to start the generator. Then the code execution runs until + # the first dummy None is yielded at which point the context was already + # pushed. This item is discarded. Then when the iteration continues the + # real generator is executed. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g + + +def make_response(*args: t.Any) -> "Response": + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) # type: ignore + + +def url_for( + endpoint: str, + *, + _anchor: t.Optional[str] = None, + _method: t.Optional[str] = None, + _scheme: t.Optional[str] = None, + _external: t.Optional[bool] = None, + **values: t.Any, +) -> str: + """Generate a URL to the given endpoint with the given values. + + This requires an active request or application context, and calls + :meth:`current_app.url_for() `. See that method + for full documentation. + + :param endpoint: The endpoint name associated with the URL to + generate. If this starts with a ``.``, the current blueprint + name (if any) will be used. + :param _anchor: If given, append this as ``#anchor`` to the URL. + :param _method: If given, generate the URL associated with this + method for the endpoint. + :param _scheme: If given, the URL will have this scheme if it is + external. + :param _external: If given, prefer the URL to be internal (False) or + require it to be external (True). External URLs include the + scheme and domain. When not in an active request, URLs are + external by default. + :param values: Values to use for the variable parts of the URL rule. + Unknown keys are appended as query string arguments, like + ``?a=b&c=d``. + + .. versionchanged:: 2.2 + Calls ``current_app.url_for``, allowing an app to override the + behavior. + + .. versionchanged:: 0.10 + The ``_scheme`` parameter was added. + + .. versionchanged:: 0.9 + The ``_anchor`` and ``_method`` parameters were added. + + .. versionchanged:: 0.9 + Calls ``app.handle_url_build_error`` on build errors. + """ + return current_app.url_for( + endpoint, + _anchor=_anchor, + _method=_method, + _scheme=_scheme, + _external=_external, + **values, + ) + + +def redirect( + location: str, code: int = 302, Response: t.Optional[t.Type["BaseResponse"]] = None +) -> "BaseResponse": + """Create a redirect response object. + + If :data:`~flask.current_app` is available, it will use its + :meth:`~flask.Flask.redirect` method, otherwise it will use + :func:`werkzeug.utils.redirect`. + + :param location: The URL to redirect to. + :param code: The status code for the redirect. + :param Response: The response class to use. Not used when + ``current_app`` is active, which uses ``app.response_class``. + + .. versionadded:: 2.2 + Calls ``current_app.redirect`` if available instead of always + using Werkzeug's default ``redirect``. + """ + if current_app: + return current_app.redirect(location, code=code) + + return _wz_redirect(location, code=code, Response=Response) + + +def abort( + code: t.Union[int, "BaseResponse"], *args: t.Any, **kwargs: t.Any +) -> "te.NoReturn": + """Raise an :exc:`~werkzeug.exceptions.HTTPException` for the given + status code. + + If :data:`~flask.current_app` is available, it will call its + :attr:`~flask.Flask.aborter` object, otherwise it will use + :func:`werkzeug.exceptions.abort`. + + :param code: The status code for the exception, which must be + registered in ``app.aborter``. + :param args: Passed to the exception. + :param kwargs: Passed to the exception. + + .. versionadded:: 2.2 + Calls ``current_app.aborter`` if available instead of always + using Werkzeug's default ``abort``. + """ + if current_app: + current_app.aborter(code, *args, **kwargs) + + _wz_abort(code, *args, **kwargs) + + +def get_template_attribute(template_name: str, attribute: str) -> t.Any: + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named :file:`_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, attribute) + + +def flash(message: str, category: str = "message") -> None: + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # always in sync with the session object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get("_flashes", []) + flashes.append((category, message)) + session["_flashes"] = flashes + message_flashed.send( + current_app._get_current_object(), # type: ignore + message=message, + category=category, + ) + + +def get_flashed_messages( + with_categories: bool = False, category_filter: t.Iterable[str] = () +) -> t.Union[t.List[str], t.List[t.Tuple[str, str]]]: + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to ``True``, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (``True`` gives a tuple, where ``False`` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :doc:`/patterns/flashing` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to ``True`` to also receive categories. + :param category_filter: filter of categories to limit return values. Only + categories in the list will be returned. + """ + flashes = request_ctx.flashes + if flashes is None: + flashes = session.pop("_flashes") if "_flashes" in session else [] + request_ctx.flashes = flashes + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def _prepare_send_file_kwargs(**kwargs: t.Any) -> t.Dict[str, t.Any]: + if kwargs.get("max_age") is None: + kwargs["max_age"] = current_app.get_send_file_max_age + + kwargs.update( + environ=request.environ, + use_x_sendfile=current_app.config["USE_X_SENDFILE"], + response_class=current_app.response_class, + _root_path=current_app.root_path, # type: ignore + ) + return kwargs + + +def send_file( + path_or_file: t.Union[os.PathLike, str, t.BinaryIO], + mimetype: t.Optional[str] = None, + as_attachment: bool = False, + download_name: t.Optional[str] = None, + conditional: bool = True, + etag: t.Union[bool, str] = True, + last_modified: t.Optional[t.Union[datetime, int, float]] = None, + max_age: t.Optional[ + t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]] + ] = None, +) -> "Response": + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve + user-requested paths from within a directory. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, configuring Flask with + ``USE_X_SENDFILE = True`` will tell the server to send the given + path, which is much more efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + + .. versionchanged:: 2.0 + ``download_name`` replaces the ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces the ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces the ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + Passing a file-like object that inherits from + :class:`~io.TextIOBase` will raise a :exc:`ValueError` rather + than sending an empty file. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionchanged:: 1.1 + ``filename`` may be a :class:`~os.PathLike` object. + + .. versionchanged:: 1.1 + Passing a :class:`~io.BytesIO` object supports range requests. + + .. versionchanged:: 1.0.3 + Filenames are encoded with ASCII instead of Latin-1 for broader + compatibility with WSGI servers. + + .. versionchanged:: 1.0 + UTF-8 filenames as specified in :rfc:`2231` are supported. + + .. versionchanged:: 0.12 + The filename is no longer automatically inferred from file + objects. If you want to use automatic MIME and etag support, + pass a filename via ``filename_or_fp`` or + ``attachment_filename``. + + .. versionchanged:: 0.12 + ``attachment_filename`` is preferred over ``filename`` for MIME + detection. + + .. versionchanged:: 0.9 + ``cache_timeout`` defaults to + :meth:`Flask.get_send_file_max_age`. + + .. versionchanged:: 0.7 + MIME guessing and etag support for file-like objects was + deprecated because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. + + .. versionchanged:: 0.5 + The ``add_etags``, ``cache_timeout`` and ``conditional`` + parameters were added. The default behavior is to add etags. + + .. versionadded:: 0.2 + """ + return werkzeug.utils.send_file( # type: ignore[return-value] + **_prepare_send_file_kwargs( + path_or_file=path_or_file, + environ=request.environ, + mimetype=mimetype, + as_attachment=as_attachment, + download_name=download_name, + conditional=conditional, + etag=etag, + last_modified=last_modified, + max_age=max_age, + ) + ) + + +def send_from_directory( + directory: t.Union[os.PathLike, str], + path: t.Union[os.PathLike, str], + **kwargs: t.Any, +) -> "Response": + """Send a file from within a directory using :func:`send_file`. + + .. code-block:: python + + @app.route("/uploads/") + def download_file(name): + return send_from_directory( + app.config['UPLOAD_FOLDER'], name, as_attachment=True + ) + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + raises a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under, + relative to the current application's root path. + :param path: The path to the file to send, relative to + ``directory``. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionchanged:: 2.0 + ``path`` replaces the ``filename`` parameter. + + .. versionadded:: 2.0 + Moved the implementation to Werkzeug. This is now a wrapper to + pass some Flask-specific arguments. + + .. versionadded:: 0.5 + """ + return werkzeug.utils.send_from_directory( # type: ignore[return-value] + directory, path, **_prepare_send_file_kwargs(**kwargs) + ) + + +def get_root_path(import_name: str) -> str: + """Find the root path of a package, or the path that contains a + module. If it cannot be found, returns the current working + directory. + + Not to be confused with the value returned by :func:`find_package`. + + :meta private: + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + + if mod is not None and hasattr(mod, "__file__") and mod.__file__ is not None: + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + loader = pkgutil.get_loader(import_name) + + # Loader does not exist or we're referring to an unloaded main + # module or a main module without path (interactive sessions), go + # with the current working directory. + if loader is None or import_name == "__main__": + return os.getcwd() + + if hasattr(loader, "get_filename"): + filepath = loader.get_filename(import_name) + else: + # Fall back to imports. + __import__(import_name) + mod = sys.modules[import_name] + filepath = getattr(mod, "__file__", None) + + # If we don't have a file path it might be because it is a + # namespace package. In this case pick the root path from the + # first module that is contained in the package. + if filepath is None: + raise RuntimeError( + "No root path can be found for the provided module" + f" {import_name!r}. This can happen because the module" + " came from an import hook that does not provide file" + " name information or because it's a namespace package." + " In this case the root path needs to be explicitly" + " provided." + ) + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) + + +class locked_cached_property(werkzeug.utils.cached_property): + """A :func:`property` that is only evaluated once. Like + :class:`werkzeug.utils.cached_property` except access uses a lock + for thread safety. + + .. versionchanged:: 2.0 + Inherits from Werkzeug's ``cached_property`` (and ``property``). + """ + + def __init__( + self, + fget: t.Callable[[t.Any], t.Any], + name: t.Optional[str] = None, + doc: t.Optional[str] = None, + ) -> None: + super().__init__(fget, name=name, doc=doc) + self.lock = RLock() + + def __get__(self, obj: object, type: type = None) -> t.Any: # type: ignore + if obj is None: + return self + + with self.lock: + return super().__get__(obj, type=type) + + def __set__(self, obj: object, value: t.Any) -> None: + with self.lock: + super().__set__(obj, value) + + def __delete__(self, obj: object) -> None: + with self.lock: + super().__delete__(obj) + + +def is_ip(value: str) -> bool: + """Determine if the given string is an IP address. + + :param value: value to check + :type value: str + + :return: True if string is an IP address + :rtype: bool + """ + for family in (socket.AF_INET, socket.AF_INET6): + try: + socket.inet_pton(family, value) + except OSError: + pass + else: + return True + + return False + + +@lru_cache(maxsize=None) +def _split_blueprint_path(name: str) -> t.List[str]: + out: t.List[str] = [name] + + if "." in name: + out.extend(_split_blueprint_path(name.rpartition(".")[0])) + + return out diff --git a/flask-server/venv/lib/python3.10/site-packages/flask/json/__init__.py b/flask-server/venv/lib/python3.10/site-packages/flask/json/__init__.py new file mode 100644 index 00000000..65d8829a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/flask/json/__init__.py @@ -0,0 +1,342 @@ +from __future__ import annotations + +import json as _json +import typing as t + +from jinja2.utils import htmlsafe_json_dumps as _jinja_htmlsafe_dumps + +from ..globals import current_app +from .provider import _default + +if t.TYPE_CHECKING: # pragma: no cover + from ..app import Flask + from ..wrappers import Response + + +class JSONEncoder(_json.JSONEncoder): + """The default JSON encoder. Handles extra types compared to the + built-in :class:`json.JSONEncoder`. + + - :class:`datetime.datetime` and :class:`datetime.date` are + serialized to :rfc:`822` strings. This is the same as the HTTP + date format. + - :class:`decimal.Decimal` is serialized to a string. + - :class:`uuid.UUID` is serialized to a string. + - :class:`dataclasses.dataclass` is passed to + :func:`dataclasses.asdict`. + - :class:`~markupsafe.Markup` (or any object with a ``__html__`` + method) will call the ``__html__`` method to get a string. + + Assign a subclass of this to :attr:`flask.Flask.json_encoder` or + :attr:`flask.Blueprint.json_encoder` to override the default. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use ``app.json`` instead. + """ + + def __init__(self, **kwargs) -> None: + import warnings + + warnings.warn( + "'JSONEncoder' is deprecated and will be removed in" + " Flask 2.3. Use 'Flask.json' to provide an alternate" + " JSON implementation instead.", + DeprecationWarning, + stacklevel=3, + ) + super().__init__(**kwargs) + + def default(self, o: t.Any) -> t.Any: + """Convert ``o`` to a JSON serializable type. See + :meth:`json.JSONEncoder.default`. Python does not support + overriding how basic types like ``str`` or ``list`` are + serialized, they are handled before this method. + """ + return _default(o) + + +class JSONDecoder(_json.JSONDecoder): + """The default JSON decoder. + + This does not change any behavior from the built-in + :class:`json.JSONDecoder`. + + Assign a subclass of this to :attr:`flask.Flask.json_decoder` or + :attr:`flask.Blueprint.json_decoder` to override the default. + + .. deprecated:: 2.2 + Will be removed in Flask 2.3. Use ``app.json`` instead. + """ + + def __init__(self, **kwargs) -> None: + import warnings + + warnings.warn( + "'JSONDecoder' is deprecated and will be removed in" + " Flask 2.3. Use 'Flask.json' to provide an alternate" + " JSON implementation instead.", + DeprecationWarning, + stacklevel=3, + ) + super().__init__(**kwargs) + + +def dumps(obj: t.Any, *, app: Flask | None = None, **kwargs: t.Any) -> str: + """Serialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dumps() ` + method, otherwise it will use :func:`json.dumps`. + + :param obj: The data to serialize. + :param kwargs: Arguments passed to the ``dumps`` implementation. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dumps``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0.2 + :class:`decimal.Decimal` is supported by converting to a string. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if app is not None: + import warnings + + warnings.warn( + "The 'app' parameter is deprecated and will be removed in" + " Flask 2.3. Call 'app.json.dumps' directly instead.", + DeprecationWarning, + stacklevel=2, + ) + else: + app = current_app + + if app: + return app.json.dumps(obj, **kwargs) + + kwargs.setdefault("default", _default) + return _json.dumps(obj, **kwargs) + + +def dump( + obj: t.Any, fp: t.IO[str], *, app: Flask | None = None, **kwargs: t.Any +) -> None: + """Serialize data as JSON and write to a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.dump() ` + method, otherwise it will use :func:`json.dump`. + + :param obj: The data to serialize. + :param fp: A file opened for writing text. Should use the UTF-8 + encoding to be valid JSON. + :param kwargs: Arguments passed to the ``dump`` implementation. + + .. versionchanged:: 2.2 + Calls ``current_app.json.dump``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + Writing to a binary file, and the ``encoding`` argument, will be + removed in Flask 2.1. + """ + if app is not None: + import warnings + + warnings.warn( + "The 'app' parameter is deprecated and will be removed in" + " Flask 2.3. Call 'app.json.dump' directly instead.", + DeprecationWarning, + stacklevel=2, + ) + else: + app = current_app + + if app: + app.json.dump(obj, fp, **kwargs) + else: + kwargs.setdefault("default", _default) + _json.dump(obj, fp, **kwargs) + + +def loads(s: str | bytes, *, app: Flask | None = None, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.loads() ` + method, otherwise it will use :func:`json.loads`. + + :param s: Text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``loads`` implementation. + + .. versionchanged:: 2.2 + Calls ``current_app.json.loads``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The data must be a + string or UTF-8 bytes. + + .. versionchanged:: 1.0.3 + ``app`` can be passed directly, rather than requiring an app + context for configuration. + """ + if app is not None: + import warnings + + warnings.warn( + "The 'app' parameter is deprecated and will be removed in" + " Flask 2.3. Call 'app.json.loads' directly instead.", + DeprecationWarning, + stacklevel=2, + ) + else: + app = current_app + + if app: + return app.json.loads(s, **kwargs) + + return _json.loads(s, **kwargs) + + +def load(fp: t.IO[t.AnyStr], *, app: Flask | None = None, **kwargs: t.Any) -> t.Any: + """Deserialize data as JSON read from a file. + + If :data:`~flask.current_app` is available, it will use its + :meth:`app.json.load() ` + method, otherwise it will use :func:`json.load`. + + :param fp: A file opened for reading text or UTF-8 bytes. + :param kwargs: Arguments passed to the ``load`` implementation. + + .. versionchanged:: 2.2 + Calls ``current_app.json.load``, allowing an app to override + the behavior. + + .. versionchanged:: 2.2 + The ``app`` parameter will be removed in Flask 2.3. + + .. versionchanged:: 2.0 + ``encoding`` will be removed in Flask 2.1. The file must be text + mode, or binary mode with UTF-8 bytes. + """ + if app is not None: + import warnings + + warnings.warn( + "The 'app' parameter is deprecated and will be removed in" + " Flask 2.3. Call 'app.json.load' directly instead.", + DeprecationWarning, + stacklevel=2, + ) + else: + app = current_app + + if app: + return app.json.load(fp, **kwargs) + + return _json.load(fp, **kwargs) + + +def htmlsafe_dumps(obj: t.Any, **kwargs: t.Any) -> str: + """Serialize an object to a string of JSON with :func:`dumps`, then + replace HTML-unsafe characters with Unicode escapes and mark the + result safe with :class:`~markupsafe.Markup`. + + This is available in templates as the ``|tojson`` filter. + + The returned string is safe to render in HTML documents and + `` + + + +
+""" + +FOOTER = """\ + +
+ +
+
+

Console Locked

+

+ The console is locked and needs to be unlocked by entering the PIN. + You can find the PIN printed out on the standard output of your + shell that runs the server. +

+

PIN: + + +

+
+
+ + +""" + +PAGE_HTML = ( + HEADER + + """\ +

%(exception_type)s

+
+

%(exception)s

+
+

Traceback (most recent call last)

+%(summary)s +
+

+ This is the Copy/Paste friendly version of the traceback. +

+ +
+
+ The debugger caught an exception in your WSGI application. You can now + look at the traceback which led to the error. + If you enable JavaScript you can also use additional features such as code + execution (if the evalex feature is enabled), automatic pasting of the + exceptions and much more. +
+""" + + FOOTER + + """ + +""" +) + +CONSOLE_HTML = ( + HEADER + + """\ +

Interactive Console

+
+In this console you can execute Python expressions in the context of the +application. The initial namespace was created by the debugger automatically. +
+
The Console requires JavaScript.
+""" + + FOOTER +) + +SUMMARY_HTML = """\ +
+ %(title)s +
    %(frames)s
+ %(description)s +
+""" + +FRAME_HTML = """\ +
+

File "%(filename)s", + line %(lineno)s, + in %(function_name)s

+
%(lines)s
+
+""" + + +def _process_traceback( + exc: BaseException, + te: t.Optional[traceback.TracebackException] = None, + *, + skip: int = 0, + hide: bool = True, +) -> traceback.TracebackException: + if te is None: + te = traceback.TracebackException.from_exception(exc, lookup_lines=False) + + # Get the frames the same way StackSummary.extract did, in order + # to match each frame with the FrameSummary to augment. + frame_gen = traceback.walk_tb(exc.__traceback__) + limit = getattr(sys, "tracebacklimit", None) + + if limit is not None: + if limit < 0: + limit = 0 + + frame_gen = itertools.islice(frame_gen, limit) + + if skip: + frame_gen = itertools.islice(frame_gen, skip, None) + del te.stack[:skip] + + new_stack: t.List[DebugFrameSummary] = [] + hidden = False + + # Match each frame with the FrameSummary that was generated. + # Hide frames using Paste's __traceback_hide__ rules. Replace + # all visible FrameSummary with DebugFrameSummary. + for (f, _), fs in zip(frame_gen, te.stack): + if hide: + hide_value = f.f_locals.get("__traceback_hide__", False) + + if hide_value in {"before", "before_and_this"}: + new_stack = [] + hidden = False + + if hide_value == "before_and_this": + continue + elif hide_value in {"reset", "reset_and_this"}: + hidden = False + + if hide_value == "reset_and_this": + continue + elif hide_value in {"after", "after_and_this"}: + hidden = True + + if hide_value == "after_and_this": + continue + elif hide_value or hidden: + continue + + frame_args: t.Dict[str, t.Any] = { + "filename": fs.filename, + "lineno": fs.lineno, + "name": fs.name, + "locals": f.f_locals, + "globals": f.f_globals, + } + + if hasattr(fs, "colno"): + frame_args["colno"] = fs.colno + frame_args["end_colno"] = fs.end_colno # type: ignore[attr-defined] + + new_stack.append(DebugFrameSummary(**frame_args)) + + # The codeop module is used to compile code from the interactive + # debugger. Hide any codeop frames from the bottom of the traceback. + while new_stack: + module = new_stack[0].global_ns.get("__name__") + + if module is None: + module = new_stack[0].local_ns.get("__name__") + + if module == "codeop": + del new_stack[0] + else: + break + + te.stack[:] = new_stack + + if te.__context__: + context_exc = t.cast(BaseException, exc.__context__) + te.__context__ = _process_traceback(context_exc, te.__context__, hide=hide) + + if te.__cause__: + cause_exc = t.cast(BaseException, exc.__cause__) + te.__cause__ = _process_traceback(cause_exc, te.__cause__, hide=hide) + + return te + + +class DebugTraceback: + __slots__ = ("_te", "_cache_all_tracebacks", "_cache_all_frames") + + def __init__( + self, + exc: BaseException, + te: t.Optional[traceback.TracebackException] = None, + *, + skip: int = 0, + hide: bool = True, + ) -> None: + self._te = _process_traceback(exc, te, skip=skip, hide=hide) + + def __str__(self) -> str: + return f"<{type(self).__name__} {self._te}>" + + @cached_property + def all_tracebacks( + self, + ) -> t.List[t.Tuple[t.Optional[str], traceback.TracebackException]]: + out = [] + current = self._te + + while current is not None: + if current.__cause__ is not None: + chained_msg = ( + "The above exception was the direct cause of the" + " following exception" + ) + chained_exc = current.__cause__ + elif current.__context__ is not None and not current.__suppress_context__: + chained_msg = ( + "During handling of the above exception, another" + " exception occurred" + ) + chained_exc = current.__context__ + else: + chained_msg = None + chained_exc = None + + out.append((chained_msg, current)) + current = chained_exc + + return out + + @cached_property + def all_frames(self) -> t.List["DebugFrameSummary"]: + return [ + f for _, te in self.all_tracebacks for f in te.stack # type: ignore[misc] + ] + + def render_traceback_text(self) -> str: + return "".join(self._te.format()) + + def render_traceback_html(self, include_title: bool = True) -> str: + library_frames = [f.is_library for f in self.all_frames] + mark_library = 0 < sum(library_frames) < len(library_frames) + rows = [] + + if not library_frames: + classes = "traceback noframe-traceback" + else: + classes = "traceback" + + for msg, current in reversed(self.all_tracebacks): + row_parts = [] + + if msg is not None: + row_parts.append(f'
  • {msg}:
    ') + + for frame in current.stack: + frame = t.cast(DebugFrameSummary, frame) + info = f' title="{escape(frame.info)}"' if frame.info else "" + row_parts.append(f"{frame.render_html(mark_library)}") + + rows.append("\n".join(row_parts)) + + is_syntax_error = issubclass(self._te.exc_type, SyntaxError) + + if include_title: + if is_syntax_error: + title = "Syntax Error" + else: + title = "Traceback (most recent call last):" + else: + title = "" + + exc_full = escape("".join(self._te.format_exception_only())) + + if is_syntax_error: + description = f"
    {exc_full}
    " + else: + description = f"
    {exc_full}
    " + + return SUMMARY_HTML % { + "classes": classes, + "title": f"

    {title}

    ", + "frames": "\n".join(rows), + "description": description, + } + + def render_debugger_html( + self, evalex: bool, secret: str, evalex_trusted: bool + ) -> str: + exc_lines = list(self._te.format_exception_only()) + plaintext = "".join(self._te.format()) + return PAGE_HTML % { + "evalex": "true" if evalex else "false", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "false", + "title": exc_lines[0], + "exception": escape("".join(exc_lines)), + "exception_type": escape(self._te.exc_type.__name__), + "summary": self.render_traceback_html(include_title=False), + "plaintext": escape(plaintext), + "plaintext_cs": re.sub("-{2,}", "-", plaintext), + "secret": secret, + } + + +class DebugFrameSummary(traceback.FrameSummary): + """A :class:`traceback.FrameSummary` that can evaluate code in the + frame's namespace. + """ + + __slots__ = ( + "local_ns", + "global_ns", + "_cache_info", + "_cache_is_library", + "_cache_console", + ) + + def __init__( + self, + *, + locals: t.Dict[str, t.Any], + globals: t.Dict[str, t.Any], + **kwargs: t.Any, + ) -> None: + super().__init__(locals=None, **kwargs) + self.local_ns = locals + self.global_ns = globals + + @cached_property + def info(self) -> t.Optional[str]: + return self.local_ns.get("__traceback_info__") + + @cached_property + def is_library(self) -> bool: + return any( + self.filename.startswith((path, os.path.realpath(path))) + for path in sysconfig.get_paths().values() + ) + + @cached_property + def console(self) -> Console: + return Console(self.global_ns, self.local_ns) + + def eval(self, code: str) -> t.Any: + return self.console.eval(code) + + def render_html(self, mark_library: bool) -> str: + context = 5 + lines = linecache.getlines(self.filename) + line_idx = self.lineno - 1 # type: ignore[operator] + start_idx = max(0, line_idx - context) + stop_idx = min(len(lines), line_idx + context + 1) + rendered_lines = [] + + def render_line(line: str, cls: str) -> None: + line = line.expandtabs().rstrip() + stripped_line = line.strip() + prefix = len(line) - len(stripped_line) + colno = getattr(self, "colno", 0) + end_colno = getattr(self, "end_colno", 0) + + if cls == "current" and colno and end_colno: + arrow = ( + f'\n{" " * prefix}' + f'{" " * (colno - prefix)}{"^" * (end_colno - colno)}' + ) + else: + arrow = "" + + rendered_lines.append( + f'
    {" " * prefix}'
    +                f"{escape(stripped_line) if stripped_line else ' '}"
    +                f"{arrow if arrow else ''}
    " + ) + + if lines: + for line in lines[start_idx:line_idx]: + render_line(line, "before") + + render_line(lines[line_idx], "current") + + for line in lines[line_idx + 1 : stop_idx]: + render_line(line, "after") + + return FRAME_HTML % { + "id": id(self), + "filename": escape(self.filename), + "lineno": self.lineno, + "function_name": escape(self.name), + "lines": "\n".join(rendered_lines), + "library": "library" if mark_library and self.is_library else "", + } + + +def render_console_html(secret: str, evalex_trusted: bool) -> str: + return CONSOLE_HTML % { + "evalex": "true", + "evalex_trusted": "true" if evalex_trusted else "false", + "console": "true", + "title": "Console", + "secret": secret, + } diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/exceptions.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/exceptions.py new file mode 100644 index 00000000..739bd905 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/exceptions.py @@ -0,0 +1,884 @@ +"""Implements a number of Python exceptions which can be raised from within +a view to trigger a standard HTTP non-200 response. + +Usage Example +------------- + +.. code-block:: python + + from werkzeug.wrappers.request import Request + from werkzeug.exceptions import HTTPException, NotFound + + def view(request): + raise NotFound() + + @Request.application + def application(request): + try: + return view(request) + except HTTPException as e: + return e + +As you can see from this example those exceptions are callable WSGI +applications. However, they are not Werkzeug response objects. You +can get a response object by calling ``get_response()`` on a HTTP +exception. + +Keep in mind that you may have to pass an environ (WSGI) or scope +(ASGI) to ``get_response()`` because some errors fetch additional +information relating to the request. + +If you want to hook in a different exception page to say, a 404 status +code, you can add a second except for a specific subclass of an error: + +.. code-block:: python + + @Request.application + def application(request): + try: + return view(request) + except NotFound as e: + return not_found(request) + except HTTPException as e: + return e + +""" +import typing as t +from datetime import datetime + +from markupsafe import escape +from markupsafe import Markup + +from ._internal import _get_environ + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + from .datastructures import WWWAuthenticate + from .sansio.response import Response + from .wrappers.request import Request as WSGIRequest # noqa: F401 + from .wrappers.response import Response as WSGIResponse # noqa: F401 + + +class HTTPException(Exception): + """The base class for all HTTP exceptions. This exception can be called as a WSGI + application to render a default error page or you can catch the subclasses + of it independently and render nicer error messages. + + .. versionchanged:: 2.1 + Removed the ``wrap`` class method. + """ + + code: t.Optional[int] = None + description: t.Optional[str] = None + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + super().__init__() + if description is not None: + self.description = description + self.response = response + + @property + def name(self) -> str: + """The status name.""" + from .http import HTTP_STATUS_CODES + + return HTTP_STATUS_CODES.get(self.code, "Unknown Error") # type: ignore + + def get_description( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> str: + """Get the description.""" + if self.description is None: + description = "" + elif not isinstance(self.description, str): + description = str(self.description) + else: + description = self.description + + description = escape(description).replace("\n", Markup("
    ")) + return f"

    {description}

    " + + def get_body( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> str: + """Get the HTML body.""" + return ( + "\n" + "\n" + f"{self.code} {escape(self.name)}\n" + f"

    {escape(self.name)}

    \n" + f"{self.get_description(environ)}\n" + ) + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + """Get a list of headers.""" + return [("Content-Type", "text/html; charset=utf-8")] + + def get_response( + self, + environ: t.Optional[t.Union["WSGIEnvironment", "WSGIRequest"]] = None, + scope: t.Optional[dict] = None, + ) -> "Response": + """Get a response object. If one was passed to the exception + it's returned directly. + + :param environ: the optional environ for the request. This + can be used to modify the response depending + on how the request looked like. + :return: a :class:`Response` object or a subclass thereof. + """ + from .wrappers.response import Response as WSGIResponse # noqa: F811 + + if self.response is not None: + return self.response + if environ is not None: + environ = _get_environ(environ) + headers = self.get_headers(environ, scope) + return WSGIResponse(self.get_body(environ, scope), self.code, headers) + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Call the exception as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + """ + response = t.cast("WSGIResponse", self.get_response(environ)) + return response(environ, start_response) + + def __str__(self) -> str: + code = self.code if self.code is not None else "???" + return f"{code} {self.name}: {self.description}" + + def __repr__(self) -> str: + code = self.code if self.code is not None else "???" + return f"<{type(self).__name__} '{code}: {self.name}'>" + + +class BadRequest(HTTPException): + """*400* `Bad Request` + + Raise if the browser sends something to the application the application + or server cannot handle. + """ + + code = 400 + description = ( + "The browser (or proxy) sent a request that this server could " + "not understand." + ) + + +class BadRequestKeyError(BadRequest, KeyError): + """An exception that is used to signal both a :exc:`KeyError` and a + :exc:`BadRequest`. Used by many of the datastructures. + """ + + _description = BadRequest.description + #: Show the KeyError along with the HTTP error message in the + #: response. This should be disabled in production, but can be + #: useful in a debug mode. + show_exception = False + + def __init__(self, arg: t.Optional[str] = None, *args: t.Any, **kwargs: t.Any): + super().__init__(*args, **kwargs) + + if arg is None: + KeyError.__init__(self) + else: + KeyError.__init__(self, arg) + + @property # type: ignore + def description(self) -> str: + if self.show_exception: + return ( + f"{self._description}\n" + f"{KeyError.__name__}: {KeyError.__str__(self)}" + ) + + return self._description + + @description.setter + def description(self, value: str) -> None: + self._description = value + + +class ClientDisconnected(BadRequest): + """Internal exception that is raised if Werkzeug detects a disconnected + client. Since the client is already gone at that point attempting to + send the error message to the client might not work and might ultimately + result in another exception in the server. Mainly this is here so that + it is silenced by default as far as Werkzeug is concerned. + + Since disconnections cannot be reliably detected and are unspecified + by WSGI to a large extent this might or might not be raised if a client + is gone. + + .. versionadded:: 0.8 + """ + + +class SecurityError(BadRequest): + """Raised if something triggers a security error. This is otherwise + exactly like a bad request error. + + .. versionadded:: 0.9 + """ + + +class BadHost(BadRequest): + """Raised if the submitted host is badly formatted. + + .. versionadded:: 0.11.2 + """ + + +class Unauthorized(HTTPException): + """*401* ``Unauthorized`` + + Raise if the user is not authorized to access a resource. + + The ``www_authenticate`` argument should be used to set the + ``WWW-Authenticate`` header. This is used for HTTP basic auth and + other schemes. Use :class:`~werkzeug.datastructures.WWWAuthenticate` + to create correctly formatted values. Strictly speaking a 401 + response is invalid if it doesn't provide at least one value for + this header, although real clients typically don't care. + + :param description: Override the default message used for the body + of the response. + :param www-authenticate: A single value, or list of values, for the + WWW-Authenticate header(s). + + .. versionchanged:: 2.0 + Serialize multiple ``www_authenticate`` items into multiple + ``WWW-Authenticate`` headers, rather than joining them + into a single value, for better interoperability. + + .. versionchanged:: 0.15.3 + If the ``www_authenticate`` argument is not set, the + ``WWW-Authenticate`` header is not set. + + .. versionchanged:: 0.15.3 + The ``response`` argument was restored. + + .. versionchanged:: 0.15.1 + ``description`` was moved back as the first argument, restoring + its previous position. + + .. versionchanged:: 0.15.0 + ``www_authenticate`` was added as the first argument, ahead of + ``description``. + """ + + code = 401 + description = ( + "The server could not verify that you are authorized to access" + " the URL requested. You either supplied the wrong credentials" + " (e.g. a bad password), or your browser doesn't understand" + " how to supply the credentials required." + ) + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + www_authenticate: t.Optional[ + t.Union["WWWAuthenticate", t.Iterable["WWWAuthenticate"]] + ] = None, + ) -> None: + super().__init__(description, response) + + from .datastructures import WWWAuthenticate + + if isinstance(www_authenticate, WWWAuthenticate): + www_authenticate = (www_authenticate,) + + self.www_authenticate = www_authenticate + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.www_authenticate: + headers.extend(("WWW-Authenticate", str(x)) for x in self.www_authenticate) + return headers + + +class Forbidden(HTTPException): + """*403* `Forbidden` + + Raise if the user doesn't have the permission for the requested resource + but was authenticated. + """ + + code = 403 + description = ( + "You don't have the permission to access the requested" + " resource. It is either read-protected or not readable by the" + " server." + ) + + +class NotFound(HTTPException): + """*404* `Not Found` + + Raise if a resource does not exist and never existed. + """ + + code = 404 + description = ( + "The requested URL was not found on the server. If you entered" + " the URL manually please check your spelling and try again." + ) + + +class MethodNotAllowed(HTTPException): + """*405* `Method Not Allowed` + + Raise if the server used a method the resource does not handle. For + example `POST` if the resource is view only. Especially useful for REST. + + The first argument for this exception should be a list of allowed methods. + Strictly speaking the response would be invalid if you don't provide valid + methods in the header which you can do with that list. + """ + + code = 405 + description = "The method is not allowed for the requested URL." + + def __init__( + self, + valid_methods: t.Optional[t.Iterable[str]] = None, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + """Takes an optional list of valid http methods + starting with werkzeug 0.3 the list will be mandatory.""" + super().__init__(description=description, response=response) + self.valid_methods = valid_methods + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.valid_methods: + headers.append(("Allow", ", ".join(self.valid_methods))) + return headers + + +class NotAcceptable(HTTPException): + """*406* `Not Acceptable` + + Raise if the server can't return any content conforming to the + `Accept` headers of the client. + """ + + code = 406 + description = ( + "The resource identified by the request is only capable of" + " generating response entities which have content" + " characteristics not acceptable according to the accept" + " headers sent in the request." + ) + + +class RequestTimeout(HTTPException): + """*408* `Request Timeout` + + Raise to signalize a timeout. + """ + + code = 408 + description = ( + "The server closed the network connection because the browser" + " didn't finish the request within the specified time." + ) + + +class Conflict(HTTPException): + """*409* `Conflict` + + Raise to signal that a request cannot be completed because it conflicts + with the current state on the server. + + .. versionadded:: 0.7 + """ + + code = 409 + description = ( + "A conflict happened while processing the request. The" + " resource might have been modified while the request was being" + " processed." + ) + + +class Gone(HTTPException): + """*410* `Gone` + + Raise if a resource existed previously and went away without new location. + """ + + code = 410 + description = ( + "The requested URL is no longer available on this server and" + " there is no forwarding address. If you followed a link from a" + " foreign page, please contact the author of this page." + ) + + +class LengthRequired(HTTPException): + """*411* `Length Required` + + Raise if the browser submitted data but no ``Content-Length`` header which + is required for the kind of processing the server does. + """ + + code = 411 + description = ( + "A request with this method requires a valid Content-" + "Length header." + ) + + +class PreconditionFailed(HTTPException): + """*412* `Precondition Failed` + + Status code used in combination with ``If-Match``, ``If-None-Match``, or + ``If-Unmodified-Since``. + """ + + code = 412 + description = ( + "The precondition on the request for the URL failed positive evaluation." + ) + + +class RequestEntityTooLarge(HTTPException): + """*413* `Request Entity Too Large` + + The status code one should return if the data submitted exceeded a given + limit. + """ + + code = 413 + description = "The data value transmitted exceeds the capacity limit." + + +class RequestURITooLarge(HTTPException): + """*414* `Request URI Too Large` + + Like *413* but for too long URLs. + """ + + code = 414 + description = ( + "The length of the requested URL exceeds the capacity limit for" + " this server. The request cannot be processed." + ) + + +class UnsupportedMediaType(HTTPException): + """*415* `Unsupported Media Type` + + The status code returned if the server is unable to handle the media type + the client transmitted. + """ + + code = 415 + description = ( + "The server does not support the media type transmitted in the request." + ) + + +class RequestedRangeNotSatisfiable(HTTPException): + """*416* `Requested Range Not Satisfiable` + + The client asked for an invalid part of the file. + + .. versionadded:: 0.7 + """ + + code = 416 + description = "The server cannot provide the requested range." + + def __init__( + self, + length: t.Optional[int] = None, + units: str = "bytes", + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + ) -> None: + """Takes an optional `Content-Range` header value based on ``length`` + parameter. + """ + super().__init__(description=description, response=response) + self.length = length + self.units = units + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + if self.length is not None: + headers.append(("Content-Range", f"{self.units} */{self.length}")) + return headers + + +class ExpectationFailed(HTTPException): + """*417* `Expectation Failed` + + The server cannot meet the requirements of the Expect request-header. + + .. versionadded:: 0.7 + """ + + code = 417 + description = "The server could not meet the requirements of the Expect header" + + +class ImATeapot(HTTPException): + """*418* `I'm a teapot` + + The server should return this if it is a teapot and someone attempted + to brew coffee with it. + + .. versionadded:: 0.7 + """ + + code = 418 + description = "This server is a teapot, not a coffee machine" + + +class UnprocessableEntity(HTTPException): + """*422* `Unprocessable Entity` + + Used if the request is well formed, but the instructions are otherwise + incorrect. + """ + + code = 422 + description = ( + "The request was well-formed but was unable to be followed due" + " to semantic errors." + ) + + +class Locked(HTTPException): + """*423* `Locked` + + Used if the resource that is being accessed is locked. + """ + + code = 423 + description = "The resource that is being accessed is locked." + + +class FailedDependency(HTTPException): + """*424* `Failed Dependency` + + Used if the method could not be performed on the resource + because the requested action depended on another action and that action failed. + """ + + code = 424 + description = ( + "The method could not be performed on the resource because the" + " requested action depended on another action and that action" + " failed." + ) + + +class PreconditionRequired(HTTPException): + """*428* `Precondition Required` + + The server requires this request to be conditional, typically to prevent + the lost update problem, which is a race condition between two or more + clients attempting to update a resource through PUT or DELETE. By requiring + each client to include a conditional header ("If-Match" or "If-Unmodified- + Since") with the proper value retained from a recent GET request, the + server ensures that each client has at least seen the previous revision of + the resource. + """ + + code = 428 + description = ( + "This request is required to be conditional; try using" + ' "If-Match" or "If-Unmodified-Since".' + ) + + +class _RetryAfter(HTTPException): + """Adds an optional ``retry_after`` parameter which will set the + ``Retry-After`` header. May be an :class:`int` number of seconds or + a :class:`~datetime.datetime`. + """ + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + retry_after: t.Optional[t.Union[datetime, int]] = None, + ) -> None: + super().__init__(description, response) + self.retry_after = retry_after + + def get_headers( + self, + environ: t.Optional["WSGIEnvironment"] = None, + scope: t.Optional[dict] = None, + ) -> t.List[t.Tuple[str, str]]: + headers = super().get_headers(environ, scope) + + if self.retry_after: + if isinstance(self.retry_after, datetime): + from .http import http_date + + value = http_date(self.retry_after) + else: + value = str(self.retry_after) + + headers.append(("Retry-After", value)) + + return headers + + +class TooManyRequests(_RetryAfter): + """*429* `Too Many Requests` + + The server is limiting the rate at which this user receives + responses, and this request exceeds that rate. (The server may use + any convenient method to identify users and their request rates). + The server may include a "Retry-After" header to indicate how long + the user should wait before retrying. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 429 + description = "This user has exceeded an allotted request count. Try again later." + + +class RequestHeaderFieldsTooLarge(HTTPException): + """*431* `Request Header Fields Too Large` + + The server refuses to process the request because the header fields are too + large. One or more individual fields may be too large, or the set of all + headers is too large. + """ + + code = 431 + description = "One or more header fields exceeds the maximum size." + + +class UnavailableForLegalReasons(HTTPException): + """*451* `Unavailable For Legal Reasons` + + This status code indicates that the server is denying access to the + resource as a consequence of a legal demand. + """ + + code = 451 + description = "Unavailable for legal reasons." + + +class InternalServerError(HTTPException): + """*500* `Internal Server Error` + + Raise if an internal server error occurred. This is a good fallback if an + unknown error occurred in the dispatcher. + + .. versionchanged:: 1.0.0 + Added the :attr:`original_exception` attribute. + """ + + code = 500 + description = ( + "The server encountered an internal error and was unable to" + " complete your request. Either the server is overloaded or" + " there is an error in the application." + ) + + def __init__( + self, + description: t.Optional[str] = None, + response: t.Optional["Response"] = None, + original_exception: t.Optional[BaseException] = None, + ) -> None: + #: The original exception that caused this 500 error. Can be + #: used by frameworks to provide context when handling + #: unexpected errors. + self.original_exception = original_exception + super().__init__(description=description, response=response) + + +class NotImplemented(HTTPException): + """*501* `Not Implemented` + + Raise if the application does not support the action requested by the + browser. + """ + + code = 501 + description = "The server does not support the action requested by the browser." + + +class BadGateway(HTTPException): + """*502* `Bad Gateway` + + If you do proxying in your application you should return this status code + if you received an invalid response from the upstream server it accessed + in attempting to fulfill the request. + """ + + code = 502 + description = ( + "The proxy server received an invalid response from an upstream server." + ) + + +class ServiceUnavailable(_RetryAfter): + """*503* `Service Unavailable` + + Status code you should return if a service is temporarily + unavailable. + + :param retry_after: If given, set the ``Retry-After`` header to this + value. May be an :class:`int` number of seconds or a + :class:`~datetime.datetime`. + + .. versionchanged:: 1.0 + Added ``retry_after`` parameter. + """ + + code = 503 + description = ( + "The server is temporarily unable to service your request due" + " to maintenance downtime or capacity problems. Please try" + " again later." + ) + + +class GatewayTimeout(HTTPException): + """*504* `Gateway Timeout` + + Status code you should return if a connection to an upstream server + times out. + """ + + code = 504 + description = "The connection to an upstream server timed out." + + +class HTTPVersionNotSupported(HTTPException): + """*505* `HTTP Version Not Supported` + + The server does not support the HTTP protocol version used in the request. + """ + + code = 505 + description = ( + "The server does not support the HTTP protocol version used in the request." + ) + + +default_exceptions: t.Dict[int, t.Type[HTTPException]] = {} + + +def _find_exceptions() -> None: + for obj in globals().values(): + try: + is_http_exception = issubclass(obj, HTTPException) + except TypeError: + is_http_exception = False + if not is_http_exception or obj.code is None: + continue + old_obj = default_exceptions.get(obj.code, None) + if old_obj is not None and issubclass(obj, old_obj): + continue + default_exceptions[obj.code] = obj + + +_find_exceptions() +del _find_exceptions + + +class Aborter: + """When passed a dict of code -> exception items it can be used as + callable that raises exceptions. If the first argument to the + callable is an integer it will be looked up in the mapping, if it's + a WSGI application it will be raised in a proxy exception. + + The rest of the arguments are forwarded to the exception constructor. + """ + + def __init__( + self, + mapping: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, + extra: t.Optional[t.Dict[int, t.Type[HTTPException]]] = None, + ) -> None: + if mapping is None: + mapping = default_exceptions + self.mapping = dict(mapping) + if extra is not None: + self.mapping.update(extra) + + def __call__( + self, code: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any + ) -> "te.NoReturn": + from .sansio.response import Response + + if isinstance(code, Response): + raise HTTPException(response=code) + + if code not in self.mapping: + raise LookupError(f"no exception for {code!r}") + + raise self.mapping[code](*args, **kwargs) + + +def abort( + status: t.Union[int, "Response"], *args: t.Any, **kwargs: t.Any +) -> "te.NoReturn": + """Raises an :py:exc:`HTTPException` for the given status code or WSGI + application. + + If a status code is given, it will be looked up in the list of + exceptions and will raise that exception. If passed a WSGI application, + it will wrap it in a proxy WSGI exception and raise that:: + + abort(404) # 404 Not Found + abort(Response('Hello World')) + + """ + _aborter(status, *args, **kwargs) + + +_aborter: Aborter = Aborter() diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/formparser.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/formparser.py new file mode 100644 index 00000000..bebb2fc8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/formparser.py @@ -0,0 +1,465 @@ +import typing as t +from functools import update_wrapper +from io import BytesIO +from itertools import chain +from typing import Union + +from . import exceptions +from .datastructures import FileStorage +from .datastructures import Headers +from .datastructures import MultiDict +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartDecoder +from .sansio.multipart import NeedData +from .urls import url_decode_stream +from .wsgi import _make_chunk_iter +from .wsgi import get_content_length +from .wsgi import get_input_stream + +# there are some platforms where SpooledTemporaryFile is not available. +# In that case we need to provide a fallback. +try: + from tempfile import SpooledTemporaryFile +except ImportError: + from tempfile import TemporaryFile + + SpooledTemporaryFile = None # type: ignore + +if t.TYPE_CHECKING: + import typing as te + from _typeshed.wsgi import WSGIEnvironment + + t_parse_result = t.Tuple[t.IO[bytes], MultiDict, MultiDict] + + class TStreamFactory(te.Protocol): + def __call__( + self, + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str], + content_length: t.Optional[int] = None, + ) -> t.IO[bytes]: + ... + + +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def _exhaust(stream: t.IO[bytes]) -> None: + bts = stream.read(64 * 1024) + while bts: + bts = stream.read(64 * 1024) + + +def default_stream_factory( + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str], + content_length: t.Optional[int] = None, +) -> t.IO[bytes]: + max_size = 1024 * 500 + + if SpooledTemporaryFile is not None: + return t.cast(t.IO[bytes], SpooledTemporaryFile(max_size=max_size, mode="rb+")) + elif total_content_length is None or total_content_length > max_size: + return t.cast(t.IO[bytes], TemporaryFile("rb+")) + + return BytesIO() + + +def parse_form_data( + environ: "WSGIEnvironment", + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + max_content_length: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + silent: bool = True, +) -> "t_parse_result": + """Parse the form data in the environ and return it as tuple in the form + ``(stream, form, files)``. You should only call this method if the + transport method is `POST`, `PUT`, or `PATCH`. + + If the mimetype of the data transmitted is `multipart/form-data` the + files multidict will be filled with `FileStorage` objects. If the + mimetype is unknown the input stream is wrapped and returned as first + argument, else the stream is empty. + + This is a shortcut for the common usage of :class:`FormDataParser`. + + Have a look at :doc:`/request_data` for more details. + + .. versionadded:: 0.5 + The `max_form_memory_size`, `max_content_length` and + `cls` parameters were added. + + .. versionadded:: 0.5.1 + The optional `silent` flag was added. + + :param environ: the WSGI environment to be used for parsing. + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :return: A tuple in the form ``(stream, form, files)``. + """ + return FormDataParser( + stream_factory, + charset, + errors, + max_form_memory_size, + max_content_length, + cls, + silent, + ).parse_from_environ(environ) + + +def exhaust_stream(f: F) -> F: + """Helper decorator for methods that exhausts the stream on return.""" + + def wrapper(self, stream, *args, **kwargs): # type: ignore + try: + return f(self, stream, *args, **kwargs) + finally: + exhaust = getattr(stream, "exhaust", None) + + if exhaust is not None: + exhaust() + else: + while True: + chunk = stream.read(1024 * 64) + + if not chunk: + break + + return update_wrapper(t.cast(F, wrapper), f) + + +class FormDataParser: + """This class implements parsing of form data for Werkzeug. By itself + it can parse multipart and url encoded form data. It can be subclassed + and extended but for most mimetypes it is a better idea to use the + untouched stream and expose it as separate attributes on a request + object. + + .. versionadded:: 0.8 + + :param stream_factory: An optional callable that returns a new read and + writeable file descriptor. This callable works + the same as :meth:`Response._get_file_stream`. + :param charset: The character set for URL and url encoded form data. + :param errors: The encoding error behavior. + :param max_form_memory_size: the maximum number of bytes to be accepted for + in-memory stored form data. If the data + exceeds the value specified an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param max_content_length: If this is provided and the transmitted data + is longer than this value an + :exc:`~exceptions.RequestEntityTooLarge` + exception is raised. + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param silent: If set to False parsing errors will not be caught. + :param max_form_parts: The maximum number of parts to be parsed. If this is + exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised. + """ + + def __init__( + self, + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + max_content_length: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + silent: bool = True, + *, + max_form_parts: t.Optional[int] = None, + ) -> None: + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + self.max_content_length = max_content_length + self.max_form_parts = max_form_parts + + if cls is None: + cls = MultiDict + + self.cls = cls + self.silent = silent + + def get_parse_func( + self, mimetype: str, options: t.Dict[str, str] + ) -> t.Optional[ + t.Callable[ + ["FormDataParser", t.IO[bytes], str, t.Optional[int], t.Dict[str, str]], + "t_parse_result", + ] + ]: + return self.parse_functions.get(mimetype) + + def parse_from_environ(self, environ: "WSGIEnvironment") -> "t_parse_result": + """Parses the information from the environment as form data. + + :param environ: the WSGI environment to be used for parsing. + :return: A tuple in the form ``(stream, form, files)``. + """ + content_type = environ.get("CONTENT_TYPE", "") + content_length = get_content_length(environ) + mimetype, options = parse_options_header(content_type) + return self.parse(get_input_stream(environ), mimetype, content_length, options) + + def parse( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Optional[t.Dict[str, str]] = None, + ) -> "t_parse_result": + """Parses the information from the given stream, mimetype, + content length and mimetype parameters. + + :param stream: an input stream + :param mimetype: the mimetype of the data + :param content_length: the content length of the incoming data + :param options: optional mimetype parameters (used for + the multipart boundary for instance) + :return: A tuple in the form ``(stream, form, files)``. + """ + if ( + self.max_content_length is not None + and content_length is not None + and content_length > self.max_content_length + ): + # if the input stream is not exhausted, firefox reports Connection Reset + _exhaust(stream) + raise exceptions.RequestEntityTooLarge() + + if options is None: + options = {} + + parse_func = self.get_parse_func(mimetype, options) + + if parse_func is not None: + try: + return parse_func(self, stream, mimetype, content_length, options) + except ValueError: + if not self.silent: + raise + + return stream, self.cls(), self.cls() + + @exhaust_stream + def _parse_multipart( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Dict[str, str], + ) -> "t_parse_result": + parser = MultiPartParser( + self.stream_factory, + self.charset, + self.errors, + max_form_memory_size=self.max_form_memory_size, + cls=self.cls, + max_form_parts=self.max_form_parts, + ) + boundary = options.get("boundary", "").encode("ascii") + + if not boundary: + raise ValueError("Missing boundary") + + form, files = parser.parse(stream, boundary, content_length) + return stream, form, files + + @exhaust_stream + def _parse_urlencoded( + self, + stream: t.IO[bytes], + mimetype: str, + content_length: t.Optional[int], + options: t.Dict[str, str], + ) -> "t_parse_result": + if ( + self.max_form_memory_size is not None + and content_length is not None + and content_length > self.max_form_memory_size + ): + # if the input stream is not exhausted, firefox reports Connection Reset + _exhaust(stream) + raise exceptions.RequestEntityTooLarge() + + form = url_decode_stream(stream, self.charset, errors=self.errors, cls=self.cls) + return stream, form, self.cls() + + #: mapping of mimetypes to parsing functions + parse_functions: t.Dict[ + str, + t.Callable[ + ["FormDataParser", t.IO[bytes], str, t.Optional[int], t.Dict[str, str]], + "t_parse_result", + ], + ] = { + "multipart/form-data": _parse_multipart, + "application/x-www-form-urlencoded": _parse_urlencoded, + "application/x-url-encoded": _parse_urlencoded, + } + + +def _line_parse(line: str) -> t.Tuple[str, bool]: + """Removes line ending characters and returns a tuple (`stripped_line`, + `is_terminated`). + """ + if line[-2:] == "\r\n": + return line[:-2], True + + elif line[-1:] in {"\r", "\n"}: + return line[:-1], True + + return line, False + + +class MultiPartParser: + def __init__( + self, + stream_factory: t.Optional["TStreamFactory"] = None, + charset: str = "utf-8", + errors: str = "replace", + max_form_memory_size: t.Optional[int] = None, + cls: t.Optional[t.Type[MultiDict]] = None, + buffer_size: int = 64 * 1024, + max_form_parts: t.Optional[int] = None, + ) -> None: + self.charset = charset + self.errors = errors + self.max_form_memory_size = max_form_memory_size + self.max_form_parts = max_form_parts + + if stream_factory is None: + stream_factory = default_stream_factory + + self.stream_factory = stream_factory + + if cls is None: + cls = MultiDict + + self.cls = cls + + self.buffer_size = buffer_size + + def fail(self, message: str) -> "te.NoReturn": + raise ValueError(message) + + def get_part_charset(self, headers: Headers) -> str: + # Figure out input charset for current part + content_type = headers.get("content-type") + + if content_type: + mimetype, ct_params = parse_options_header(content_type) + return ct_params.get("charset", self.charset) + + return self.charset + + def start_file_streaming( + self, event: File, total_content_length: t.Optional[int] + ) -> t.IO[bytes]: + content_type = event.headers.get("content-type") + + try: + content_length = int(event.headers["content-length"]) + except (KeyError, ValueError): + content_length = 0 + + container = self.stream_factory( + total_content_length=total_content_length, + filename=event.filename, + content_type=content_type, + content_length=content_length, + ) + return container + + def parse( + self, stream: t.IO[bytes], boundary: bytes, content_length: t.Optional[int] + ) -> t.Tuple[MultiDict, MultiDict]: + container: t.Union[t.IO[bytes], t.List[bytes]] + _write: t.Callable[[bytes], t.Any] + + iterator = chain( + _make_chunk_iter( + stream, + limit=content_length, + buffer_size=self.buffer_size, + ), + [None], + ) + + parser = MultipartDecoder( + boundary, self.max_form_memory_size, max_parts=self.max_form_parts + ) + + fields = [] + files = [] + + current_part: Union[Field, File] + for data in iterator: + parser.receive_data(data) + event = parser.next_event() + while not isinstance(event, (Epilogue, NeedData)): + if isinstance(event, Field): + current_part = event + container = [] + _write = container.append + elif isinstance(event, File): + current_part = event + container = self.start_file_streaming(event, content_length) + _write = container.write + elif isinstance(event, Data): + _write(event.data) + if not event.more_data: + if isinstance(current_part, Field): + value = b"".join(container).decode( + self.get_part_charset(current_part.headers), self.errors + ) + fields.append((current_part.name, value)) + else: + container = t.cast(t.IO[bytes], container) + container.seek(0) + files.append( + ( + current_part.name, + FileStorage( + container, + current_part.filename, + current_part.name, + headers=current_part.headers, + ), + ) + ) + + event = parser.next_event() + + return self.cls(fields), self.cls(files) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/http.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/http.py new file mode 100644 index 00000000..0a7bc739 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/http.py @@ -0,0 +1,1327 @@ +import base64 +import email.utils +import re +import typing +import typing as t +import warnings +from datetime import date +from datetime import datetime +from datetime import time +from datetime import timedelta +from datetime import timezone +from enum import Enum +from hashlib import sha1 +from time import mktime +from time import struct_time +from urllib.parse import unquote_to_bytes as _unquote +from urllib.request import parse_http_list as _parse_list_header + +from ._internal import _cookie_quote +from ._internal import _dt_as_utc +from ._internal import _make_cookie_domain +from ._internal import _to_bytes +from ._internal import _to_str +from ._internal import _wsgi_decoding_dance + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + +# for explanation of "media-range", etc. see Sections 5.3.{1,2} of RFC 7231 +_accept_re = re.compile( + r""" + ( # media-range capturing-parenthesis + [^\s;,]+ # type/subtype + (?:[ \t]*;[ \t]* # ";" + (?: # parameter non-capturing-parenthesis + [^\s;,q][^\s;,]* # token that doesn't start with "q" + | # or + q[^\s;,=][^\s;,]* # token that is more than just "q" + ) + )* # zero or more parameters + ) # end of media-range + (?:[ \t]*;[ \t]*q= # weight is a "q" parameter + (\d*(?:\.\d+)?) # qvalue capturing-parentheses + [^,]* # "extension" accept params: who cares? + )? # accept params are optional + """, + re.VERBOSE, +) +_token_chars = frozenset( + "!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~" +) +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') +_option_header_piece_re = re.compile( + r""" + ;\s*,?\s* # newlines were replaced with commas + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^\s;,=*]+ # token + ) + (?:\*(?P\d+))? # *1, optional continuation index + \s* + (?: # optionally followed by =value + (?: # equals sign, possibly with encoding + \*\s*=\s* # * indicates extended notation + (?: # optional encoding + (?P[^\s]+?) + '(?P[^\s]*?)' + )? + | + =\s* # basic notation + ) + (?P + "[^"\\]*(?:\\.[^"\\]*)*" # quoted string + | + [^;,]+ # token + )? + )? + \s* + """, + flags=re.VERBOSE, +) +_option_header_start_mime_type = re.compile(r",\s*([^;,\s]+)([;,]\s*.+)?") +_entity_headers = frozenset( + [ + "allow", + "content-encoding", + "content-language", + "content-length", + "content-location", + "content-md5", + "content-range", + "content-type", + "expires", + "last-modified", + ] +) +_hop_by_hop_headers = frozenset( + [ + "connection", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "transfer-encoding", + "upgrade", + ] +) +HTTP_STATUS_CODES = { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 103: "Early Hints", # see RFC 8297 + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi Status", + 208: "Already Reported", # see RFC 5842 + 226: "IM Used", # see RFC 3229 + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Switch Proxy", # unused + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", # unused + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 418: "I'm a teapot", # see RFC 2324 + 421: "Misdirected Request", # see RFC 7540 + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Too Early", # see RFC 8470 + 426: "Upgrade Required", + 428: "Precondition Required", # see RFC 6585 + 429: "Too Many Requests", + 431: "Request Header Fields Too Large", + 449: "Retry With", # proprietary MS extension + 451: "Unavailable For Legal Reasons", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates", # see RFC 2295 + 507: "Insufficient Storage", + 508: "Loop Detected", # see RFC 5842 + 510: "Not Extended", + 511: "Network Authentication Failed", +} + + +class COEP(Enum): + """Cross Origin Embedder Policies""" + + UNSAFE_NONE = "unsafe-none" + REQUIRE_CORP = "require-corp" + + +class COOP(Enum): + """Cross Origin Opener Policies""" + + UNSAFE_NONE = "unsafe-none" + SAME_ORIGIN_ALLOW_POPUPS = "same-origin-allow-popups" + SAME_ORIGIN = "same-origin" + + +def _is_extended_parameter(key: str) -> bool: + """Per RFC 5987/8187, "extended" values may *not* be quoted. + This is in keeping with browser implementations. So we test + using this function to see if the key indicates this parameter + follows the `ext-parameter` syntax (using a trailing '*'). + """ + return key.strip().endswith("*") + + +def quote_header_value( + value: t.Union[str, int], extra_chars: str = "", allow_token: bool = True +) -> str: + """Quote a header value if necessary. + + .. versionadded:: 0.5 + + :param value: the value to quote. + :param extra_chars: a list of extra characters to skip quoting. + :param allow_token: if this is enabled token values are returned + unchanged. + """ + if isinstance(value, bytes): + value = value.decode("latin1") + value = str(value) + if allow_token: + token_chars = _token_chars | set(extra_chars) + if set(value).issubset(token_chars): + return value + value = value.replace("\\", "\\\\").replace('"', '\\"') + return f'"{value}"' + + +def unquote_header_value(value: str, is_filename: bool = False) -> str: + r"""Unquotes a header value. (Reversal of :func:`quote_header_value`). + This does not use the real unquoting but what browsers are actually + using for quoting. + + .. versionadded:: 0.5 + + :param value: the header value to unquote. + :param is_filename: The value represents a filename or path. + """ + if value and value[0] == value[-1] == '"': + # this is not the real unquoting, but fixing this so that the + # RFC is met will result in bugs with internet explorer and + # probably some other browsers as well. IE for example is + # uploading files with "C:\foo\bar.txt" as filename + value = value[1:-1] + + # if this is a filename and the starting characters look like + # a UNC path, then just return the value without quotes. Using the + # replace sequence below on a UNC path has the effect of turning + # the leading double slash into a single slash and then + # _fix_ie_filename() doesn't work correctly. See #458. + if not is_filename or value[:2] != "\\\\": + return value.replace("\\\\", "\\").replace('\\"', '"') + return value + + +def dump_options_header( + header: t.Optional[str], options: t.Mapping[str, t.Optional[t.Union[str, int]]] +) -> str: + """The reverse function to :func:`parse_options_header`. + + :param header: the header to dump + :param options: a dict of options to append. + """ + segments = [] + if header is not None: + segments.append(header) + for key, value in options.items(): + if value is None: + segments.append(key) + elif _is_extended_parameter(key): + segments.append(f"{key}={value}") + else: + segments.append(f"{key}={quote_header_value(value)}") + return "; ".join(segments) + + +def dump_header( + iterable: t.Union[t.Dict[str, t.Union[str, int]], t.Iterable[str]], + allow_token: bool = True, +) -> str: + """Dump an HTTP header again. This is the reversal of + :func:`parse_list_header`, :func:`parse_set_header` and + :func:`parse_dict_header`. This also quotes strings that include an + equals sign unless you pass it as dict of key, value pairs. + + >>> dump_header({'foo': 'bar baz'}) + 'foo="bar baz"' + >>> dump_header(('foo', 'bar baz')) + 'foo, "bar baz"' + + :param iterable: the iterable or dict of values to quote. + :param allow_token: if set to `False` tokens as values are disallowed. + See :func:`quote_header_value` for more details. + """ + if isinstance(iterable, dict): + items = [] + for key, value in iterable.items(): + if value is None: + items.append(key) + elif _is_extended_parameter(key): + items.append(f"{key}={value}") + else: + items.append( + f"{key}={quote_header_value(value, allow_token=allow_token)}" + ) + else: + items = [quote_header_value(x, allow_token=allow_token) for x in iterable] + return ", ".join(items) + + +def dump_csp_header(header: "ds.ContentSecurityPolicy") -> str: + """Dump a Content Security Policy header. + + These are structured into policies such as "default-src 'self'; + script-src 'self'". + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + """ + return "; ".join(f"{key} {value}" for key, value in header.items()) + + +def parse_list_header(value: str) -> t.List[str]: + """Parse lists as described by RFC 2068 Section 2. + + In particular, parse comma-separated lists where the elements of + the list may include quoted-strings. A quoted-string could + contain a comma. A non-quoted string could have quotes in the + middle. Quotes are removed automatically after parsing. + + It basically works like :func:`parse_set_header` just that items + may appear multiple times and case sensitivity is preserved. + + The return value is a standard :class:`list`: + + >>> parse_list_header('token, "quoted value"') + ['token', 'quoted value'] + + To create a header from the :class:`list` again, use the + :func:`dump_header` function. + + :param value: a string with a list header. + :return: :class:`list` + """ + result = [] + for item in _parse_list_header(value): + if item[:1] == item[-1:] == '"': + item = unquote_header_value(item[1:-1]) + result.append(item) + return result + + +def parse_dict_header(value: str, cls: t.Type[dict] = dict) -> t.Dict[str, str]: + """Parse lists of key, value pairs as described by RFC 2068 Section 2 and + convert them into a python dict (or any other mapping object created from + the type with a dict like interface provided by the `cls` argument): + + >>> d = parse_dict_header('foo="is a fish", bar="as well"') + >>> type(d) is dict + True + >>> sorted(d.items()) + [('bar', 'as well'), ('foo', 'is a fish')] + + If there is no value for a key it will be `None`: + + >>> parse_dict_header('key_without_value') + {'key_without_value': None} + + To create a header from the :class:`dict` again, use the + :func:`dump_header` function. + + .. versionchanged:: 0.9 + Added support for `cls` argument. + + :param value: a string with a dict header. + :param cls: callable to use for storage of parsed results. + :return: an instance of `cls` + """ + result = cls() + if isinstance(value, bytes): + value = value.decode("latin1") + for item in _parse_list_header(value): + if "=" not in item: + result[item] = None + continue + name, value = item.split("=", 1) + if value[:1] == value[-1:] == '"': + value = unquote_header_value(value[1:-1]) + result[name] = value + return result + + +def parse_options_header(value: t.Optional[str]) -> t.Tuple[str, t.Dict[str, str]]: + """Parse a ``Content-Type``-like header into a tuple with the + value and any options: + + >>> parse_options_header('text/html; charset=utf8') + ('text/html', {'charset': 'utf8'}) + + This should is not for ``Cache-Control``-like headers, which use a + different format. For those, use :func:`parse_dict_header`. + + :param value: The header value to parse. + + .. versionchanged:: 2.2 + Option names are always converted to lowercase. + + .. versionchanged:: 2.1 + The ``multiple`` parameter is deprecated and will be removed in + Werkzeug 2.2. + + .. versionchanged:: 0.15 + :rfc:`2231` parameter continuations are handled. + + .. versionadded:: 0.5 + """ + if not value: + return "", {} + + result: t.List[t.Any] = [] + + value = "," + value.replace("\n", ",") + while value: + match = _option_header_start_mime_type.match(value) + if not match: + break + result.append(match.group(1)) # mimetype + options: t.Dict[str, str] = {} + # Parse options + rest = match.group(2) + encoding: t.Optional[str] + continued_encoding: t.Optional[str] = None + while rest: + optmatch = _option_header_piece_re.match(rest) + if not optmatch: + break + option, count, encoding, language, option_value = optmatch.groups() + # Continuations don't have to supply the encoding after the + # first line. If we're in a continuation, track the current + # encoding to use for subsequent lines. Reset it when the + # continuation ends. + if not count: + continued_encoding = None + else: + if not encoding: + encoding = continued_encoding + continued_encoding = encoding + option = unquote_header_value(option).lower() + + if option_value is not None: + option_value = unquote_header_value(option_value, option == "filename") + + if encoding is not None: + option_value = _unquote(option_value).decode(encoding) + + if count: + # Continuations append to the existing value. For + # simplicity, this ignores the possibility of + # out-of-order indices, which shouldn't happen anyway. + if option_value is not None: + options[option] = options.get(option, "") + option_value + else: + options[option] = option_value # type: ignore[assignment] + + rest = rest[optmatch.end() :] + result.append(options) + return tuple(result) # type: ignore[return-value] + + return tuple(result) if result else ("", {}) # type: ignore[return-value] + + +_TAnyAccept = t.TypeVar("_TAnyAccept", bound="ds.Accept") + + +@typing.overload +def parse_accept_header(value: t.Optional[str]) -> "ds.Accept": + ... + + +@typing.overload +def parse_accept_header( + value: t.Optional[str], cls: t.Type[_TAnyAccept] +) -> _TAnyAccept: + ... + + +def parse_accept_header( + value: t.Optional[str], cls: t.Optional[t.Type[_TAnyAccept]] = None +) -> _TAnyAccept: + """Parses an HTTP Accept-* header. This does not implement a complete + valid algorithm but one that supports at least value and quality + extraction. + + Returns a new :class:`Accept` object (basically a list of ``(value, quality)`` + tuples sorted by the quality with some additional accessor methods). + + The second parameter can be a subclass of :class:`Accept` that is created + with the parsed values and returned. + + :param value: the accept header string to be parsed. + :param cls: the wrapper class for the return value (can be + :class:`Accept` or a subclass thereof) + :return: an instance of `cls`. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyAccept], ds.Accept) + + if not value: + return cls(None) + + result = [] + for match in _accept_re.finditer(value): + quality_match = match.group(2) + if not quality_match: + quality: float = 1 + else: + quality = max(min(float(quality_match), 1), 0) + result.append((match.group(1), quality)) + return cls(result) + + +_TAnyCC = t.TypeVar("_TAnyCC", bound="ds._CacheControl") +_t_cc_update = t.Optional[t.Callable[[_TAnyCC], None]] + + +@typing.overload +def parse_cache_control_header( + value: t.Optional[str], on_update: _t_cc_update, cls: None = None +) -> "ds.RequestCacheControl": + ... + + +@typing.overload +def parse_cache_control_header( + value: t.Optional[str], on_update: _t_cc_update, cls: t.Type[_TAnyCC] +) -> _TAnyCC: + ... + + +def parse_cache_control_header( + value: t.Optional[str], + on_update: _t_cc_update = None, + cls: t.Optional[t.Type[_TAnyCC]] = None, +) -> _TAnyCC: + """Parse a cache control header. The RFC differs between response and + request cache control, this method does not. It's your responsibility + to not use the wrong control statements. + + .. versionadded:: 0.5 + The `cls` was added. If not specified an immutable + :class:`~werkzeug.datastructures.RequestCacheControl` is returned. + + :param value: a cache control header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.CacheControl` + object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.RequestCacheControl` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyCC], ds.RequestCacheControl) + + if not value: + return cls((), on_update) + + return cls(parse_dict_header(value), on_update) + + +_TAnyCSP = t.TypeVar("_TAnyCSP", bound="ds.ContentSecurityPolicy") +_t_csp_update = t.Optional[t.Callable[[_TAnyCSP], None]] + + +@typing.overload +def parse_csp_header( + value: t.Optional[str], on_update: _t_csp_update, cls: None = None +) -> "ds.ContentSecurityPolicy": + ... + + +@typing.overload +def parse_csp_header( + value: t.Optional[str], on_update: _t_csp_update, cls: t.Type[_TAnyCSP] +) -> _TAnyCSP: + ... + + +def parse_csp_header( + value: t.Optional[str], + on_update: _t_csp_update = None, + cls: t.Optional[t.Type[_TAnyCSP]] = None, +) -> _TAnyCSP: + """Parse a Content Security Policy header. + + .. versionadded:: 1.0.0 + Support for Content Security Policy headers was added. + + :param value: a csp header to be parsed. + :param on_update: an optional callable that is called every time a value + on the object is changed. + :param cls: the class for the returned object. By default + :class:`~werkzeug.datastructures.ContentSecurityPolicy` is used. + :return: a `cls` object. + """ + if cls is None: + cls = t.cast(t.Type[_TAnyCSP], ds.ContentSecurityPolicy) + + if value is None: + return cls((), on_update) + + items = [] + + for policy in value.split(";"): + policy = policy.strip() + + # Ignore badly formatted policies (no space) + if " " in policy: + directive, value = policy.strip().split(" ", 1) + items.append((directive.strip(), value.strip())) + + return cls(items, on_update) + + +def parse_set_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.HeaderSet"], None]] = None, +) -> "ds.HeaderSet": + """Parse a set-like header and return a + :class:`~werkzeug.datastructures.HeaderSet` object: + + >>> hs = parse_set_header('token, "quoted value"') + + The return value is an object that treats the items case-insensitively + and keeps the order of the items: + + >>> 'TOKEN' in hs + True + >>> hs.index('quoted value') + 1 + >>> hs + HeaderSet(['token', 'quoted value']) + + To create a header from the :class:`HeaderSet` again, use the + :func:`dump_header` function. + + :param value: a set header to be parsed. + :param on_update: an optional callable that is called every time a + value on the :class:`~werkzeug.datastructures.HeaderSet` + object is changed. + :return: a :class:`~werkzeug.datastructures.HeaderSet` + """ + if not value: + return ds.HeaderSet(None, on_update) + return ds.HeaderSet(parse_list_header(value), on_update) + + +def parse_authorization_header( + value: t.Optional[str], +) -> t.Optional["ds.Authorization"]: + """Parse an HTTP basic/digest authorization header transmitted by the web + browser. The return value is either `None` if the header was invalid or + not given, otherwise an :class:`~werkzeug.datastructures.Authorization` + object. + + :param value: the authorization header to parse. + :return: a :class:`~werkzeug.datastructures.Authorization` object or `None`. + """ + if not value: + return None + value = _wsgi_decoding_dance(value) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except ValueError: + return None + if auth_type == "basic": + try: + username, password = base64.b64decode(auth_info).split(b":", 1) + except Exception: + return None + try: + return ds.Authorization( + "basic", + { + "username": _to_str(username, "utf-8"), + "password": _to_str(password, "utf-8"), + }, + ) + except UnicodeDecodeError: + return None + elif auth_type == "digest": + auth_map = parse_dict_header(auth_info) + for key in "username", "realm", "nonce", "uri", "response": + if key not in auth_map: + return None + if "qop" in auth_map: + if not auth_map.get("nc") or not auth_map.get("cnonce"): + return None + return ds.Authorization("digest", auth_map) + return None + + +def parse_www_authenticate_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.WWWAuthenticate"], None]] = None, +) -> "ds.WWWAuthenticate": + """Parse an HTTP WWW-Authenticate header into a + :class:`~werkzeug.datastructures.WWWAuthenticate` object. + + :param value: a WWW-Authenticate header to parse. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.WWWAuthenticate` + object is changed. + :return: a :class:`~werkzeug.datastructures.WWWAuthenticate` object. + """ + if not value: + return ds.WWWAuthenticate(on_update=on_update) + try: + auth_type, auth_info = value.split(None, 1) + auth_type = auth_type.lower() + except (ValueError, AttributeError): + return ds.WWWAuthenticate(value.strip().lower(), on_update=on_update) + return ds.WWWAuthenticate(auth_type, parse_dict_header(auth_info), on_update) + + +def parse_if_range_header(value: t.Optional[str]) -> "ds.IfRange": + """Parses an if-range header which can be an etag or a date. Returns + a :class:`~werkzeug.datastructures.IfRange` object. + + .. versionchanged:: 2.0 + If the value represents a datetime, it is timezone-aware. + + .. versionadded:: 0.7 + """ + if not value: + return ds.IfRange() + date = parse_date(value) + if date is not None: + return ds.IfRange(date=date) + # drop weakness information + return ds.IfRange(unquote_etag(value)[0]) + + +def parse_range_header( + value: t.Optional[str], make_inclusive: bool = True +) -> t.Optional["ds.Range"]: + """Parses a range header into a :class:`~werkzeug.datastructures.Range` + object. If the header is missing or malformed `None` is returned. + `ranges` is a list of ``(start, stop)`` tuples where the ranges are + non-inclusive. + + .. versionadded:: 0.7 + """ + if not value or "=" not in value: + return None + + ranges = [] + last_end = 0 + units, rng = value.split("=", 1) + units = units.strip().lower() + + for item in rng.split(","): + item = item.strip() + if "-" not in item: + return None + if item.startswith("-"): + if last_end < 0: + return None + try: + begin = int(item) + except ValueError: + return None + end = None + last_end = -1 + elif "-" in item: + begin_str, end_str = item.split("-", 1) + begin_str = begin_str.strip() + end_str = end_str.strip() + + try: + begin = int(begin_str) + except ValueError: + return None + + if begin < last_end or last_end < 0: + return None + if end_str: + try: + end = int(end_str) + 1 + except ValueError: + return None + + if begin >= end: + return None + else: + end = None + last_end = end if end is not None else -1 + ranges.append((begin, end)) + + return ds.Range(units, ranges) + + +def parse_content_range_header( + value: t.Optional[str], + on_update: t.Optional[t.Callable[["ds.ContentRange"], None]] = None, +) -> t.Optional["ds.ContentRange"]: + """Parses a range header into a + :class:`~werkzeug.datastructures.ContentRange` object or `None` if + parsing is not possible. + + .. versionadded:: 0.7 + + :param value: a content range header to be parsed. + :param on_update: an optional callable that is called every time a value + on the :class:`~werkzeug.datastructures.ContentRange` + object is changed. + """ + if value is None: + return None + try: + units, rangedef = (value or "").strip().split(None, 1) + except ValueError: + return None + + if "/" not in rangedef: + return None + rng, length_str = rangedef.split("/", 1) + if length_str == "*": + length = None + else: + try: + length = int(length_str) + except ValueError: + return None + + if rng == "*": + if not is_byte_range_valid(None, None, length): + return None + + return ds.ContentRange(units, None, None, length, on_update=on_update) + elif "-" not in rng: + return None + + start_str, stop_str = rng.split("-", 1) + try: + start = int(start_str) + stop = int(stop_str) + 1 + except ValueError: + return None + + if is_byte_range_valid(start, stop, length): + return ds.ContentRange(units, start, stop, length, on_update=on_update) + + return None + + +def quote_etag(etag: str, weak: bool = False) -> str: + """Quote an etag. + + :param etag: the etag to quote. + :param weak: set to `True` to tag it "weak". + """ + if '"' in etag: + raise ValueError("invalid etag") + etag = f'"{etag}"' + if weak: + etag = f"W/{etag}" + return etag + + +def unquote_etag( + etag: t.Optional[str], +) -> t.Union[t.Tuple[str, bool], t.Tuple[None, None]]: + """Unquote a single etag: + + >>> unquote_etag('W/"bar"') + ('bar', True) + >>> unquote_etag('"bar"') + ('bar', False) + + :param etag: the etag identifier to unquote. + :return: a ``(etag, weak)`` tuple. + """ + if not etag: + return None, None + etag = etag.strip() + weak = False + if etag.startswith(("W/", "w/")): + weak = True + etag = etag[2:] + if etag[:1] == etag[-1:] == '"': + etag = etag[1:-1] + return etag, weak + + +def parse_etags(value: t.Optional[str]) -> "ds.ETags": + """Parse an etag header. + + :param value: the tag header to parse + :return: an :class:`~werkzeug.datastructures.ETags` object. + """ + if not value: + return ds.ETags() + strong = [] + weak = [] + end = len(value) + pos = 0 + while pos < end: + match = _etag_re.match(value, pos) + if match is None: + break + is_weak, quoted, raw = match.groups() + if raw == "*": + return ds.ETags(star_tag=True) + elif quoted: + raw = quoted + if is_weak: + weak.append(raw) + else: + strong.append(raw) + pos = match.end() + return ds.ETags(strong, weak) + + +def generate_etag(data: bytes) -> str: + """Generate an etag for some data. + + .. versionchanged:: 2.0 + Use SHA-1. MD5 may not be available in some environments. + """ + return sha1(data).hexdigest() + + +def parse_date(value: t.Optional[str]) -> t.Optional[datetime]: + """Parse an :rfc:`2822` date into a timezone-aware + :class:`datetime.datetime` object, or ``None`` if parsing fails. + + This is a wrapper for :func:`email.utils.parsedate_to_datetime`. It + returns ``None`` if parsing fails instead of raising an exception, + and always returns a timezone-aware datetime object. If the string + doesn't have timezone information, it is assumed to be UTC. + + :param value: A string with a supported date format. + + .. versionchanged:: 2.0 + Return a timezone-aware datetime object. Use + ``email.utils.parsedate_to_datetime``. + """ + if value is None: + return None + + try: + dt = email.utils.parsedate_to_datetime(value) + except (TypeError, ValueError): + return None + + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + + return dt + + +def http_date( + timestamp: t.Optional[t.Union[datetime, date, int, float, struct_time]] = None +) -> str: + """Format a datetime object or timestamp into an :rfc:`2822` date + string. + + This is a wrapper for :func:`email.utils.format_datetime`. It + assumes naive datetime objects are in UTC instead of raising an + exception. + + :param timestamp: The datetime or timestamp to format. Defaults to + the current time. + + .. versionchanged:: 2.0 + Use ``email.utils.format_datetime``. Accept ``date`` objects. + """ + if isinstance(timestamp, date): + if not isinstance(timestamp, datetime): + # Assume plain date is midnight UTC. + timestamp = datetime.combine(timestamp, time(), tzinfo=timezone.utc) + else: + # Ensure datetime is timezone-aware. + timestamp = _dt_as_utc(timestamp) + + return email.utils.format_datetime(timestamp, usegmt=True) + + if isinstance(timestamp, struct_time): + timestamp = mktime(timestamp) + + return email.utils.formatdate(timestamp, usegmt=True) + + +def parse_age(value: t.Optional[str] = None) -> t.Optional[timedelta]: + """Parses a base-10 integer count of seconds into a timedelta. + + If parsing fails, the return value is `None`. + + :param value: a string consisting of an integer represented in base-10 + :return: a :class:`datetime.timedelta` object or `None`. + """ + if not value: + return None + try: + seconds = int(value) + except ValueError: + return None + if seconds < 0: + return None + try: + return timedelta(seconds=seconds) + except OverflowError: + return None + + +def dump_age(age: t.Optional[t.Union[timedelta, int]] = None) -> t.Optional[str]: + """Formats the duration as a base-10 integer. + + :param age: should be an integer number of seconds, + a :class:`datetime.timedelta` object, or, + if the age is unknown, `None` (default). + """ + if age is None: + return None + if isinstance(age, timedelta): + age = int(age.total_seconds()) + else: + age = int(age) + + if age < 0: + raise ValueError("age cannot be negative") + + return str(age) + + +def is_resource_modified( + environ: "WSGIEnvironment", + etag: t.Optional[str] = None, + data: t.Optional[bytes] = None, + last_modified: t.Optional[t.Union[datetime, str]] = None, + ignore_if_range: bool = True, +) -> bool: + """Convenience method for conditional requests. + + :param environ: the WSGI environment of the request to be checked. + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + + .. versionchanged:: 2.0 + SHA-1 is used to generate an etag value for the data. MD5 may + not be available in some environments. + + .. versionchanged:: 1.0.0 + The check is run for methods other than ``GET`` and ``HEAD``. + """ + return _sansio_http.is_resource_modified( + http_range=environ.get("HTTP_RANGE"), + http_if_range=environ.get("HTTP_IF_RANGE"), + http_if_modified_since=environ.get("HTTP_IF_MODIFIED_SINCE"), + http_if_none_match=environ.get("HTTP_IF_NONE_MATCH"), + http_if_match=environ.get("HTTP_IF_MATCH"), + etag=etag, + data=data, + last_modified=last_modified, + ignore_if_range=ignore_if_range, + ) + + +def remove_entity_headers( + headers: t.Union["ds.Headers", t.List[t.Tuple[str, str]]], + allowed: t.Iterable[str] = ("expires", "content-location"), +) -> None: + """Remove all entity headers from a list or :class:`Headers` object. This + operation works in-place. `Expires` and `Content-Location` headers are + by default not removed. The reason for this is :rfc:`2616` section + 10.3.5 which specifies some entity headers that should be sent. + + .. versionchanged:: 0.5 + added `allowed` parameter. + + :param headers: a list or :class:`Headers` object. + :param allowed: a list of headers that should still be allowed even though + they are entity headers. + """ + allowed = {x.lower() for x in allowed} + headers[:] = [ + (key, value) + for key, value in headers + if not is_entity_header(key) or key.lower() in allowed + ] + + +def remove_hop_by_hop_headers( + headers: t.Union["ds.Headers", t.List[t.Tuple[str, str]]] +) -> None: + """Remove all HTTP/1.1 "Hop-by-Hop" headers from a list or + :class:`Headers` object. This operation works in-place. + + .. versionadded:: 0.5 + + :param headers: a list or :class:`Headers` object. + """ + headers[:] = [ + (key, value) for key, value in headers if not is_hop_by_hop_header(key) + ] + + +def is_entity_header(header: str) -> bool: + """Check if a header is an entity header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an entity header, `False` otherwise. + """ + return header.lower() in _entity_headers + + +def is_hop_by_hop_header(header: str) -> bool: + """Check if a header is an HTTP/1.1 "Hop-by-Hop" header. + + .. versionadded:: 0.5 + + :param header: the header to test. + :return: `True` if it's an HTTP/1.1 "Hop-by-Hop" header, `False` otherwise. + """ + return header.lower() in _hop_by_hop_headers + + +def parse_cookie( + header: t.Union["WSGIEnvironment", str, bytes, None], + charset: str = "utf-8", + errors: str = "replace", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, +) -> "ds.MultiDict[str, str]": + """Parse a cookie from a string or WSGI environ. + + The same key can be provided multiple times, the values are stored + in-order. The default :class:`MultiDict` will have the first value + first, and all values can be retrieved with + :meth:`MultiDict.getlist`. + + :param header: The cookie header as a string, or a WSGI environ dict + with a ``HTTP_COOKIE`` key. + :param charset: The charset for the cookie values. + :param errors: The error behavior for the charset decoding. + :param cls: A dict-like class to store the parsed cookies in. + Defaults to :class:`MultiDict`. + + .. versionchanged:: 1.0.0 + Returns a :class:`MultiDict` instead of a + ``TypeConversionDict``. + + .. versionchanged:: 0.5 + Returns a :class:`TypeConversionDict` instead of a regular dict. + The ``cls`` parameter was added. + """ + if isinstance(header, dict): + cookie = header.get("HTTP_COOKIE", "") + elif header is None: + cookie = "" + else: + cookie = header + + return _sansio_http.parse_cookie( + cookie=cookie, charset=charset, errors=errors, cls=cls + ) + + +def dump_cookie( + key: str, + value: t.Union[bytes, str] = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: t.Optional[str] = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + charset: str = "utf-8", + sync_expires: bool = True, + max_size: int = 4093, + samesite: t.Optional[str] = None, +) -> str: + """Create a Set-Cookie header without the ``Set-Cookie`` prefix. + + The return value is usually restricted to ascii as the vast majority + of values are properly escaped, but that is no guarantee. It's + tunneled through latin1 as required by :pep:`3333`. + + The return value is not ASCII safe if the key contains unicode + characters. This is technically against the specification but + happens in the wild. It's strongly recommended to not use + non-ASCII values for the keys. + + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. Additionally `timedelta` objects + are accepted, too. + :param expires: should be a `datetime` object or unix timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: Use this if you want to set a cross-domain cookie. For + example, ``domain=".example.com"`` will set a cookie + that is readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: The cookie will only be available via HTTPS + :param httponly: disallow JavaScript to access the cookie. This is an + extension to the cookie standard and probably not + supported by all browsers. + :param charset: the encoding for string values. + :param sync_expires: automatically set expires if max_age is defined + but expires not. + :param max_size: Warn if the final header value exceeds this size. The + default, 4093, should be safely `supported by most browsers + `_. Set to 0 to disable this check. + :param samesite: Limits the scope of the cookie such that it will + only be attached to requests if those requests are same-site. + + .. _`cookie`: http://browsercookielimits.squawky.net/ + + .. versionchanged:: 1.0.0 + The string ``'None'`` is accepted for ``samesite``. + """ + key = _to_bytes(key, charset) + value = _to_bytes(value, charset) + + if path is not None: + from .urls import iri_to_uri + + path = iri_to_uri(path, charset) + + domain = _make_cookie_domain(domain) + + if isinstance(max_age, timedelta): + max_age = int(max_age.total_seconds()) + + if expires is not None: + if not isinstance(expires, str): + expires = http_date(expires) + elif max_age is not None and sync_expires: + expires = http_date(datetime.now(tz=timezone.utc).timestamp() + max_age) + + if samesite is not None: + samesite = samesite.title() + + if samesite not in {"Strict", "Lax", "None"}: + raise ValueError("SameSite must be 'Strict', 'Lax', or 'None'.") + + buf = [key + b"=" + _cookie_quote(value)] + + # XXX: In theory all of these parameters that are not marked with `None` + # should be quoted. Because stdlib did not quote it before I did not + # want to introduce quoting there now. + for k, v, q in ( + (b"Domain", domain, True), + (b"Expires", expires, False), + (b"Max-Age", max_age, False), + (b"Secure", secure, None), + (b"HttpOnly", httponly, None), + (b"Path", path, False), + (b"SameSite", samesite, False), + ): + if q is None: + if v: + buf.append(k) + continue + + if v is None: + continue + + tmp = bytearray(k) + if not isinstance(v, (bytes, bytearray)): + v = _to_bytes(str(v), charset) + if q: + v = _cookie_quote(v) + tmp += b"=" + v + buf.append(bytes(tmp)) + + # The return value will be an incorrectly encoded latin1 header for + # consistency with the headers object. + rv = b"; ".join(buf) + rv = rv.decode("latin1") + + # Warn if the final value of the cookie is larger than the limit. If the + # cookie is too large, then it may be silently ignored by the browser, + # which can be quite hard to debug. + cookie_size = len(rv) + + if max_size and cookie_size > max_size: + value_size = len(value) + warnings.warn( + f"The {key.decode(charset)!r} cookie is too large: the value was" + f" {value_size} bytes but the" + f" header required {cookie_size - value_size} extra bytes. The final size" + f" was {cookie_size} bytes but the limit is {max_size} bytes. Browsers may" + f" silently ignore cookies larger than this.", + stacklevel=2, + ) + + return rv + + +def is_byte_range_valid( + start: t.Optional[int], stop: t.Optional[int], length: t.Optional[int] +) -> bool: + """Checks if a given byte content range is valid for the given length. + + .. versionadded:: 0.7 + """ + if (start is None) != (stop is None): + return False + elif start is None: + return length is None or length >= 0 + elif length is None: + return 0 <= start < stop # type: ignore + elif start >= stop: # type: ignore + return False + return 0 <= start < length + + +# circular dependencies +from . import datastructures as ds +from .sansio import http as _sansio_http diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/local.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/local.py new file mode 100644 index 00000000..9927a0a1 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/local.py @@ -0,0 +1,648 @@ +import copy +import math +import operator +import typing as t +from contextvars import ContextVar +from functools import partial +from functools import update_wrapper +from operator import attrgetter + +from .wsgi import ClosingIterator + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + +T = t.TypeVar("T") +F = t.TypeVar("F", bound=t.Callable[..., t.Any]) + + +def release_local(local: t.Union["Local", "LocalStack"]) -> None: + """Release the data for the current context in a :class:`Local` or + :class:`LocalStack` without using a :class:`LocalManager`. + + This should not be needed for modern use cases, and may be removed + in the future. + + .. versionadded:: 0.6.1 + """ + local.__release_local__() + + +class Local: + """Create a namespace of context-local data. This wraps a + :class:`ContextVar` containing a :class:`dict` value. + + This may incur a performance penalty compared to using individual + context vars, as it has to copy data to avoid mutating the dict + between nested contexts. + + :param context_var: The :class:`~contextvars.ContextVar` to use as + storage for this local. If not given, one will be created. + Context vars not created at the global scope may interfere with + garbage collection. + + .. versionchanged:: 2.0 + Uses ``ContextVar`` instead of a custom storage implementation. + """ + + __slots__ = ("__storage",) + + def __init__( + self, context_var: t.Optional[ContextVar[t.Dict[str, t.Any]]] = None + ) -> None: + if context_var is None: + # A ContextVar not created at global scope interferes with + # Python's garbage collection. However, a local only makes + # sense defined at the global scope as well, in which case + # the GC issue doesn't seem relevant. + context_var = ContextVar(f"werkzeug.Local<{id(self)}>.storage") + + object.__setattr__(self, "_Local__storage", context_var) + + def __iter__(self) -> t.Iterator[t.Tuple[str, t.Any]]: + return iter(self.__storage.get({}).items()) + + def __call__( + self, name: str, *, unbound_message: t.Optional[str] = None + ) -> "LocalProxy": + """Create a :class:`LocalProxy` that access an attribute on this + local namespace. + + :param name: Proxy this attribute. + :param unbound_message: The error message that the proxy will + show if the attribute isn't set. + """ + return LocalProxy(self, name, unbound_message=unbound_message) + + def __release_local__(self) -> None: + self.__storage.set({}) + + def __getattr__(self, name: str) -> t.Any: + values = self.__storage.get({}) + + if name in values: + return values[name] + + raise AttributeError(name) + + def __setattr__(self, name: str, value: t.Any) -> None: + values = self.__storage.get({}).copy() + values[name] = value + self.__storage.set(values) + + def __delattr__(self, name: str) -> None: + values = self.__storage.get({}) + + if name in values: + values = values.copy() + del values[name] + self.__storage.set(values) + else: + raise AttributeError(name) + + +class LocalStack(t.Generic[T]): + """Create a stack of context-local data. This wraps a + :class:`ContextVar` containing a :class:`list` value. + + This may incur a performance penalty compared to using individual + context vars, as it has to copy data to avoid mutating the list + between nested contexts. + + :param context_var: The :class:`~contextvars.ContextVar` to use as + storage for this local. If not given, one will be created. + Context vars not created at the global scope may interfere with + garbage collection. + + .. versionchanged:: 2.0 + Uses ``ContextVar`` instead of a custom storage implementation. + + .. versionadded:: 0.6.1 + """ + + __slots__ = ("_storage",) + + def __init__(self, context_var: t.Optional[ContextVar[t.List[T]]] = None) -> None: + if context_var is None: + # A ContextVar not created at global scope interferes with + # Python's garbage collection. However, a local only makes + # sense defined at the global scope as well, in which case + # the GC issue doesn't seem relevant. + context_var = ContextVar(f"werkzeug.LocalStack<{id(self)}>.storage") + + self._storage = context_var + + def __release_local__(self) -> None: + self._storage.set([]) + + def push(self, obj: T) -> t.List[T]: + """Add a new item to the top of the stack.""" + stack = self._storage.get([]).copy() + stack.append(obj) + self._storage.set(stack) + return stack + + def pop(self) -> t.Optional[T]: + """Remove the top item from the stack and return it. If the + stack is empty, return ``None``. + """ + stack = self._storage.get([]) + + if len(stack) == 0: + return None + + rv = stack[-1] + self._storage.set(stack[:-1]) + return rv + + @property + def top(self) -> t.Optional[T]: + """The topmost item on the stack. If the stack is empty, + `None` is returned. + """ + stack = self._storage.get([]) + + if len(stack) == 0: + return None + + return stack[-1] + + def __call__( + self, name: t.Optional[str] = None, *, unbound_message: t.Optional[str] = None + ) -> "LocalProxy": + """Create a :class:`LocalProxy` that accesses the top of this + local stack. + + :param name: If given, the proxy access this attribute of the + top item, rather than the item itself. + :param unbound_message: The error message that the proxy will + show if the stack is empty. + """ + return LocalProxy(self, name, unbound_message=unbound_message) + + +class LocalManager: + """Manage releasing the data for the current context in one or more + :class:`Local` and :class:`LocalStack` objects. + + This should not be needed for modern use cases, and may be removed + in the future. + + :param locals: A local or list of locals to manage. + + .. versionchanged:: 2.0 + ``ident_func`` is deprecated and will be removed in Werkzeug + 2.1. + + .. versionchanged:: 0.7 + The ``ident_func`` parameter was added. + + .. versionchanged:: 0.6.1 + The :func:`release_local` function can be used instead of a + manager. + """ + + __slots__ = ("locals",) + + def __init__( + self, + locals: t.Optional[ + t.Union[Local, LocalStack, t.Iterable[t.Union[Local, LocalStack]]] + ] = None, + ) -> None: + if locals is None: + self.locals = [] + elif isinstance(locals, Local): + self.locals = [locals] + else: + self.locals = list(locals) # type: ignore[arg-type] + + def cleanup(self) -> None: + """Release the data in the locals for this context. Call this at + the end of each request or use :meth:`make_middleware`. + """ + for local in self.locals: + release_local(local) + + def make_middleware(self, app: "WSGIApplication") -> "WSGIApplication": + """Wrap a WSGI application so that local data is released + automatically after the response has been sent for a request. + """ + + def application( + environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + return ClosingIterator(app(environ, start_response), self.cleanup) + + return application + + def middleware(self, func: "WSGIApplication") -> "WSGIApplication": + """Like :meth:`make_middleware` but used as a decorator on the + WSGI application function. + + .. code-block:: python + + @manager.middleware + def application(environ, start_response): + ... + """ + return update_wrapper(self.make_middleware(func), func) + + def __repr__(self) -> str: + return f"<{type(self).__name__} storages: {len(self.locals)}>" + + +class _ProxyLookup: + """Descriptor that handles proxied attribute lookup for + :class:`LocalProxy`. + + :param f: The built-in function this attribute is accessed through. + Instead of looking up the special method, the function call + is redone on the object. + :param fallback: Return this function if the proxy is unbound + instead of raising a :exc:`RuntimeError`. + :param is_attr: This proxied name is an attribute, not a function. + Call the fallback immediately to get the value. + :param class_value: Value to return when accessed from the + ``LocalProxy`` class directly. Used for ``__doc__`` so building + docs still works. + """ + + __slots__ = ("bind_f", "fallback", "is_attr", "class_value", "name") + + def __init__( + self, + f: t.Optional[t.Callable] = None, + fallback: t.Optional[t.Callable] = None, + class_value: t.Optional[t.Any] = None, + is_attr: bool = False, + ) -> None: + bind_f: t.Optional[t.Callable[["LocalProxy", t.Any], t.Callable]] + + if hasattr(f, "__get__"): + # A Python function, can be turned into a bound method. + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + return f.__get__(obj, type(obj)) # type: ignore + + elif f is not None: + # A C function, use partial to bind the first argument. + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + return partial(f, obj) + + else: + # Use getattr, which will produce a bound method. + bind_f = None + + self.bind_f = bind_f + self.fallback = fallback + self.class_value = class_value + self.is_attr = is_attr + + def __set_name__(self, owner: "LocalProxy", name: str) -> None: + self.name = name + + def __get__(self, instance: "LocalProxy", owner: t.Optional[type] = None) -> t.Any: + if instance is None: + if self.class_value is not None: + return self.class_value + + return self + + try: + obj = instance._get_current_object() + except RuntimeError: + if self.fallback is None: + raise + + fallback = self.fallback.__get__(instance, owner) + + if self.is_attr: + # __class__ and __doc__ are attributes, not methods. + # Call the fallback to get the value. + return fallback() + + return fallback + + if self.bind_f is not None: + return self.bind_f(instance, obj) + + return getattr(obj, self.name) + + def __repr__(self) -> str: + return f"proxy {self.name}" + + def __call__(self, instance: "LocalProxy", *args: t.Any, **kwargs: t.Any) -> t.Any: + """Support calling unbound methods from the class. For example, + this happens with ``copy.copy``, which does + ``type(x).__copy__(x)``. ``type(x)`` can't be proxied, so it + returns the proxy type and descriptor. + """ + return self.__get__(instance, type(instance))(*args, **kwargs) + + +class _ProxyIOp(_ProxyLookup): + """Look up an augmented assignment method on a proxied object. The + method is wrapped to return the proxy instead of the object. + """ + + __slots__ = () + + def __init__( + self, f: t.Optional[t.Callable] = None, fallback: t.Optional[t.Callable] = None + ) -> None: + super().__init__(f, fallback) + + def bind_f(instance: "LocalProxy", obj: t.Any) -> t.Callable: + def i_op(self: t.Any, other: t.Any) -> "LocalProxy": + f(self, other) # type: ignore + return instance + + return i_op.__get__(obj, type(obj)) # type: ignore + + self.bind_f = bind_f + + +def _l_to_r_op(op: F) -> F: + """Swap the argument order to turn an l-op into an r-op.""" + + def r_op(obj: t.Any, other: t.Any) -> t.Any: + return op(other, obj) + + return t.cast(F, r_op) + + +def _identity(o: T) -> T: + return o + + +class LocalProxy(t.Generic[T]): + """A proxy to the object bound to a context-local object. All + operations on the proxy are forwarded to the bound object. If no + object is bound, a ``RuntimeError`` is raised. + + :param local: The context-local object that provides the proxied + object. + :param name: Proxy this attribute from the proxied object. + :param unbound_message: The error message to show if the + context-local object is unbound. + + Proxy a :class:`~contextvars.ContextVar` to make it easier to + access. Pass a name to proxy that attribute. + + .. code-block:: python + + _request_var = ContextVar("request") + request = LocalProxy(_request_var) + session = LocalProxy(_request_var, "session") + + Proxy an attribute on a :class:`Local` namespace by calling the + local with the attribute name: + + .. code-block:: python + + data = Local() + user = data("user") + + Proxy the top item on a :class:`LocalStack` by calling the local. + Pass a name to proxy that attribute. + + .. code-block:: + + app_stack = LocalStack() + current_app = app_stack() + g = app_stack("g") + + Pass a function to proxy the return value from that function. This + was previously used to access attributes of local objects before + that was supported directly. + + .. code-block:: python + + session = LocalProxy(lambda: request.session) + + ``__repr__`` and ``__class__`` are proxied, so ``repr(x)`` and + ``isinstance(x, cls)`` will look like the proxied object. Use + ``issubclass(type(x), LocalProxy)`` to check if an object is a + proxy. + + .. code-block:: python + + repr(user) # + isinstance(user, User) # True + issubclass(type(user), LocalProxy) # True + + .. versionchanged:: 2.2.2 + ``__wrapped__`` is set when wrapping an object, not only when + wrapping a function, to prevent doctest from failing. + + .. versionchanged:: 2.2 + Can proxy a ``ContextVar`` or ``LocalStack`` directly. + + .. versionchanged:: 2.2 + The ``name`` parameter can be used with any proxied object, not + only ``Local``. + + .. versionchanged:: 2.2 + Added the ``unbound_message`` parameter. + + .. versionchanged:: 2.0 + Updated proxied attributes and methods to reflect the current + data model. + + .. versionchanged:: 0.6.1 + The class can be instantiated with a callable. + """ + + __slots__ = ("__wrapped", "_get_current_object") + + _get_current_object: t.Callable[[], T] + """Return the current object this proxy is bound to. If the proxy is + unbound, this raises a ``RuntimeError``. + + This should be used if you need to pass the object to something that + doesn't understand the proxy. It can also be useful for performance + if you are accessing the object multiple times in a function, rather + than going through the proxy multiple times. + """ + + def __init__( + self, + local: t.Union[ContextVar[T], Local, LocalStack[T], t.Callable[[], T]], + name: t.Optional[str] = None, + *, + unbound_message: t.Optional[str] = None, + ) -> None: + if name is None: + get_name = _identity + else: + get_name = attrgetter(name) # type: ignore[assignment] + + if unbound_message is None: + unbound_message = "object is not bound" + + if isinstance(local, Local): + if name is None: + raise TypeError("'name' is required when proxying a 'Local' object.") + + def _get_current_object() -> T: + try: + return get_name(local) # type: ignore[return-value] + except AttributeError: + raise RuntimeError(unbound_message) from None + + elif isinstance(local, LocalStack): + + def _get_current_object() -> T: + obj = local.top # type: ignore[union-attr] + + if obj is None: + raise RuntimeError(unbound_message) + + return get_name(obj) + + elif isinstance(local, ContextVar): + + def _get_current_object() -> T: + try: + obj = local.get() # type: ignore[union-attr] + except LookupError: + raise RuntimeError(unbound_message) from None + + return get_name(obj) + + elif callable(local): + + def _get_current_object() -> T: + return get_name(local()) # type: ignore + + else: + raise TypeError(f"Don't know how to proxy '{type(local)}'.") + + object.__setattr__(self, "_LocalProxy__wrapped", local) + object.__setattr__(self, "_get_current_object", _get_current_object) + + __doc__ = _ProxyLookup( # type: ignore + class_value=__doc__, fallback=lambda self: type(self).__doc__, is_attr=True + ) + __wrapped__ = _ProxyLookup( + fallback=lambda self: self._LocalProxy__wrapped, is_attr=True + ) + # __del__ should only delete the proxy + __repr__ = _ProxyLookup( # type: ignore + repr, fallback=lambda self: f"<{type(self).__name__} unbound>" + ) + __str__ = _ProxyLookup(str) # type: ignore + __bytes__ = _ProxyLookup(bytes) + __format__ = _ProxyLookup() # type: ignore + __lt__ = _ProxyLookup(operator.lt) + __le__ = _ProxyLookup(operator.le) + __eq__ = _ProxyLookup(operator.eq) # type: ignore + __ne__ = _ProxyLookup(operator.ne) # type: ignore + __gt__ = _ProxyLookup(operator.gt) + __ge__ = _ProxyLookup(operator.ge) + __hash__ = _ProxyLookup(hash) # type: ignore + __bool__ = _ProxyLookup(bool, fallback=lambda self: False) + __getattr__ = _ProxyLookup(getattr) + # __getattribute__ triggered through __getattr__ + __setattr__ = _ProxyLookup(setattr) # type: ignore + __delattr__ = _ProxyLookup(delattr) # type: ignore + __dir__ = _ProxyLookup(dir, fallback=lambda self: []) # type: ignore + # __get__ (proxying descriptor not supported) + # __set__ (descriptor) + # __delete__ (descriptor) + # __set_name__ (descriptor) + # __objclass__ (descriptor) + # __slots__ used by proxy itself + # __dict__ (__getattr__) + # __weakref__ (__getattr__) + # __init_subclass__ (proxying metaclass not supported) + # __prepare__ (metaclass) + __class__ = _ProxyLookup( + fallback=lambda self: type(self), is_attr=True + ) # type: ignore + __instancecheck__ = _ProxyLookup(lambda self, other: isinstance(other, self)) + __subclasscheck__ = _ProxyLookup(lambda self, other: issubclass(other, self)) + # __class_getitem__ triggered through __getitem__ + __call__ = _ProxyLookup(lambda self, *args, **kwargs: self(*args, **kwargs)) + __len__ = _ProxyLookup(len) + __length_hint__ = _ProxyLookup(operator.length_hint) + __getitem__ = _ProxyLookup(operator.getitem) + __setitem__ = _ProxyLookup(operator.setitem) + __delitem__ = _ProxyLookup(operator.delitem) + # __missing__ triggered through __getitem__ + __iter__ = _ProxyLookup(iter) + __next__ = _ProxyLookup(next) + __reversed__ = _ProxyLookup(reversed) + __contains__ = _ProxyLookup(operator.contains) + __add__ = _ProxyLookup(operator.add) + __sub__ = _ProxyLookup(operator.sub) + __mul__ = _ProxyLookup(operator.mul) + __matmul__ = _ProxyLookup(operator.matmul) + __truediv__ = _ProxyLookup(operator.truediv) + __floordiv__ = _ProxyLookup(operator.floordiv) + __mod__ = _ProxyLookup(operator.mod) + __divmod__ = _ProxyLookup(divmod) + __pow__ = _ProxyLookup(pow) + __lshift__ = _ProxyLookup(operator.lshift) + __rshift__ = _ProxyLookup(operator.rshift) + __and__ = _ProxyLookup(operator.and_) + __xor__ = _ProxyLookup(operator.xor) + __or__ = _ProxyLookup(operator.or_) + __radd__ = _ProxyLookup(_l_to_r_op(operator.add)) + __rsub__ = _ProxyLookup(_l_to_r_op(operator.sub)) + __rmul__ = _ProxyLookup(_l_to_r_op(operator.mul)) + __rmatmul__ = _ProxyLookup(_l_to_r_op(operator.matmul)) + __rtruediv__ = _ProxyLookup(_l_to_r_op(operator.truediv)) + __rfloordiv__ = _ProxyLookup(_l_to_r_op(operator.floordiv)) + __rmod__ = _ProxyLookup(_l_to_r_op(operator.mod)) + __rdivmod__ = _ProxyLookup(_l_to_r_op(divmod)) + __rpow__ = _ProxyLookup(_l_to_r_op(pow)) + __rlshift__ = _ProxyLookup(_l_to_r_op(operator.lshift)) + __rrshift__ = _ProxyLookup(_l_to_r_op(operator.rshift)) + __rand__ = _ProxyLookup(_l_to_r_op(operator.and_)) + __rxor__ = _ProxyLookup(_l_to_r_op(operator.xor)) + __ror__ = _ProxyLookup(_l_to_r_op(operator.or_)) + __iadd__ = _ProxyIOp(operator.iadd) + __isub__ = _ProxyIOp(operator.isub) + __imul__ = _ProxyIOp(operator.imul) + __imatmul__ = _ProxyIOp(operator.imatmul) + __itruediv__ = _ProxyIOp(operator.itruediv) + __ifloordiv__ = _ProxyIOp(operator.ifloordiv) + __imod__ = _ProxyIOp(operator.imod) + __ipow__ = _ProxyIOp(operator.ipow) + __ilshift__ = _ProxyIOp(operator.ilshift) + __irshift__ = _ProxyIOp(operator.irshift) + __iand__ = _ProxyIOp(operator.iand) + __ixor__ = _ProxyIOp(operator.ixor) + __ior__ = _ProxyIOp(operator.ior) + __neg__ = _ProxyLookup(operator.neg) + __pos__ = _ProxyLookup(operator.pos) + __abs__ = _ProxyLookup(abs) + __invert__ = _ProxyLookup(operator.invert) + __complex__ = _ProxyLookup(complex) + __int__ = _ProxyLookup(int) + __float__ = _ProxyLookup(float) + __index__ = _ProxyLookup(operator.index) + __round__ = _ProxyLookup(round) + __trunc__ = _ProxyLookup(math.trunc) + __floor__ = _ProxyLookup(math.floor) + __ceil__ = _ProxyLookup(math.ceil) + __enter__ = _ProxyLookup() + __exit__ = _ProxyLookup() + __await__ = _ProxyLookup() + __aiter__ = _ProxyLookup() + __anext__ = _ProxyLookup() + __aenter__ = _ProxyLookup() + __aexit__ = _ProxyLookup() + __copy__ = _ProxyLookup(copy.copy) + __deepcopy__ = _ProxyLookup(copy.deepcopy) + # __getnewargs_ex__ (pickle through proxy not supported) + # __getnewargs__ (pickle) + # __getstate__ (pickle) + # __setstate__ (pickle) + # __reduce__ (pickle) + # __reduce_ex__ (pickle) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__init__.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__init__.py new file mode 100644 index 00000000..6ddcf7f5 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__init__.py @@ -0,0 +1,22 @@ +""" +Middleware +========== + +A WSGI middleware is a WSGI application that wraps another application +in order to observe or change its behavior. Werkzeug provides some +middleware for common use cases. + +.. toctree:: + :maxdepth: 1 + + proxy_fix + shared_data + dispatcher + http_proxy + lint + profiler + +The :doc:`interactive debugger ` is also a middleware that can +be applied manually, although it is typically used automatically with +the :doc:`development server `. +""" diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..40ea0ec4 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc new file mode 100644 index 00000000..69290275 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc new file mode 100644 index 00000000..70caf57e Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/lint.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/lint.cpython-310.pyc new file mode 100644 index 00000000..af1e2697 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/lint.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-310.pyc new file mode 100644 index 00000000..3fa39f8a Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc new file mode 100644 index 00000000..b35c3a2b Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc new file mode 100644 index 00000000..646c3e53 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py new file mode 100644 index 00000000..ace1c750 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/dispatcher.py @@ -0,0 +1,78 @@ +""" +Application Dispatcher +====================== + +This middleware creates a single WSGI application that dispatches to +multiple other WSGI applications mounted at different URL paths. + +A common example is writing a Single Page Application, where you have a +backend API and a frontend written in JavaScript that does the routing +in the browser rather than requesting different pages from the server. +The frontend is a single HTML and JS file that should be served for any +path besides "/api". + +This example dispatches to an API app under "/api", an admin app +under "/admin", and an app that serves frontend files for all other +requests:: + + app = DispatcherMiddleware(serve_frontend, { + '/api': api_app, + '/admin': admin_app, + }) + +In production, you might instead handle this at the HTTP server level, +serving files or proxying to application servers based on location. The +API and admin apps would each be deployed with a separate WSGI server, +and the static files would be served directly by the HTTP server. + +.. autoclass:: DispatcherMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class DispatcherMiddleware: + """Combine multiple applications as a single WSGI application. + Requests are dispatched to an application based on the path it is + mounted under. + + :param app: The WSGI application to dispatch to if the request + doesn't match a mounted path. + :param mounts: Maps path prefixes to applications for dispatching. + """ + + def __init__( + self, + app: "WSGIApplication", + mounts: t.Optional[t.Dict[str, "WSGIApplication"]] = None, + ) -> None: + self.app = app + self.mounts = mounts or {} + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + script = environ.get("PATH_INFO", "") + path_info = "" + + while "/" in script: + if script in self.mounts: + app = self.mounts[script] + break + + script, last_item = script.rsplit("/", 1) + path_info = f"/{last_item}{path_info}" + else: + app = self.mounts.get(script, self.app) + + original_script_name = environ.get("SCRIPT_NAME", "") + environ["SCRIPT_NAME"] = original_script_name + script + environ["PATH_INFO"] = path_info + return app(environ, start_response) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py new file mode 100644 index 00000000..1cde458d --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/http_proxy.py @@ -0,0 +1,230 @@ +""" +Basic HTTP Proxy +================ + +.. autoclass:: ProxyMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t +from http import client + +from ..datastructures import EnvironHeaders +from ..http import is_hop_by_hop_header +from ..urls import url_parse +from ..urls import url_quote +from ..wsgi import get_input_stream + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyMiddleware: + """Proxy requests under a path to an external server, routing other + requests to the app. + + This middleware can only proxy HTTP requests, as HTTP is the only + protocol handled by the WSGI server. Other protocols, such as + WebSocket requests, cannot be proxied at this layer. This should + only be used for development, in production a real proxy server + should be used. + + The middleware takes a dict mapping a path prefix to a dict + describing the host to be proxied to:: + + app = ProxyMiddleware(app, { + "/static/": { + "target": "http://127.0.0.1:5001/", + } + }) + + Each host has the following options: + + ``target``: + The target URL to dispatch to. This is required. + ``remove_prefix``: + Whether to remove the prefix from the URL before dispatching it + to the target. The default is ``False``. + ``host``: + ``""`` (default): + The host header is automatically rewritten to the URL of the + target. + ``None``: + The host header is unmodified from the client request. + Any other value: + The host header is overwritten with the value. + ``headers``: + A dictionary of headers to be sent with the request to the + target. The default is ``{}``. + ``ssl_context``: + A :class:`ssl.SSLContext` defining how to verify requests if the + target is HTTPS. The default is ``None``. + + In the example above, everything under ``"/static/"`` is proxied to + the server on port 5001. The host header is rewritten to the target, + and the ``"/static/"`` prefix is removed from the URLs. + + :param app: The WSGI application to wrap. + :param targets: Proxy target configurations. See description above. + :param chunk_size: Size of chunks to read from input stream and + write to target. + :param timeout: Seconds before an operation to a target fails. + + .. versionadded:: 0.14 + """ + + def __init__( + self, + app: "WSGIApplication", + targets: t.Mapping[str, t.Dict[str, t.Any]], + chunk_size: int = 2 << 13, + timeout: int = 10, + ) -> None: + def _set_defaults(opts: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: + opts.setdefault("remove_prefix", False) + opts.setdefault("host", "") + opts.setdefault("headers", {}) + opts.setdefault("ssl_context", None) + return opts + + self.app = app + self.targets = { + f"/{k.strip('/')}/": _set_defaults(v) for k, v in targets.items() + } + self.chunk_size = chunk_size + self.timeout = timeout + + def proxy_to( + self, opts: t.Dict[str, t.Any], path: str, prefix: str + ) -> "WSGIApplication": + target = url_parse(opts["target"]) + host = t.cast(str, target.ascii_host) + + def application( + environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + headers = list(EnvironHeaders(environ).items()) + headers[:] = [ + (k, v) + for k, v in headers + if not is_hop_by_hop_header(k) + and k.lower() not in ("content-length", "host") + ] + headers.append(("Connection", "close")) + + if opts["host"] == "": + headers.append(("Host", host)) + elif opts["host"] is None: + headers.append(("Host", environ["HTTP_HOST"])) + else: + headers.append(("Host", opts["host"])) + + headers.extend(opts["headers"].items()) + remote_path = path + + if opts["remove_prefix"]: + remote_path = remote_path[len(prefix) :].lstrip("/") + remote_path = f"{target.path.rstrip('/')}/{remote_path}" + + content_length = environ.get("CONTENT_LENGTH") + chunked = False + + if content_length not in ("", None): + headers.append(("Content-Length", content_length)) # type: ignore + elif content_length is not None: + headers.append(("Transfer-Encoding", "chunked")) + chunked = True + + try: + if target.scheme == "http": + con = client.HTTPConnection( + host, target.port or 80, timeout=self.timeout + ) + elif target.scheme == "https": + con = client.HTTPSConnection( + host, + target.port or 443, + timeout=self.timeout, + context=opts["ssl_context"], + ) + else: + raise RuntimeError( + "Target scheme must be 'http' or 'https', got" + f" {target.scheme!r}." + ) + + con.connect() + remote_url = url_quote(remote_path) + querystring = environ["QUERY_STRING"] + + if querystring: + remote_url = f"{remote_url}?{querystring}" + + con.putrequest(environ["REQUEST_METHOD"], remote_url, skip_host=True) + + for k, v in headers: + if k.lower() == "connection": + v = "close" + + con.putheader(k, v) + + con.endheaders() + stream = get_input_stream(environ) + + while True: + data = stream.read(self.chunk_size) + + if not data: + break + + if chunked: + con.send(b"%x\r\n%s\r\n" % (len(data), data)) + else: + con.send(data) + + resp = con.getresponse() + except OSError: + from ..exceptions import BadGateway + + return BadGateway()(environ, start_response) + + start_response( + f"{resp.status} {resp.reason}", + [ + (k.title(), v) + for k, v in resp.getheaders() + if not is_hop_by_hop_header(k) + ], + ) + + def read() -> t.Iterator[bytes]: + while True: + try: + data = resp.read(self.chunk_size) + except OSError: + break + + if not data: + break + + yield data + + return read() + + return application + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + path = environ["PATH_INFO"] + app = self.app + + for prefix, opts in self.targets.items(): + if path.startswith(prefix): + app = self.proxy_to(opts, path, prefix) + break + + return app(environ, start_response) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/lint.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/lint.py new file mode 100644 index 00000000..fcf3b413 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/lint.py @@ -0,0 +1,420 @@ +""" +WSGI Protocol Linter +==================== + +This module provides a middleware that performs sanity checks on the +behavior of the WSGI server and application. It checks that the +:pep:`3333` WSGI spec is properly implemented. It also warns on some +common HTTP errors such as non-empty responses for 304 status codes. + +.. autoclass:: LintMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t +from types import TracebackType +from urllib.parse import urlparse +from warnings import warn + +from ..datastructures import Headers +from ..http import is_entity_header +from ..wsgi import FileWrapper + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class WSGIWarning(Warning): + """Warning class for WSGI warnings.""" + + +class HTTPWarning(Warning): + """Warning class for HTTP warnings.""" + + +def check_type(context: str, obj: object, need: t.Type = str) -> None: + if type(obj) is not need: + warn( + f"{context!r} requires {need.__name__!r}, got {type(obj).__name__!r}.", + WSGIWarning, + stacklevel=3, + ) + + +class InputStream: + def __init__(self, stream: t.IO[bytes]) -> None: + self._stream = stream + + def read(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "WSGI does not guarantee an EOF marker on the input stream, thus making" + " calls to 'wsgi.input.read()' unsafe. Conforming servers may never" + " return from this call.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) != 1: + warn( + "Too many parameters passed to 'wsgi.input.read()'.", + WSGIWarning, + stacklevel=2, + ) + return self._stream.read(*args) + + def readline(self, *args: t.Any) -> bytes: + if len(args) == 0: + warn( + "Calls to 'wsgi.input.readline()' without arguments are unsafe. Use" + " 'wsgi.input.read()' instead.", + WSGIWarning, + stacklevel=2, + ) + elif len(args) == 1: + warn( + "'wsgi.input.readline()' was called with a size hint. WSGI does not" + " support this, although it's available on all major servers.", + WSGIWarning, + stacklevel=2, + ) + else: + raise TypeError("Too many arguments passed to 'wsgi.input.readline()'.") + return self._stream.readline(*args) + + def __iter__(self) -> t.Iterator[bytes]: + try: + return iter(self._stream) + except TypeError: + warn("'wsgi.input' is not iterable.", WSGIWarning, stacklevel=2) + return iter(()) + + def close(self) -> None: + warn("The application closed the input stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class ErrorStream: + def __init__(self, stream: t.IO[str]) -> None: + self._stream = stream + + def write(self, s: str) -> None: + check_type("wsgi.error.write()", s, str) + self._stream.write(s) + + def flush(self) -> None: + self._stream.flush() + + def writelines(self, seq: t.Iterable[str]) -> None: + for line in seq: + self.write(line) + + def close(self) -> None: + warn("The application closed the error stream!", WSGIWarning, stacklevel=2) + self._stream.close() + + +class GuardedWrite: + def __init__(self, write: t.Callable[[bytes], object], chunks: t.List[int]) -> None: + self._write = write + self._chunks = chunks + + def __call__(self, s: bytes) -> None: + check_type("write()", s, bytes) + self._write(s) + self._chunks.append(len(s)) + + +class GuardedIterator: + def __init__( + self, + iterator: t.Iterable[bytes], + headers_set: t.Tuple[int, Headers], + chunks: t.List[int], + ) -> None: + self._iterator = iterator + self._next = iter(iterator).__next__ + self.closed = False + self.headers_set = headers_set + self.chunks = chunks + + def __iter__(self) -> "GuardedIterator": + return self + + def __next__(self) -> bytes: + if self.closed: + warn("Iterated over closed 'app_iter'.", WSGIWarning, stacklevel=2) + + rv = self._next() + + if not self.headers_set: + warn( + "The application returned before it started the response.", + WSGIWarning, + stacklevel=2, + ) + + check_type("application iterator items", rv, bytes) + self.chunks.append(len(rv)) + return rv + + def close(self) -> None: + self.closed = True + + if hasattr(self._iterator, "close"): + self._iterator.close() + + if self.headers_set: + status_code, headers = self.headers_set + bytes_sent = sum(self.chunks) + content_length = headers.get("content-length", type=int) + + if status_code == 304: + for key, _value in headers: + key = key.lower() + if key not in ("expires", "content-location") and is_entity_header( + key + ): + warn( + f"Entity header {key!r} found in 304 response.", HTTPWarning + ) + if bytes_sent: + warn("304 responses must not have a body.", HTTPWarning) + elif 100 <= status_code < 200 or status_code == 204: + if content_length != 0: + warn( + f"{status_code} responses must have an empty content length.", + HTTPWarning, + ) + if bytes_sent: + warn(f"{status_code} responses must not have a body.", HTTPWarning) + elif content_length is not None and content_length != bytes_sent: + warn( + "Content-Length and the number of bytes sent to the" + " client do not match.", + WSGIWarning, + ) + + def __del__(self) -> None: + if not self.closed: + try: + warn( + "Iterator was garbage collected before it was closed.", WSGIWarning + ) + except Exception: + pass + + +class LintMiddleware: + """Warns about common errors in the WSGI and HTTP behavior of the + server and wrapped application. Some of the issues it checks are: + + - invalid status codes + - non-bytes sent to the WSGI server + - strings returned from the WSGI application + - non-empty conditional responses + - unquoted etags + - relative URLs in the Location header + - unsafe calls to wsgi.input + - unclosed iterators + + Error information is emitted using the :mod:`warnings` module. + + :param app: The WSGI application to wrap. + + .. code-block:: python + + from werkzeug.middleware.lint import LintMiddleware + app = LintMiddleware(app) + """ + + def __init__(self, app: "WSGIApplication") -> None: + self.app = app + + def check_environ(self, environ: "WSGIEnvironment") -> None: + if type(environ) is not dict: + warn( + "WSGI environment is not a standard Python dict.", + WSGIWarning, + stacklevel=4, + ) + for key in ( + "REQUEST_METHOD", + "SERVER_NAME", + "SERVER_PORT", + "wsgi.version", + "wsgi.input", + "wsgi.errors", + "wsgi.multithread", + "wsgi.multiprocess", + "wsgi.run_once", + ): + if key not in environ: + warn( + f"Required environment key {key!r} not found", + WSGIWarning, + stacklevel=3, + ) + if environ["wsgi.version"] != (1, 0): + warn("Environ is not a WSGI 1.0 environ.", WSGIWarning, stacklevel=3) + + script_name = environ.get("SCRIPT_NAME", "") + path_info = environ.get("PATH_INFO", "") + + if script_name and script_name[0] != "/": + warn( + f"'SCRIPT_NAME' does not start with a slash: {script_name!r}", + WSGIWarning, + stacklevel=3, + ) + + if path_info and path_info[0] != "/": + warn( + f"'PATH_INFO' does not start with a slash: {path_info!r}", + WSGIWarning, + stacklevel=3, + ) + + def check_start_response( + self, + status: str, + headers: t.List[t.Tuple[str, str]], + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ], + ) -> t.Tuple[int, Headers]: + check_type("status", status, str) + status_code_str = status.split(None, 1)[0] + + if len(status_code_str) != 3 or not status_code_str.isdecimal(): + warn("Status code must be three digits.", WSGIWarning, stacklevel=3) + + if len(status) < 4 or status[3] != " ": + warn( + f"Invalid value for status {status!r}. Valid status strings are three" + " digits, a space and a status explanation.", + WSGIWarning, + stacklevel=3, + ) + + status_code = int(status_code_str) + + if status_code < 100: + warn("Status code < 100 detected.", WSGIWarning, stacklevel=3) + + if type(headers) is not list: + warn("Header list is not a list.", WSGIWarning, stacklevel=3) + + for item in headers: + if type(item) is not tuple or len(item) != 2: + warn("Header items must be 2-item tuples.", WSGIWarning, stacklevel=3) + name, value = item + if type(name) is not str or type(value) is not str: + warn( + "Header keys and values must be strings.", WSGIWarning, stacklevel=3 + ) + if name.lower() == "status": + warn( + "The status header is not supported due to" + " conflicts with the CGI spec.", + WSGIWarning, + stacklevel=3, + ) + + if exc_info is not None and not isinstance(exc_info, tuple): + warn("Invalid value for exc_info.", WSGIWarning, stacklevel=3) + + headers = Headers(headers) + self.check_headers(headers) + + return status_code, headers + + def check_headers(self, headers: Headers) -> None: + etag = headers.get("etag") + + if etag is not None: + if etag.startswith(("W/", "w/")): + if etag.startswith("w/"): + warn( + "Weak etag indicator should be upper case.", + HTTPWarning, + stacklevel=4, + ) + + etag = etag[2:] + + if not (etag[:1] == etag[-1:] == '"'): + warn("Unquoted etag emitted.", HTTPWarning, stacklevel=4) + + location = headers.get("location") + + if location is not None: + if not urlparse(location).netloc: + warn( + "Absolute URLs required for location header.", + HTTPWarning, + stacklevel=4, + ) + + def check_iterator(self, app_iter: t.Iterable[bytes]) -> None: + if isinstance(app_iter, bytes): + warn( + "The application returned a bytestring. The response will send one" + " character at a time to the client, which will kill performance." + " Return a list or iterable instead.", + WSGIWarning, + stacklevel=3, + ) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Iterable[bytes]: + if len(args) != 2: + warn("A WSGI app takes two arguments.", WSGIWarning, stacklevel=2) + + if kwargs: + warn( + "A WSGI app does not take keyword arguments.", WSGIWarning, stacklevel=2 + ) + + environ: "WSGIEnvironment" = args[0] + start_response: "StartResponse" = args[1] + + self.check_environ(environ) + environ["wsgi.input"] = InputStream(environ["wsgi.input"]) + environ["wsgi.errors"] = ErrorStream(environ["wsgi.errors"]) + + # Hook our own file wrapper in so that applications will always + # iterate to the end and we can check the content length. + environ["wsgi.file_wrapper"] = FileWrapper + + headers_set: t.List[t.Any] = [] + chunks: t.List[int] = [] + + def checking_start_response( + *args: t.Any, **kwargs: t.Any + ) -> t.Callable[[bytes], None]: + if len(args) not in {2, 3}: + warn( + f"Invalid number of arguments: {len(args)}, expected 2 or 3.", + WSGIWarning, + stacklevel=2, + ) + + if kwargs: + warn("'start_response' does not take keyword arguments.", WSGIWarning) + + status: str = args[0] + headers: t.List[t.Tuple[str, str]] = args[1] + exc_info: t.Optional[ + t.Tuple[t.Type[BaseException], BaseException, TracebackType] + ] = (args[2] if len(args) == 3 else None) + + headers_set[:] = self.check_start_response(status, headers, exc_info) + return GuardedWrite(start_response(status, headers, exc_info), chunks) + + app_iter = self.app(environ, t.cast("StartResponse", checking_start_response)) + self.check_iterator(app_iter) + return GuardedIterator( + app_iter, t.cast(t.Tuple[int, Headers], headers_set), chunks + ) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/profiler.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/profiler.py new file mode 100644 index 00000000..f91e33b8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/profiler.py @@ -0,0 +1,139 @@ +""" +Application Profiler +==================== + +This module provides a middleware that profiles each request with the +:mod:`cProfile` module. This can help identify bottlenecks in your code +that may be slowing down your application. + +.. autoclass:: ProfilerMiddleware + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import os.path +import sys +import time +import typing as t +from pstats import Stats + +try: + from cProfile import Profile +except ImportError: + from profile import Profile # type: ignore + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProfilerMiddleware: + """Wrap a WSGI application and profile the execution of each + request. Responses are buffered so that timings are more exact. + + If ``stream`` is given, :class:`pstats.Stats` are written to it + after each request. If ``profile_dir`` is given, :mod:`cProfile` + data files are saved to that directory, one file per request. + + The filename can be customized by passing ``filename_format``. If + it is a string, it will be formatted using :meth:`str.format` with + the following fields available: + + - ``{method}`` - The request method; GET, POST, etc. + - ``{path}`` - The request path or 'root' should one not exist. + - ``{elapsed}`` - The elapsed time of the request. + - ``{time}`` - The time of the request. + + If it is a callable, it will be called with the WSGI ``environ`` + dict and should return a filename. + + :param app: The WSGI application to wrap. + :param stream: Write stats to this stream. Disable with ``None``. + :param sort_by: A tuple of columns to sort stats by. See + :meth:`pstats.Stats.sort_stats`. + :param restrictions: A tuple of restrictions to filter stats by. See + :meth:`pstats.Stats.print_stats`. + :param profile_dir: Save profile data files to this directory. + :param filename_format: Format string for profile data file names, + or a callable returning a name. See explanation above. + + .. code-block:: python + + from werkzeug.middleware.profiler import ProfilerMiddleware + app = ProfilerMiddleware(app) + + .. versionchanged:: 0.15 + Stats are written even if ``profile_dir`` is given, and can be + disable by passing ``stream=None``. + + .. versionadded:: 0.15 + Added ``filename_format``. + + .. versionadded:: 0.9 + Added ``restrictions`` and ``profile_dir``. + """ + + def __init__( + self, + app: "WSGIApplication", + stream: t.IO[str] = sys.stdout, + sort_by: t.Iterable[str] = ("time", "calls"), + restrictions: t.Iterable[t.Union[str, int, float]] = (), + profile_dir: t.Optional[str] = None, + filename_format: str = "{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof", + ) -> None: + self._app = app + self._stream = stream + self._sort_by = sort_by + self._restrictions = restrictions + self._profile_dir = profile_dir + self._filename_format = filename_format + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + response_body: t.List[bytes] = [] + + def catching_start_response(status, headers, exc_info=None): # type: ignore + start_response(status, headers, exc_info) + return response_body.append + + def runapp() -> None: + app_iter = self._app( + environ, t.cast("StartResponse", catching_start_response) + ) + response_body.extend(app_iter) + + if hasattr(app_iter, "close"): + app_iter.close() + + profile = Profile() + start = time.time() + profile.runcall(runapp) + body = b"".join(response_body) + elapsed = time.time() - start + + if self._profile_dir is not None: + if callable(self._filename_format): + filename = self._filename_format(environ) + else: + filename = self._filename_format.format( + method=environ["REQUEST_METHOD"], + path=environ["PATH_INFO"].strip("/").replace("/", ".") or "root", + elapsed=elapsed * 1000.0, + time=time.time(), + ) + filename = os.path.join(self._profile_dir, filename) + profile.dump_stats(filename) + + if self._stream is not None: + stats = Stats(profile, stream=self._stream) + stats.sort_stats(*self._sort_by) + print("-" * 80, file=self._stream) + path_info = environ.get("PATH_INFO", "") + print(f"PATH: {path_info!r}", file=self._stream) + stats.print_stats(*self._restrictions) + print(f"{'-' * 80}\n", file=self._stream) + + return [body] diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py new file mode 100644 index 00000000..4cef7cc8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/proxy_fix.py @@ -0,0 +1,187 @@ +""" +X-Forwarded-For Proxy Fix +========================= + +This module provides a middleware that adjusts the WSGI environ based on +``X-Forwarded-`` headers that proxies in front of an application may +set. + +When an application is running behind a proxy server, WSGI may see the +request as coming from that server rather than the real client. Proxies +set various headers to track where the request actually came from. + +This middleware should only be used if the application is actually +behind such a proxy, and should be configured with the number of proxies +that are chained in front of it. Not all proxies set all the headers. +Since incoming headers can be faked, you must set how many proxies are +setting each header so the middleware knows what to trust. + +.. autoclass:: ProxyFix + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import typing as t + +from ..http import parse_list_header + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class ProxyFix: + """Adjust the WSGI environ based on ``X-Forwarded-`` that proxies in + front of the application may set. + + - ``X-Forwarded-For`` sets ``REMOTE_ADDR``. + - ``X-Forwarded-Proto`` sets ``wsgi.url_scheme``. + - ``X-Forwarded-Host`` sets ``HTTP_HOST``, ``SERVER_NAME``, and + ``SERVER_PORT``. + - ``X-Forwarded-Port`` sets ``HTTP_HOST`` and ``SERVER_PORT``. + - ``X-Forwarded-Prefix`` sets ``SCRIPT_NAME``. + + You must tell the middleware how many proxies set each header so it + knows what values to trust. It is a security issue to trust values + that came from the client rather than a proxy. + + The original values of the headers are stored in the WSGI + environ as ``werkzeug.proxy_fix.orig``, a dict. + + :param app: The WSGI application to wrap. + :param x_for: Number of values to trust for ``X-Forwarded-For``. + :param x_proto: Number of values to trust for ``X-Forwarded-Proto``. + :param x_host: Number of values to trust for ``X-Forwarded-Host``. + :param x_port: Number of values to trust for ``X-Forwarded-Port``. + :param x_prefix: Number of values to trust for + ``X-Forwarded-Prefix``. + + .. code-block:: python + + from werkzeug.middleware.proxy_fix import ProxyFix + # App is behind one proxy that sets the -For and -Host headers. + app = ProxyFix(app, x_for=1, x_host=1) + + .. versionchanged:: 1.0 + Deprecated code has been removed: + + * The ``num_proxies`` argument and attribute. + * The ``get_remote_addr`` method. + * The environ keys ``orig_remote_addr``, + ``orig_wsgi_url_scheme``, and ``orig_http_host``. + + .. versionchanged:: 0.15 + All headers support multiple values. The ``num_proxies`` + argument is deprecated. Each header is configured with a + separate number of trusted proxies. + + .. versionchanged:: 0.15 + Original WSGI environ values are stored in the + ``werkzeug.proxy_fix.orig`` dict. ``orig_remote_addr``, + ``orig_wsgi_url_scheme``, and ``orig_http_host`` are deprecated + and will be removed in 1.0. + + .. versionchanged:: 0.15 + Support ``X-Forwarded-Port`` and ``X-Forwarded-Prefix``. + + .. versionchanged:: 0.15 + ``X-Forwarded-Host`` and ``X-Forwarded-Port`` modify + ``SERVER_NAME`` and ``SERVER_PORT``. + """ + + def __init__( + self, + app: "WSGIApplication", + x_for: int = 1, + x_proto: int = 1, + x_host: int = 0, + x_port: int = 0, + x_prefix: int = 0, + ) -> None: + self.app = app + self.x_for = x_for + self.x_proto = x_proto + self.x_host = x_host + self.x_port = x_port + self.x_prefix = x_prefix + + def _get_real_value(self, trusted: int, value: t.Optional[str]) -> t.Optional[str]: + """Get the real value from a list header based on the configured + number of trusted proxies. + + :param trusted: Number of values to trust in the header. + :param value: Comma separated list header value to parse. + :return: The real value, or ``None`` if there are fewer values + than the number of trusted proxies. + + .. versionchanged:: 1.0 + Renamed from ``_get_trusted_comma``. + + .. versionadded:: 0.15 + """ + if not (trusted and value): + return None + values = parse_list_header(value) + if len(values) >= trusted: + return values[-trusted] + return None + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Modify the WSGI environ based on the various ``Forwarded`` + headers before calling the wrapped application. Store the + original environ values in ``werkzeug.proxy_fix.orig_{key}``. + """ + environ_get = environ.get + orig_remote_addr = environ_get("REMOTE_ADDR") + orig_wsgi_url_scheme = environ_get("wsgi.url_scheme") + orig_http_host = environ_get("HTTP_HOST") + environ.update( + { + "werkzeug.proxy_fix.orig": { + "REMOTE_ADDR": orig_remote_addr, + "wsgi.url_scheme": orig_wsgi_url_scheme, + "HTTP_HOST": orig_http_host, + "SERVER_NAME": environ_get("SERVER_NAME"), + "SERVER_PORT": environ_get("SERVER_PORT"), + "SCRIPT_NAME": environ_get("SCRIPT_NAME"), + } + } + ) + + x_for = self._get_real_value(self.x_for, environ_get("HTTP_X_FORWARDED_FOR")) + if x_for: + environ["REMOTE_ADDR"] = x_for + + x_proto = self._get_real_value( + self.x_proto, environ_get("HTTP_X_FORWARDED_PROTO") + ) + if x_proto: + environ["wsgi.url_scheme"] = x_proto + + x_host = self._get_real_value(self.x_host, environ_get("HTTP_X_FORWARDED_HOST")) + if x_host: + environ["HTTP_HOST"] = environ["SERVER_NAME"] = x_host + # "]" to check for IPv6 address without port + if ":" in x_host and not x_host.endswith("]"): + environ["SERVER_NAME"], environ["SERVER_PORT"] = x_host.rsplit(":", 1) + + x_port = self._get_real_value(self.x_port, environ_get("HTTP_X_FORWARDED_PORT")) + if x_port: + host = environ.get("HTTP_HOST") + if host: + # "]" to check for IPv6 address without port + if ":" in host and not host.endswith("]"): + host = host.rsplit(":", 1)[0] + environ["HTTP_HOST"] = f"{host}:{x_port}" + environ["SERVER_PORT"] = x_port + + x_prefix = self._get_real_value( + self.x_prefix, environ_get("HTTP_X_FORWARDED_PREFIX") + ) + if x_prefix: + environ["SCRIPT_NAME"] = x_prefix + + return self.app(environ, start_response) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py new file mode 100644 index 00000000..2ec396c5 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/middleware/shared_data.py @@ -0,0 +1,280 @@ +""" +Serve Shared Static Files +========================= + +.. autoclass:: SharedDataMiddleware + :members: is_allowed + +:copyright: 2007 Pallets +:license: BSD-3-Clause +""" +import mimetypes +import os +import pkgutil +import posixpath +import typing as t +from datetime import datetime +from datetime import timezone +from io import BytesIO +from time import time +from zlib import adler32 + +from ..http import http_date +from ..http import is_resource_modified +from ..security import safe_join +from ..utils import get_content_type +from ..wsgi import get_path_info +from ..wsgi import wrap_file + +_TOpener = t.Callable[[], t.Tuple[t.IO[bytes], datetime, int]] +_TLoader = t.Callable[[t.Optional[str]], t.Tuple[t.Optional[str], t.Optional[_TOpener]]] + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class SharedDataMiddleware: + + """A WSGI middleware which provides static content for development + environments or simple server setups. Its usage is quite simple:: + + import os + from werkzeug.middleware.shared_data import SharedDataMiddleware + + app = SharedDataMiddleware(app, { + '/shared': os.path.join(os.path.dirname(__file__), 'shared') + }) + + The contents of the folder ``./shared`` will now be available on + ``http://example.com/shared/``. This is pretty useful during development + because a standalone media server is not required. Files can also be + mounted on the root folder and still continue to use the application because + the shared data middleware forwards all unhandled requests to the + application, even if the requests are below one of the shared folders. + + If `pkg_resources` is available you can also tell the middleware to serve + files from package data:: + + app = SharedDataMiddleware(app, { + '/static': ('myapplication', 'static') + }) + + This will then serve the ``static`` folder in the `myapplication` + Python package. + + The optional `disallow` parameter can be a list of :func:`~fnmatch.fnmatch` + rules for files that are not accessible from the web. If `cache` is set to + `False` no caching headers are sent. + + Currently the middleware does not support non-ASCII filenames. If the + encoding on the file system happens to match the encoding of the URI it may + work but this could also be by accident. We strongly suggest using ASCII + only file names for static files. + + The middleware will guess the mimetype using the Python `mimetype` + module. If it's unable to figure out the charset it will fall back + to `fallback_mimetype`. + + :param app: the application to wrap. If you don't want to wrap an + application you can pass it :exc:`NotFound`. + :param exports: a list or dict of exported files and folders. + :param disallow: a list of :func:`~fnmatch.fnmatch` rules. + :param cache: enable or disable caching headers. + :param cache_timeout: the cache timeout in seconds for the headers. + :param fallback_mimetype: The fallback mimetype for unknown files. + + .. versionchanged:: 1.0 + The default ``fallback_mimetype`` is + ``application/octet-stream``. If a filename looks like a text + mimetype, the ``utf-8`` charset is added to it. + + .. versionadded:: 0.6 + Added ``fallback_mimetype``. + + .. versionchanged:: 0.5 + Added ``cache_timeout``. + """ + + def __init__( + self, + app: "WSGIApplication", + exports: t.Union[ + t.Dict[str, t.Union[str, t.Tuple[str, str]]], + t.Iterable[t.Tuple[str, t.Union[str, t.Tuple[str, str]]]], + ], + disallow: None = None, + cache: bool = True, + cache_timeout: int = 60 * 60 * 12, + fallback_mimetype: str = "application/octet-stream", + ) -> None: + self.app = app + self.exports: t.List[t.Tuple[str, _TLoader]] = [] + self.cache = cache + self.cache_timeout = cache_timeout + + if isinstance(exports, dict): + exports = exports.items() + + for key, value in exports: + if isinstance(value, tuple): + loader = self.get_package_loader(*value) + elif isinstance(value, str): + if os.path.isfile(value): + loader = self.get_file_loader(value) + else: + loader = self.get_directory_loader(value) + else: + raise TypeError(f"unknown def {value!r}") + + self.exports.append((key, loader)) + + if disallow is not None: + from fnmatch import fnmatch + + self.is_allowed = lambda x: not fnmatch(x, disallow) + + self.fallback_mimetype = fallback_mimetype + + def is_allowed(self, filename: str) -> bool: + """Subclasses can override this method to disallow the access to + certain files. However by providing `disallow` in the constructor + this method is overwritten. + """ + return True + + def _opener(self, filename: str) -> _TOpener: + return lambda: ( + open(filename, "rb"), + datetime.fromtimestamp(os.path.getmtime(filename), tz=timezone.utc), + int(os.path.getsize(filename)), + ) + + def get_file_loader(self, filename: str) -> _TLoader: + return lambda x: (os.path.basename(filename), self._opener(filename)) + + def get_package_loader(self, package: str, package_path: str) -> _TLoader: + load_time = datetime.now(timezone.utc) + provider = pkgutil.get_loader(package) + reader = provider.get_resource_reader(package) # type: ignore + + def loader( + path: t.Optional[str], + ) -> t.Tuple[t.Optional[str], t.Optional[_TOpener]]: + if path is None: + return None, None + + path = safe_join(package_path, path) + + if path is None: + return None, None + + basename = posixpath.basename(path) + + try: + resource = reader.open_resource(path) + except OSError: + return None, None + + if isinstance(resource, BytesIO): + return ( + basename, + lambda: (resource, load_time, len(resource.getvalue())), + ) + + return ( + basename, + lambda: ( + resource, + datetime.fromtimestamp( + os.path.getmtime(resource.name), tz=timezone.utc + ), + os.path.getsize(resource.name), + ), + ) + + return loader + + def get_directory_loader(self, directory: str) -> _TLoader: + def loader( + path: t.Optional[str], + ) -> t.Tuple[t.Optional[str], t.Optional[_TOpener]]: + if path is not None: + path = safe_join(directory, path) + + if path is None: + return None, None + else: + path = directory + + if os.path.isfile(path): + return os.path.basename(path), self._opener(path) + + return None, None + + return loader + + def generate_etag(self, mtime: datetime, file_size: int, real_filename: str) -> str: + real_filename = os.fsencode(real_filename) + timestamp = mtime.timestamp() + checksum = adler32(real_filename) & 0xFFFFFFFF + return f"wzsdm-{timestamp}-{file_size}-{checksum}" + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + path = get_path_info(environ) + file_loader = None + + for search_path, loader in self.exports: + if search_path == path: + real_filename, file_loader = loader(None) + + if file_loader is not None: + break + + if not search_path.endswith("/"): + search_path += "/" + + if path.startswith(search_path): + real_filename, file_loader = loader(path[len(search_path) :]) + + if file_loader is not None: + break + + if file_loader is None or not self.is_allowed(real_filename): # type: ignore + return self.app(environ, start_response) + + guessed_type = mimetypes.guess_type(real_filename) # type: ignore + mime_type = get_content_type(guessed_type[0] or self.fallback_mimetype, "utf-8") + f, mtime, file_size = file_loader() + + headers = [("Date", http_date())] + + if self.cache: + timeout = self.cache_timeout + etag = self.generate_etag(mtime, file_size, real_filename) # type: ignore + headers += [ + ("Etag", f'"{etag}"'), + ("Cache-Control", f"max-age={timeout}, public"), + ] + + if not is_resource_modified(environ, etag, last_modified=mtime): + f.close() + start_response("304 Not Modified", headers) + return [] + + headers.append(("Expires", http_date(time() + timeout))) + else: + headers.append(("Cache-Control", "public")) + + headers.extend( + ( + ("Content-Type", mime_type), + ("Content-Length", str(file_size)), + ("Last-Modified", http_date(mtime)), + ) + ) + start_response("200 OK", headers) + return wrap_file(environ, f) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/py.typed b/flask-server/venv/lib/python3.10/site-packages/werkzeug/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__init__.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__init__.py new file mode 100644 index 00000000..84b043fd --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__init__.py @@ -0,0 +1,133 @@ +"""When it comes to combining multiple controller or view functions +(however you want to call them) you need a dispatcher. A simple way +would be applying regular expression tests on the ``PATH_INFO`` and +calling registered callback functions that return the value then. + +This module implements a much more powerful system than simple regular +expression matching because it can also convert values in the URLs and +build URLs. + +Here a simple example that creates a URL map for an application with +two subdomains (www and kb) and some URL rules: + +.. code-block:: python + + m = Map([ + # Static URLs + Rule('/', endpoint='static/index'), + Rule('/about', endpoint='static/about'), + Rule('/help', endpoint='static/help'), + # Knowledge Base + Subdomain('kb', [ + Rule('/', endpoint='kb/index'), + Rule('/browse/', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse'), + Rule('/browse//', endpoint='kb/browse') + ]) + ], default_subdomain='www') + +If the application doesn't use subdomains it's perfectly fine to not set +the default subdomain and not use the `Subdomain` rule factory. The +endpoint in the rules can be anything, for example import paths or +unique identifiers. The WSGI application can use those endpoints to get the +handler for that URL. It doesn't have to be a string at all but it's +recommended. + +Now it's possible to create a URL adapter for one of the subdomains and +build URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.build("kb/browse", dict(id=42)) + 'http://kb.example.com/browse/42/' + + c.build("kb/browse", dict()) + 'http://kb.example.com/browse/' + + c.build("kb/browse", dict(id=42, page=3)) + 'http://kb.example.com/browse/42/3' + + c.build("static/about") + '/about' + + c.build("static/index", force_external=True) + 'http://www.example.com/' + + c = m.bind('example.com', subdomain='kb') + + c.build("static/about") + 'http://www.example.com/about' + +The first argument to bind is the server name *without* the subdomain. +Per default it will assume that the script is mounted on the root, but +often that's not the case so you can provide the real mount point as +second argument: + +.. code-block:: python + + c = m.bind('example.com', '/applications/example') + +The third argument can be the subdomain, if not given the default +subdomain is used. For more details about binding have a look at the +documentation of the `MapAdapter`. + +And here is how you can match URLs: + +.. code-block:: python + + c = m.bind('example.com') + + c.match("/") + ('static/index', {}) + + c.match("/about") + ('static/about', {}) + + c = m.bind('example.com', '/', 'kb') + + c.match("/") + ('kb/index', {}) + + c.match("/browse/42/23") + ('kb/browse', {'id': 42, 'page': 23}) + +If matching fails you get a ``NotFound`` exception, if the rule thinks +it's a good idea to redirect (for example because the URL was defined +to have a slash at the end but the request was missing that slash) it +will raise a ``RequestRedirect`` exception. Both are subclasses of +``HTTPException`` so you can use those errors as responses in the +application. + +If matching succeeded but the URL rule was incompatible to the given +method (for example there were only rules for ``GET`` and ``HEAD`` but +routing tried to match a ``POST`` request) a ``MethodNotAllowed`` +exception is raised. +""" +from .converters import AnyConverter as AnyConverter +from .converters import BaseConverter as BaseConverter +from .converters import FloatConverter as FloatConverter +from .converters import IntegerConverter as IntegerConverter +from .converters import PathConverter as PathConverter +from .converters import UnicodeConverter as UnicodeConverter +from .converters import UUIDConverter as UUIDConverter +from .converters import ValidationError as ValidationError +from .exceptions import BuildError as BuildError +from .exceptions import NoMatch as NoMatch +from .exceptions import RequestAliasRedirect as RequestAliasRedirect +from .exceptions import RequestPath as RequestPath +from .exceptions import RequestRedirect as RequestRedirect +from .exceptions import RoutingException as RoutingException +from .exceptions import WebsocketMismatch as WebsocketMismatch +from .map import Map as Map +from .map import MapAdapter as MapAdapter +from .matcher import StateMachineMatcher as StateMachineMatcher +from .rules import EndpointPrefix as EndpointPrefix +from .rules import parse_converter_args as parse_converter_args +from .rules import Rule as Rule +from .rules import RuleFactory as RuleFactory +from .rules import RuleTemplate as RuleTemplate +from .rules import RuleTemplateFactory as RuleTemplateFactory +from .rules import Subdomain as Subdomain +from .rules import Submount as Submount diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..5675d1da Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/converters.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/converters.cpython-310.pyc new file mode 100644 index 00000000..743d1359 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/converters.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-310.pyc new file mode 100644 index 00000000..d639d5d4 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/map.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/map.cpython-310.pyc new file mode 100644 index 00000000..46945717 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/map.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/matcher.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/matcher.cpython-310.pyc new file mode 100644 index 00000000..cfbc4987 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/matcher.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/rules.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/rules.cpython-310.pyc new file mode 100644 index 00000000..bd946ea5 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/__pycache__/rules.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/converters.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/converters.py new file mode 100644 index 00000000..bbad29d7 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/converters.py @@ -0,0 +1,257 @@ +import re +import typing as t +import uuid + +from ..urls import _fast_url_quote + +if t.TYPE_CHECKING: + from .map import Map + + +class ValidationError(ValueError): + """Validation error. If a rule converter raises this exception the rule + does not match the current URL and the next URL is tried. + """ + + +class BaseConverter: + """Base class for all converters.""" + + regex = "[^/]+" + weight = 100 + part_isolating = True + + def __init__(self, map: "Map", *args: t.Any, **kwargs: t.Any) -> None: + self.map = map + + def to_python(self, value: str) -> t.Any: + return value + + def to_url(self, value: t.Any) -> str: + if isinstance(value, (bytes, bytearray)): + return _fast_url_quote(value) + return _fast_url_quote(str(value).encode(self.map.charset)) + + +class UnicodeConverter(BaseConverter): + """This converter is the default converter and accepts any string but + only one path segment. Thus the string can not include a slash. + + This is the default validator. + + Example:: + + Rule('/pages/'), + Rule('/') + + :param map: the :class:`Map`. + :param minlength: the minimum length of the string. Must be greater + or equal 1. + :param maxlength: the maximum length of the string. + :param length: the exact length of the string. + """ + + part_isolating = True + + def __init__( + self, + map: "Map", + minlength: int = 1, + maxlength: t.Optional[int] = None, + length: t.Optional[int] = None, + ) -> None: + super().__init__(map) + if length is not None: + length_regex = f"{{{int(length)}}}" + else: + if maxlength is None: + maxlength_value = "" + else: + maxlength_value = str(int(maxlength)) + length_regex = f"{{{int(minlength)},{maxlength_value}}}" + self.regex = f"[^/]{length_regex}" + + +class AnyConverter(BaseConverter): + """Matches one of the items provided. Items can either be Python + identifiers or strings:: + + Rule('/') + + :param map: the :class:`Map`. + :param items: this function accepts the possible items as positional + arguments. + + .. versionchanged:: 2.2 + Value is validated when building a URL. + """ + + part_isolating = True + + def __init__(self, map: "Map", *items: str) -> None: + super().__init__(map) + self.items = set(items) + self.regex = f"(?:{'|'.join([re.escape(x) for x in items])})" + + def to_url(self, value: t.Any) -> str: + if value in self.items: + return str(value) + + valid_values = ", ".join(f"'{item}'" for item in sorted(self.items)) + raise ValueError(f"'{value}' is not one of {valid_values}") + + +class PathConverter(BaseConverter): + """Like the default :class:`UnicodeConverter`, but it also matches + slashes. This is useful for wikis and similar applications:: + + Rule('/') + Rule('//edit') + + :param map: the :class:`Map`. + """ + + regex = "[^/].*?" + weight = 200 + part_isolating = False + + +class NumberConverter(BaseConverter): + """Baseclass for `IntegerConverter` and `FloatConverter`. + + :internal: + """ + + weight = 50 + num_convert: t.Callable = int + part_isolating = True + + def __init__( + self, + map: "Map", + fixed_digits: int = 0, + min: t.Optional[int] = None, + max: t.Optional[int] = None, + signed: bool = False, + ) -> None: + if signed: + self.regex = self.signed_regex + super().__init__(map) + self.fixed_digits = fixed_digits + self.min = min + self.max = max + self.signed = signed + + def to_python(self, value: str) -> t.Any: + if self.fixed_digits and len(value) != self.fixed_digits: + raise ValidationError() + value = self.num_convert(value) + if (self.min is not None and value < self.min) or ( + self.max is not None and value > self.max + ): + raise ValidationError() + return value + + def to_url(self, value: t.Any) -> str: + value = str(self.num_convert(value)) + if self.fixed_digits: + value = value.zfill(self.fixed_digits) + return value + + @property + def signed_regex(self) -> str: + return f"-?{self.regex}" + + +class IntegerConverter(NumberConverter): + """This converter only accepts integer values:: + + Rule("/page/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/page/") + + :param map: The :class:`Map`. + :param fixed_digits: The number of fixed digits in the URL. If you + set this to ``4`` for example, the rule will only match if the + URL looks like ``/0001/``. The default is variable length. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+" + part_isolating = True + + +class FloatConverter(NumberConverter): + """This converter only accepts floating point values:: + + Rule("/probability/") + + By default it only accepts unsigned, positive values. The ``signed`` + parameter will enable signed, negative values. :: + + Rule("/offset/") + + :param map: The :class:`Map`. + :param min: The minimal value. + :param max: The maximal value. + :param signed: Allow signed (negative) values. + + .. versionadded:: 0.15 + The ``signed`` parameter. + """ + + regex = r"\d+\.\d+" + num_convert = float + part_isolating = True + + def __init__( + self, + map: "Map", + min: t.Optional[float] = None, + max: t.Optional[float] = None, + signed: bool = False, + ) -> None: + super().__init__(map, min=min, max=max, signed=signed) # type: ignore + + +class UUIDConverter(BaseConverter): + """This converter only accepts UUID strings:: + + Rule('/object/') + + .. versionadded:: 0.10 + + :param map: the :class:`Map`. + """ + + regex = ( + r"[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-" + r"[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + ) + part_isolating = True + + def to_python(self, value: str) -> uuid.UUID: + return uuid.UUID(value) + + def to_url(self, value: uuid.UUID) -> str: + return str(value) + + +#: the default converter mapping for the map. +DEFAULT_CONVERTERS: t.Mapping[str, t.Type[BaseConverter]] = { + "default": UnicodeConverter, + "string": UnicodeConverter, + "any": AnyConverter, + "path": PathConverter, + "int": IntegerConverter, + "float": FloatConverter, + "uuid": UUIDConverter, +} diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/exceptions.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/exceptions.py new file mode 100644 index 00000000..7cbe6e91 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/exceptions.py @@ -0,0 +1,146 @@ +import difflib +import typing as t + +from ..exceptions import BadRequest +from ..exceptions import HTTPException +from ..utils import cached_property +from ..utils import redirect + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + from .map import MapAdapter + from .rules import Rule # noqa: F401 + from ..wrappers.request import Request + from ..wrappers.response import Response + + +class RoutingException(Exception): + """Special exceptions that require the application to redirect, notifying + about missing urls, etc. + + :internal: + """ + + +class RequestRedirect(HTTPException, RoutingException): + """Raise if the map requests a redirect. This is for example the case if + `strict_slashes` are activated and an url that requires a trailing slash. + + The attribute `new_url` contains the absolute destination url. + """ + + code = 308 + + def __init__(self, new_url: str) -> None: + super().__init__(new_url) + self.new_url = new_url + + def get_response( + self, + environ: t.Optional[t.Union["WSGIEnvironment", "Request"]] = None, + scope: t.Optional[dict] = None, + ) -> "Response": + return redirect(self.new_url, self.code) + + +class RequestPath(RoutingException): + """Internal exception.""" + + __slots__ = ("path_info",) + + def __init__(self, path_info: str) -> None: + super().__init__() + self.path_info = path_info + + +class RequestAliasRedirect(RoutingException): # noqa: B903 + """This rule is an alias and wants to redirect to the canonical URL.""" + + def __init__(self, matched_values: t.Mapping[str, t.Any], endpoint: str) -> None: + super().__init__() + self.matched_values = matched_values + self.endpoint = endpoint + + +class BuildError(RoutingException, LookupError): + """Raised if the build system cannot find a URL for an endpoint with the + values provided. + """ + + def __init__( + self, + endpoint: str, + values: t.Mapping[str, t.Any], + method: t.Optional[str], + adapter: t.Optional["MapAdapter"] = None, + ) -> None: + super().__init__(endpoint, values, method) + self.endpoint = endpoint + self.values = values + self.method = method + self.adapter = adapter + + @cached_property + def suggested(self) -> t.Optional["Rule"]: + return self.closest_rule(self.adapter) + + def closest_rule(self, adapter: t.Optional["MapAdapter"]) -> t.Optional["Rule"]: + def _score_rule(rule: "Rule") -> float: + return sum( + [ + 0.98 + * difflib.SequenceMatcher( + None, rule.endpoint, self.endpoint + ).ratio(), + 0.01 * bool(set(self.values or ()).issubset(rule.arguments)), + 0.01 * bool(rule.methods and self.method in rule.methods), + ] + ) + + if adapter and adapter.map._rules: + return max(adapter.map._rules, key=_score_rule) + + return None + + def __str__(self) -> str: + message = [f"Could not build url for endpoint {self.endpoint!r}"] + if self.method: + message.append(f" ({self.method!r})") + if self.values: + message.append(f" with values {sorted(self.values)!r}") + message.append(".") + if self.suggested: + if self.endpoint == self.suggested.endpoint: + if ( + self.method + and self.suggested.methods is not None + and self.method not in self.suggested.methods + ): + message.append( + " Did you mean to use methods" + f" {sorted(self.suggested.methods)!r}?" + ) + missing_values = self.suggested.arguments.union( + set(self.suggested.defaults or ()) + ) - set(self.values.keys()) + if missing_values: + message.append( + f" Did you forget to specify values {sorted(missing_values)!r}?" + ) + else: + message.append(f" Did you mean {self.suggested.endpoint!r} instead?") + return "".join(message) + + +class WebsocketMismatch(BadRequest): + """The only matched rule is either a WebSocket and the request is + HTTP, or the rule is HTTP and the request is a WebSocket. + """ + + +class NoMatch(Exception): + __slots__ = ("have_match_for", "websocket_mismatch") + + def __init__(self, have_match_for: t.Set[str], websocket_mismatch: bool) -> None: + self.have_match_for = have_match_for + self.websocket_mismatch = websocket_mismatch diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/map.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/map.py new file mode 100644 index 00000000..daf94b6a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/map.py @@ -0,0 +1,944 @@ +import posixpath +import typing as t +import warnings +from pprint import pformat +from threading import Lock + +from .._internal import _encode_idna +from .._internal import _get_environ +from .._internal import _to_str +from .._internal import _wsgi_decoding_dance +from ..datastructures import ImmutableDict +from ..datastructures import MultiDict +from ..exceptions import BadHost +from ..exceptions import HTTPException +from ..exceptions import MethodNotAllowed +from ..exceptions import NotFound +from ..urls import url_encode +from ..urls import url_join +from ..urls import url_quote +from ..wsgi import get_host +from .converters import DEFAULT_CONVERTERS +from .exceptions import BuildError +from .exceptions import NoMatch +from .exceptions import RequestAliasRedirect +from .exceptions import RequestPath +from .exceptions import RequestRedirect +from .exceptions import WebsocketMismatch +from .matcher import StateMachineMatcher +from .rules import _simple_rule_re +from .rules import Rule + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from .converters import BaseConverter + from .rules import RuleFactory + from ..wrappers.request import Request + + +class Map: + """The map class stores all the URL rules and some configuration + parameters. Some of the configuration values are only stored on the + `Map` instance since those affect all rules, others are just defaults + and can be overridden for each rule. Note that you have to specify all + arguments besides the `rules` as keyword arguments! + + :param rules: sequence of url rules for this map. + :param default_subdomain: The default subdomain for rules without a + subdomain defined. + :param charset: charset of the url. defaults to ``"utf-8"`` + :param strict_slashes: If a rule ends with a slash but the matched + URL does not, redirect to the URL with a trailing slash. + :param merge_slashes: Merge consecutive slashes when matching or + building URLs. Matches will redirect to the normalized URL. + Slashes in variable parts are not merged. + :param redirect_defaults: This will redirect to the default rule if it + wasn't visited that way. This helps creating + unique URLs. + :param converters: A dict of converters that adds additional converters + to the list of converters. If you redefine one + converter this will override the original one. + :param sort_parameters: If set to `True` the url parameters are sorted. + See `url_encode` for more details. + :param sort_key: The sort key function for `url_encode`. + :param encoding_errors: the error method to use for decoding + :param host_matching: if set to `True` it enables the host matching + feature and disables the subdomain one. If + enabled the `host` parameter to rules is used + instead of the `subdomain` one. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules + will match. + + .. versionchanged:: 1.0 + Added ``merge_slashes``. + + .. versionchanged:: 0.7 + Added ``encoding_errors`` and ``host_matching``. + + .. versionchanged:: 0.5 + Added ``sort_parameters`` and ``sort_key``. + """ + + #: A dict of default converters to be used. + default_converters = ImmutableDict(DEFAULT_CONVERTERS) + + #: The type of lock to use when updating. + #: + #: .. versionadded:: 1.0 + lock_class = Lock + + def __init__( + self, + rules: t.Optional[t.Iterable["RuleFactory"]] = None, + default_subdomain: str = "", + charset: str = "utf-8", + strict_slashes: bool = True, + merge_slashes: bool = True, + redirect_defaults: bool = True, + converters: t.Optional[t.Mapping[str, t.Type["BaseConverter"]]] = None, + sort_parameters: bool = False, + sort_key: t.Optional[t.Callable[[t.Any], t.Any]] = None, + encoding_errors: str = "replace", + host_matching: bool = False, + ) -> None: + self._matcher = StateMachineMatcher(merge_slashes) + self._rules_by_endpoint: t.Dict[str, t.List[Rule]] = {} + self._remap = True + self._remap_lock = self.lock_class() + + self.default_subdomain = default_subdomain + self.charset = charset + self.encoding_errors = encoding_errors + self.strict_slashes = strict_slashes + self.merge_slashes = merge_slashes + self.redirect_defaults = redirect_defaults + self.host_matching = host_matching + + self.converters = self.default_converters.copy() + if converters: + self.converters.update(converters) + + self.sort_parameters = sort_parameters + self.sort_key = sort_key + + for rulefactory in rules or (): + self.add(rulefactory) + + def is_endpoint_expecting(self, endpoint: str, *arguments: str) -> bool: + """Iterate over all rules and check if the endpoint expects + the arguments provided. This is for example useful if you have + some URLs that expect a language code and others that do not and + you want to wrap the builder a bit so that the current language + code is automatically added if not provided but endpoints expect + it. + + :param endpoint: the endpoint to check. + :param arguments: this function accepts one or more arguments + as positional arguments. Each one of them is + checked. + """ + self.update() + arguments = set(arguments) + for rule in self._rules_by_endpoint[endpoint]: + if arguments.issubset(rule.arguments): + return True + return False + + @property + def _rules(self) -> t.List[Rule]: + return [rule for rules in self._rules_by_endpoint.values() for rule in rules] + + def iter_rules(self, endpoint: t.Optional[str] = None) -> t.Iterator[Rule]: + """Iterate over all rules or the rules of an endpoint. + + :param endpoint: if provided only the rules for that endpoint + are returned. + :return: an iterator + """ + self.update() + if endpoint is not None: + return iter(self._rules_by_endpoint[endpoint]) + return iter(self._rules) + + def add(self, rulefactory: "RuleFactory") -> None: + """Add a new rule or factory to the map and bind it. Requires that the + rule is not bound to another map. + + :param rulefactory: a :class:`Rule` or :class:`RuleFactory` + """ + for rule in rulefactory.get_rules(self): + rule.bind(self) + if not rule.build_only: + self._matcher.add(rule) + self._rules_by_endpoint.setdefault(rule.endpoint, []).append(rule) + self._remap = True + + def bind( + self, + server_name: str, + script_name: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + url_scheme: str = "http", + default_method: str = "GET", + path_info: t.Optional[str] = None, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + ) -> "MapAdapter": + """Return a new :class:`MapAdapter` with the details specified to the + call. Note that `script_name` will default to ``'/'`` if not further + specified or `None`. The `server_name` at least is a requirement + because the HTTP RFC requires absolute URLs for redirects and so all + redirect exceptions raised by Werkzeug will contain the full canonical + URL. + + If no path_info is passed to :meth:`match` it will use the default path + info passed to bind. While this doesn't really make sense for + manual bind calls, it's useful if you bind a map to a WSGI + environment which already contains the path info. + + `subdomain` will default to the `default_subdomain` for this map if + no defined. If there is no `default_subdomain` you cannot use the + subdomain feature. + + .. versionchanged:: 1.0 + If ``url_scheme`` is ``ws`` or ``wss``, only WebSocket rules + will match. + + .. versionchanged:: 0.15 + ``path_info`` defaults to ``'/'`` if ``None``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionchanged:: 0.7 + Added ``query_args``. + """ + server_name = server_name.lower() + if self.host_matching: + if subdomain is not None: + raise RuntimeError("host matching enabled and a subdomain was provided") + elif subdomain is None: + subdomain = self.default_subdomain + if script_name is None: + script_name = "/" + if path_info is None: + path_info = "/" + + try: + server_name = _encode_idna(server_name) # type: ignore + except UnicodeError as e: + raise BadHost() from e + + return MapAdapter( + self, + server_name, + script_name, + subdomain, + url_scheme, + path_info, + default_method, + query_args, + ) + + def bind_to_environ( + self, + environ: t.Union["WSGIEnvironment", "Request"], + server_name: t.Optional[str] = None, + subdomain: t.Optional[str] = None, + ) -> "MapAdapter": + """Like :meth:`bind` but you can pass it an WSGI environment and it + will fetch the information from that dictionary. Note that because of + limitations in the protocol there is no way to get the current + subdomain and real `server_name` from the environment. If you don't + provide it, Werkzeug will use `SERVER_NAME` and `SERVER_PORT` (or + `HTTP_HOST` if provided) as used `server_name` with disabled subdomain + feature. + + If `subdomain` is `None` but an environment and a server name is + provided it will calculate the current subdomain automatically. + Example: `server_name` is ``'example.com'`` and the `SERVER_NAME` + in the wsgi `environ` is ``'staging.dev.example.com'`` the calculated + subdomain will be ``'staging.dev'``. + + If the object passed as environ has an environ attribute, the value of + this attribute is used instead. This allows you to pass request + objects. Additionally `PATH_INFO` added as a default of the + :class:`MapAdapter` so that you don't have to pass the path info to + the match method. + + .. versionchanged:: 1.0.0 + If the passed server name specifies port 443, it will match + if the incoming scheme is ``https`` without a port. + + .. versionchanged:: 1.0.0 + A warning is shown when the passed server name does not + match the incoming WSGI server name. + + .. versionchanged:: 0.8 + This will no longer raise a ValueError when an unexpected server + name was passed. + + .. versionchanged:: 0.5 + previously this method accepted a bogus `calculate_subdomain` + parameter that did not have any effect. It was removed because + of that. + + :param environ: a WSGI environment. + :param server_name: an optional server name hint (see above). + :param subdomain: optionally the current subdomain (see above). + """ + env = _get_environ(environ) + wsgi_server_name = get_host(env).lower() + scheme = env["wsgi.url_scheme"] + upgrade = any( + v.strip() == "upgrade" + for v in env.get("HTTP_CONNECTION", "").lower().split(",") + ) + + if upgrade and env.get("HTTP_UPGRADE", "").lower() == "websocket": + scheme = "wss" if scheme == "https" else "ws" + + if server_name is None: + server_name = wsgi_server_name + else: + server_name = server_name.lower() + + # strip standard port to match get_host() + if scheme in {"http", "ws"} and server_name.endswith(":80"): + server_name = server_name[:-3] + elif scheme in {"https", "wss"} and server_name.endswith(":443"): + server_name = server_name[:-4] + + if subdomain is None and not self.host_matching: + cur_server_name = wsgi_server_name.split(".") + real_server_name = server_name.split(".") + offset = -len(real_server_name) + + if cur_server_name[offset:] != real_server_name: + # This can happen even with valid configs if the server was + # accessed directly by IP address under some situations. + # Instead of raising an exception like in Werkzeug 0.7 or + # earlier we go by an invalid subdomain which will result + # in a 404 error on matching. + warnings.warn( + f"Current server name {wsgi_server_name!r} doesn't match configured" + f" server name {server_name!r}", + stacklevel=2, + ) + subdomain = "" + else: + subdomain = ".".join(filter(None, cur_server_name[:offset])) + + def _get_wsgi_string(name: str) -> t.Optional[str]: + val = env.get(name) + if val is not None: + return _wsgi_decoding_dance(val, self.charset) + return None + + script_name = _get_wsgi_string("SCRIPT_NAME") + path_info = _get_wsgi_string("PATH_INFO") + query_args = _get_wsgi_string("QUERY_STRING") + return Map.bind( + self, + server_name, + script_name, + subdomain, + scheme, + env["REQUEST_METHOD"], + path_info, + query_args=query_args, + ) + + def update(self) -> None: + """Called before matching and building to keep the compiled rules + in the correct order after things changed. + """ + if not self._remap: + return + + with self._remap_lock: + if not self._remap: + return + + self._matcher.update() + for rules in self._rules_by_endpoint.values(): + rules.sort(key=lambda x: x.build_compare_key()) + self._remap = False + + def __repr__(self) -> str: + rules = self.iter_rules() + return f"{type(self).__name__}({pformat(list(rules))})" + + +class MapAdapter: + + """Returned by :meth:`Map.bind` or :meth:`Map.bind_to_environ` and does + the URL matching and building based on runtime information. + """ + + def __init__( + self, + map: Map, + server_name: str, + script_name: str, + subdomain: t.Optional[str], + url_scheme: str, + path_info: str, + default_method: str, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + ): + self.map = map + self.server_name = _to_str(server_name) + script_name = _to_str(script_name) + if not script_name.endswith("/"): + script_name += "/" + self.script_name = script_name + self.subdomain = _to_str(subdomain) + self.url_scheme = _to_str(url_scheme) + self.path_info = _to_str(path_info) + self.default_method = _to_str(default_method) + self.query_args = query_args + self.websocket = self.url_scheme in {"ws", "wss"} + + def dispatch( + self, + view_func: t.Callable[[str, t.Mapping[str, t.Any]], "WSGIApplication"], + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + catch_http_exceptions: bool = False, + ) -> "WSGIApplication": + """Does the complete dispatching process. `view_func` is called with + the endpoint and a dict with the values for the view. It should + look up the view function, call it, and return a response object + or WSGI application. http exceptions are not caught by default + so that applications can display nicer error messages by just + catching them by hand. If you want to stick with the default + error messages you can pass it ``catch_http_exceptions=True`` and + it will catch the http exceptions. + + Here a small example for the dispatch usage:: + + from werkzeug.wrappers import Request, Response + from werkzeug.wsgi import responder + from werkzeug.routing import Map, Rule + + def on_index(request): + return Response('Hello from the index') + + url_map = Map([Rule('/', endpoint='index')]) + views = {'index': on_index} + + @responder + def application(environ, start_response): + request = Request(environ) + urls = url_map.bind_to_environ(environ) + return urls.dispatch(lambda e, v: views[e](request, **v), + catch_http_exceptions=True) + + Keep in mind that this method might return exception objects, too, so + use :class:`Response.force_type` to get a response object. + + :param view_func: a function that is called with the endpoint as + first argument and the value dict as second. Has + to dispatch to the actual view function with this + information. (see above) + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param catch_http_exceptions: set to `True` to catch any of the + werkzeug :class:`HTTPException`\\s. + """ + try: + try: + endpoint, args = self.match(path_info, method) + except RequestRedirect as e: + return e + return view_func(endpoint, args) + except HTTPException as e: + if catch_http_exceptions: + return e + raise + + @t.overload + def match( # type: ignore + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: "te.Literal[False]" = False, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[str, t.Mapping[str, t.Any]]: + ... + + @t.overload + def match( + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: "te.Literal[True]" = True, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[Rule, t.Mapping[str, t.Any]]: + ... + + def match( + self, + path_info: t.Optional[str] = None, + method: t.Optional[str] = None, + return_rule: bool = False, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + websocket: t.Optional[bool] = None, + ) -> t.Tuple[t.Union[str, Rule], t.Mapping[str, t.Any]]: + """The usage is simple: you just pass the match method the current + path info as well as the method (which defaults to `GET`). The + following things can then happen: + + - you receive a `NotFound` exception that indicates that no URL is + matching. A `NotFound` exception is also a WSGI application you + can call to get a default page not found page (happens to be the + same object as `werkzeug.exceptions.NotFound`) + + - you receive a `MethodNotAllowed` exception that indicates that there + is a match for this URL but not for the current request method. + This is useful for RESTful applications. + + - you receive a `RequestRedirect` exception with a `new_url` + attribute. This exception is used to notify you about a request + Werkzeug requests from your WSGI application. This is for example the + case if you request ``/foo`` although the correct URL is ``/foo/`` + You can use the `RequestRedirect` instance as response-like object + similar to all other subclasses of `HTTPException`. + + - you receive a ``WebsocketMismatch`` exception if the only + match is a WebSocket rule but the bind is an HTTP request, or + if the match is an HTTP rule but the bind is a WebSocket + request. + + - you get a tuple in the form ``(endpoint, arguments)`` if there is + a match (unless `return_rule` is True, in which case you get a tuple + in the form ``(rule, arguments)``) + + If the path info is not passed to the match method the default path + info of the map is used (defaults to the root URL if not defined + explicitly). + + All of the exceptions raised are subclasses of `HTTPException` so they + can be used as WSGI responses. They will all render generic error or + redirect pages. + + Here is a small example for matching: + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.match("/", "GET") + ('index', {}) + >>> urls.match("/downloads/42") + ('downloads/show', {'id': 42}) + + And here is what happens on redirect and missing URLs: + + >>> urls.match("/downloads") + Traceback (most recent call last): + ... + RequestRedirect: http://example.com/downloads/ + >>> urls.match("/missing") + Traceback (most recent call last): + ... + NotFound: 404 Not Found + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + :param return_rule: return the rule that matched instead of just the + endpoint (defaults to `False`). + :param query_args: optional query arguments that are used for + automatic redirects as string or dictionary. It's + currently not possible to use the query arguments + for URL matching. + :param websocket: Match WebSocket instead of HTTP requests. A + websocket request has a ``ws`` or ``wss`` + :attr:`url_scheme`. This overrides that detection. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionchanged:: 0.8 + ``query_args`` can be a string. + + .. versionadded:: 0.7 + Added ``query_args``. + + .. versionadded:: 0.6 + Added ``return_rule``. + """ + self.map.update() + if path_info is None: + path_info = self.path_info + else: + path_info = _to_str(path_info, self.map.charset) + if query_args is None: + query_args = self.query_args or {} + method = (method or self.default_method).upper() + + if websocket is None: + websocket = self.websocket + + domain_part = self.server_name if self.map.host_matching else self.subdomain + path_part = f"/{path_info.lstrip('/')}" if path_info else "" + + try: + result = self.map._matcher.match(domain_part, path_part, method, websocket) + except RequestPath as e: + raise RequestRedirect( + self.make_redirect_url( + url_quote(e.path_info, self.map.charset, safe="/:|+"), + query_args, + ) + ) from None + except RequestAliasRedirect as e: + raise RequestRedirect( + self.make_alias_redirect_url( + f"{domain_part}|{path_part}", + e.endpoint, + e.matched_values, + method, + query_args, + ) + ) from None + except NoMatch as e: + if e.have_match_for: + raise MethodNotAllowed(valid_methods=list(e.have_match_for)) from None + + if e.websocket_mismatch: + raise WebsocketMismatch() from None + + raise NotFound() from None + else: + rule, rv = result + + if self.map.redirect_defaults: + redirect_url = self.get_default_redirect(rule, method, rv, query_args) + if redirect_url is not None: + raise RequestRedirect(redirect_url) + + if rule.redirect_to is not None: + if isinstance(rule.redirect_to, str): + + def _handle_match(match: t.Match[str]) -> str: + value = rv[match.group(1)] + return rule._converters[match.group(1)].to_url(value) + + redirect_url = _simple_rule_re.sub(_handle_match, rule.redirect_to) + else: + redirect_url = rule.redirect_to(self, **rv) + + if self.subdomain: + netloc = f"{self.subdomain}.{self.server_name}" + else: + netloc = self.server_name + + raise RequestRedirect( + url_join( + f"{self.url_scheme or 'http'}://{netloc}{self.script_name}", + redirect_url, + ) + ) + + if return_rule: + return rule, rv + else: + return rule.endpoint, rv + + def test( + self, path_info: t.Optional[str] = None, method: t.Optional[str] = None + ) -> bool: + """Test if a rule would match. Works like `match` but returns `True` + if the URL matches, or `False` if it does not exist. + + :param path_info: the path info to use for matching. Overrides the + path info specified on binding. + :param method: the HTTP method used for matching. Overrides the + method specified on binding. + """ + try: + self.match(path_info, method) + except RequestRedirect: + pass + except HTTPException: + return False + return True + + def allowed_methods(self, path_info: t.Optional[str] = None) -> t.Iterable[str]: + """Returns the valid methods that match for a given path. + + .. versionadded:: 0.7 + """ + try: + self.match(path_info, method="--") + except MethodNotAllowed as e: + return e.valid_methods # type: ignore + except HTTPException: + pass + return [] + + def get_host(self, domain_part: t.Optional[str]) -> str: + """Figures out the full host name for the given domain part. The + domain part is a subdomain in case host matching is disabled or + a full host name. + """ + if self.map.host_matching: + if domain_part is None: + return self.server_name + return _to_str(domain_part, "ascii") + subdomain = domain_part + if subdomain is None: + subdomain = self.subdomain + else: + subdomain = _to_str(subdomain, "ascii") + + if subdomain: + return f"{subdomain}.{self.server_name}" + else: + return self.server_name + + def get_default_redirect( + self, + rule: Rule, + method: str, + values: t.MutableMapping[str, t.Any], + query_args: t.Union[t.Mapping[str, t.Any], str], + ) -> t.Optional[str]: + """A helper that returns the URL to redirect to if it finds one. + This is used for default redirecting only. + + :internal: + """ + assert self.map.redirect_defaults + for r in self.map._rules_by_endpoint[rule.endpoint]: + # every rule that comes after this one, including ourself + # has a lower priority for the defaults. We order the ones + # with the highest priority up for building. + if r is rule: + break + if r.provides_defaults_for(rule) and r.suitable_for(values, method): + values.update(r.defaults) # type: ignore + domain_part, path = r.build(values) # type: ignore + return self.make_redirect_url(path, query_args, domain_part=domain_part) + return None + + def encode_query_args(self, query_args: t.Union[t.Mapping[str, t.Any], str]) -> str: + if not isinstance(query_args, str): + return url_encode(query_args, self.map.charset) + return query_args + + def make_redirect_url( + self, + path_info: str, + query_args: t.Optional[t.Union[t.Mapping[str, t.Any], str]] = None, + domain_part: t.Optional[str] = None, + ) -> str: + """Creates a redirect URL. + + :internal: + """ + if query_args: + suffix = f"?{self.encode_query_args(query_args)}" + else: + suffix = "" + + scheme = self.url_scheme or "http" + host = self.get_host(domain_part) + path = posixpath.join(self.script_name.strip("/"), path_info.lstrip("/")) + return f"{scheme}://{host}/{path}{suffix}" + + def make_alias_redirect_url( + self, + path: str, + endpoint: str, + values: t.Mapping[str, t.Any], + method: str, + query_args: t.Union[t.Mapping[str, t.Any], str], + ) -> str: + """Internally called to make an alias redirect URL.""" + url = self.build( + endpoint, values, method, append_unknown=False, force_external=True + ) + if query_args: + url += f"?{self.encode_query_args(query_args)}" + assert url != path, "detected invalid alias setting. No canonical URL found" + return url + + def _partial_build( + self, + endpoint: str, + values: t.Mapping[str, t.Any], + method: t.Optional[str], + append_unknown: bool, + ) -> t.Optional[t.Tuple[str, str, bool]]: + """Helper for :meth:`build`. Returns subdomain and path for the + rule that accepts this endpoint, values and method. + + :internal: + """ + # in case the method is none, try with the default method first + if method is None: + rv = self._partial_build( + endpoint, values, self.default_method, append_unknown + ) + if rv is not None: + return rv + + # Default method did not match or a specific method is passed. + # Check all for first match with matching host. If no matching + # host is found, go with first result. + first_match = None + + for rule in self.map._rules_by_endpoint.get(endpoint, ()): + if rule.suitable_for(values, method): + build_rv = rule.build(values, append_unknown) + + if build_rv is not None: + rv = (build_rv[0], build_rv[1], rule.websocket) + if self.map.host_matching: + if rv[0] == self.server_name: + return rv + elif first_match is None: + first_match = rv + else: + return rv + + return first_match + + def build( + self, + endpoint: str, + values: t.Optional[t.Mapping[str, t.Any]] = None, + method: t.Optional[str] = None, + force_external: bool = False, + append_unknown: bool = True, + url_scheme: t.Optional[str] = None, + ) -> str: + """Building URLs works pretty much the other way round. Instead of + `match` you call `build` and pass it the endpoint and a dict of + arguments for the placeholders. + + The `build` function also accepts an argument called `force_external` + which, if you set it to `True` will force external URLs. Per default + external URLs (include the server name) will only be used if the + target URL is on a different subdomain. + + >>> m = Map([ + ... Rule('/', endpoint='index'), + ... Rule('/downloads/', endpoint='downloads/index'), + ... Rule('/downloads/', endpoint='downloads/show') + ... ]) + >>> urls = m.bind("example.com", "/") + >>> urls.build("index", {}) + '/' + >>> urls.build("downloads/show", {'id': 42}) + '/downloads/42' + >>> urls.build("downloads/show", {'id': 42}, force_external=True) + 'http://example.com/downloads/42' + + Because URLs cannot contain non ASCII data you will always get + bytes back. Non ASCII characters are urlencoded with the + charset defined on the map instance. + + Additional values are converted to strings and appended to the URL as + URL querystring parameters: + + >>> urls.build("index", {'q': 'My Searchstring'}) + '/?q=My+Searchstring' + + When processing those additional values, lists are furthermore + interpreted as multiple values (as per + :py:class:`werkzeug.datastructures.MultiDict`): + + >>> urls.build("index", {'q': ['a', 'b', 'c']}) + '/?q=a&q=b&q=c' + + Passing a ``MultiDict`` will also add multiple values: + + >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 'b')))) + '/?p=z&q=a&q=b' + + If a rule does not exist when building a `BuildError` exception is + raised. + + The build method accepts an argument called `method` which allows you + to specify the method you want to have an URL built for if you have + different methods for the same endpoint specified. + + :param endpoint: the endpoint of the URL to build. + :param values: the values for the URL to build. Unhandled values are + appended to the URL as query parameters. + :param method: the HTTP method for the rule if there are different + URLs for different methods on the same endpoint. + :param force_external: enforce full canonical external URLs. If the URL + scheme is not provided, this will generate + a protocol-relative URL. + :param append_unknown: unknown parameters are appended to the generated + URL as query string argument. Disable this + if you want the builder to ignore those. + :param url_scheme: Scheme to use in place of the bound + :attr:`url_scheme`. + + .. versionchanged:: 2.0 + Added the ``url_scheme`` parameter. + + .. versionadded:: 0.6 + Added the ``append_unknown`` parameter. + """ + self.map.update() + + if values: + if isinstance(values, MultiDict): + values = { + k: (v[0] if len(v) == 1 else v) + for k, v in dict.items(values) + if len(v) != 0 + } + else: # plain dict + values = {k: v for k, v in values.items() if v is not None} + else: + values = {} + + rv = self._partial_build(endpoint, values, method, append_unknown) + if rv is None: + raise BuildError(endpoint, values, method, self) + + domain_part, path, websocket = rv + host = self.get_host(domain_part) + + if url_scheme is None: + url_scheme = self.url_scheme + + # Always build WebSocket routes with the scheme (browsers + # require full URLs). If bound to a WebSocket, ensure that HTTP + # routes are built with an HTTP scheme. + secure = url_scheme in {"https", "wss"} + + if websocket: + force_external = True + url_scheme = "wss" if secure else "ws" + elif url_scheme: + url_scheme = "https" if secure else "http" + + # shortcut this. + if not force_external and ( + (self.map.host_matching and host == self.server_name) + or (not self.map.host_matching and domain_part == self.subdomain) + ): + return f"{self.script_name.rstrip('/')}/{path.lstrip('/')}" + + scheme = f"{url_scheme}:" if url_scheme else "" + return f"{scheme}//{host}{self.script_name[:-1]}/{path.lstrip('/')}" diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/matcher.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/matcher.py new file mode 100644 index 00000000..05370c3e --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/matcher.py @@ -0,0 +1,192 @@ +import re +import typing as t +from dataclasses import dataclass +from dataclasses import field + +from .converters import ValidationError +from .exceptions import NoMatch +from .exceptions import RequestAliasRedirect +from .exceptions import RequestPath +from .rules import Rule +from .rules import RulePart + + +class SlashRequired(Exception): + pass + + +@dataclass +class State: + """A representation of a rule state. + + This includes the *rules* that correspond to the state and the + possible *static* and *dynamic* transitions to the next state. + """ + + dynamic: t.List[t.Tuple[RulePart, "State"]] = field(default_factory=list) + rules: t.List[Rule] = field(default_factory=list) + static: t.Dict[str, "State"] = field(default_factory=dict) + + +class StateMachineMatcher: + def __init__(self, merge_slashes: bool) -> None: + self._root = State() + self.merge_slashes = merge_slashes + + def add(self, rule: Rule) -> None: + state = self._root + for part in rule._parts: + if part.static: + state.static.setdefault(part.content, State()) + state = state.static[part.content] + else: + for test_part, new_state in state.dynamic: + if test_part == part: + state = new_state + break + else: + new_state = State() + state.dynamic.append((part, new_state)) + state = new_state + state.rules.append(rule) + + def update(self) -> None: + # For every state the dynamic transitions should be sorted by + # the weight of the transition + state = self._root + + def _update_state(state: State) -> None: + state.dynamic.sort(key=lambda entry: entry[0].weight) + for new_state in state.static.values(): + _update_state(new_state) + for _, new_state in state.dynamic: + _update_state(new_state) + + _update_state(state) + + def match( + self, domain: str, path: str, method: str, websocket: bool + ) -> t.Tuple[Rule, t.MutableMapping[str, t.Any]]: + # To match to a rule we need to start at the root state and + # try to follow the transitions until we find a match, or find + # there is no transition to follow. + + have_match_for = set() + websocket_mismatch = False + + def _match( + state: State, parts: t.List[str], values: t.List[str] + ) -> t.Optional[t.Tuple[Rule, t.List[str]]]: + # This function is meant to be called recursively, and will attempt + # to match the head part to the state's transitions. + nonlocal have_match_for, websocket_mismatch + + # The base case is when all parts have been matched via + # transitions. Hence if there is a rule with methods & + # websocket that work return it and the dynamic values + # extracted. + if parts == []: + for rule in state.rules: + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + elif rule.websocket != websocket: + websocket_mismatch = True + else: + return rule, values + + # Test if there is a match with this path with a + # trailing slash, if so raise an exception to report + # that matching is possible with an additional slash + if "" in state.static: + for rule in state.static[""].rules: + if websocket == rule.websocket and ( + rule.methods is None or method in rule.methods + ): + if rule.strict_slashes: + raise SlashRequired() + else: + return rule, values + return None + + part = parts[0] + # To match this part try the static transitions first + if part in state.static: + rv = _match(state.static[part], parts[1:], values) + if rv is not None: + return rv + # No match via the static transitions, so try the dynamic + # ones. + for test_part, new_state in state.dynamic: + target = part + remaining = parts[1:] + # A final part indicates a transition that always + # consumes the remaining parts i.e. transitions to a + # final state. + if test_part.final: + target = "/".join(parts) + remaining = [] + match = re.compile(test_part.content).match(target) + if match is not None: + groups = list(match.groups()) + if test_part.suffixed: + # If a part_isolating=False part has a slash suffix, remove the + # suffix from the match and check for the slash redirect next. + suffix = groups.pop() + if suffix == "/": + remaining = [""] + rv = _match(new_state, remaining, values + groups) + if rv is not None: + return rv + + # If there is no match and the only part left is a + # trailing slash ("") consider rules that aren't + # strict-slashes as these should match if there is a final + # slash part. + if parts == [""]: + for rule in state.rules: + if rule.strict_slashes: + continue + if rule.methods is not None and method not in rule.methods: + have_match_for.update(rule.methods) + elif rule.websocket != websocket: + websocket_mismatch = True + else: + return rule, values + + return None + + try: + rv = _match(self._root, [domain, *path.split("/")], []) + except SlashRequired: + raise RequestPath(f"{path}/") from None + + if self.merge_slashes and rv is None: + # Try to match again, but with slashes merged + path = re.sub("/{2,}?", "/", path) + try: + rv = _match(self._root, [domain, *path.split("/")], []) + except SlashRequired: + raise RequestPath(f"{path}/") from None + if rv is None: + raise NoMatch(have_match_for, websocket_mismatch) + else: + raise RequestPath(f"{path}") + elif rv is not None: + rule, values = rv + + result = {} + for name, value in zip(rule._converters.keys(), values): + try: + value = rule._converters[name].to_python(value) + except ValidationError: + raise NoMatch(have_match_for, websocket_mismatch) from None + result[str(name)] = value + if rule.defaults: + result.update(rule.defaults) + + if rule.alias and rule.map.redirect_defaults: + raise RequestAliasRedirect(result, rule.endpoint) + + return rule, result + + raise NoMatch(have_match_for, websocket_mismatch) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/rules.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/rules.py new file mode 100644 index 00000000..7b37890a --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/routing/rules.py @@ -0,0 +1,904 @@ +import ast +import re +import typing as t +from dataclasses import dataclass +from string import Template +from types import CodeType + +from .._internal import _to_bytes +from ..urls import url_encode +from ..urls import url_quote +from .converters import ValidationError + +if t.TYPE_CHECKING: + from .converters import BaseConverter + from .map import Map + + +class Weighting(t.NamedTuple): + number_static_weights: int + static_weights: t.List[t.Tuple[int, int]] + number_argument_weights: int + argument_weights: t.List[int] + + +@dataclass +class RulePart: + """A part of a rule. + + Rules can be represented by parts as delimited by `/` with + instances of this class representing those parts. The *content* is + either the raw content if *static* or a regex string to match + against. The *weight* can be used to order parts when matching. + + """ + + content: str + final: bool + static: bool + suffixed: bool + weight: Weighting + + +_part_re = re.compile( + r""" + (?: + (?P\/) # a slash + | + (?P[^<\/]+) # static rule data + | + (?: + < + (?: + (?P[a-zA-Z_][a-zA-Z0-9_]*) # converter name + (?:\((?P.*?)\))? # converter arguments + \: # variable delimiter + )? + (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name + > + ) + ) + """, + re.VERBOSE, +) + +_simple_rule_re = re.compile(r"<([^>]+)>") +_converter_args_re = re.compile( + r""" + ((?P\w+)\s*=\s*)? + (?P + True|False| + \d+.\d+| + \d+.| + \d+| + [\w\d_.]+| + [urUR]?(?P"[^"]*?"|'[^']*') + )\s*, + """, + re.VERBOSE, +) + + +_PYTHON_CONSTANTS = {"None": None, "True": True, "False": False} + + +def _find(value: str, target: str, pos: int) -> int: + """Find the *target* in *value* after *pos*. + + Returns the *value* length if *target* isn't found. + """ + try: + return value.index(target, pos) + except ValueError: + return len(value) + + +def _pythonize(value: str) -> t.Union[None, bool, int, float, str]: + if value in _PYTHON_CONSTANTS: + return _PYTHON_CONSTANTS[value] + for convert in int, float: + try: + return convert(value) # type: ignore + except ValueError: + pass + if value[:1] == value[-1:] and value[0] in "\"'": + value = value[1:-1] + return str(value) + + +def parse_converter_args(argstr: str) -> t.Tuple[t.Tuple, t.Dict[str, t.Any]]: + argstr += "," + args = [] + kwargs = {} + + for item in _converter_args_re.finditer(argstr): + value = item.group("stringval") + if value is None: + value = item.group("value") + value = _pythonize(value) + if not item.group("name"): + args.append(value) + else: + name = item.group("name") + kwargs[name] = value + + return tuple(args), kwargs + + +class RuleFactory: + """As soon as you have more complex URL setups it's a good idea to use rule + factories to avoid repetitive tasks. Some of them are builtin, others can + be added by subclassing `RuleFactory` and overriding `get_rules`. + """ + + def get_rules(self, map: "Map") -> t.Iterable["Rule"]: + """Subclasses of `RuleFactory` have to override this method and return + an iterable of rules.""" + raise NotImplementedError() + + +class Subdomain(RuleFactory): + """All URLs provided by this factory have the subdomain set to a + specific domain. For example if you want to use the subdomain for + the current language this can be a good setup:: + + url_map = Map([ + Rule('/', endpoint='#select_language'), + Subdomain('', [ + Rule('/', endpoint='index'), + Rule('/about', endpoint='about'), + Rule('/help', endpoint='help') + ]) + ]) + + All the rules except for the ``'#select_language'`` endpoint will now + listen on a two letter long subdomain that holds the language code + for the current request. + """ + + def __init__(self, subdomain: str, rules: t.Iterable[RuleFactory]) -> None: + self.subdomain = subdomain + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.subdomain = self.subdomain + yield rule + + +class Submount(RuleFactory): + """Like `Subdomain` but prefixes the URL rule with a given string:: + + url_map = Map([ + Rule('/', endpoint='index'), + Submount('/blog', [ + Rule('/', endpoint='blog/index'), + Rule('/entry/', endpoint='blog/show') + ]) + ]) + + Now the rule ``'blog/show'`` matches ``/blog/entry/``. + """ + + def __init__(self, path: str, rules: t.Iterable[RuleFactory]) -> None: + self.path = path.rstrip("/") + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.rule = self.path + rule.rule + yield rule + + +class EndpointPrefix(RuleFactory): + """Prefixes all endpoints (which must be strings for this factory) with + another string. This can be useful for sub applications:: + + url_map = Map([ + Rule('/', endpoint='index'), + EndpointPrefix('blog/', [Submount('/blog', [ + Rule('/', endpoint='index'), + Rule('/entry/', endpoint='show') + ])]) + ]) + """ + + def __init__(self, prefix: str, rules: t.Iterable[RuleFactory]) -> None: + self.prefix = prefix + self.rules = rules + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + rule = rule.empty() + rule.endpoint = self.prefix + rule.endpoint + yield rule + + +class RuleTemplate: + """Returns copies of the rules wrapped and expands string templates in + the endpoint, rule, defaults or subdomain sections. + + Here a small example for such a rule template:: + + from werkzeug.routing import Map, Rule, RuleTemplate + + resource = RuleTemplate([ + Rule('/$name/', endpoint='$name.list'), + Rule('/$name/', endpoint='$name.show') + ]) + + url_map = Map([resource(name='user'), resource(name='page')]) + + When a rule template is called the keyword arguments are used to + replace the placeholders in all the string parameters. + """ + + def __init__(self, rules: t.Iterable["Rule"]) -> None: + self.rules = list(rules) + + def __call__(self, *args: t.Any, **kwargs: t.Any) -> "RuleTemplateFactory": + return RuleTemplateFactory(self.rules, dict(*args, **kwargs)) + + +class RuleTemplateFactory(RuleFactory): + """A factory that fills in template variables into rules. Used by + `RuleTemplate` internally. + + :internal: + """ + + def __init__( + self, rules: t.Iterable[RuleFactory], context: t.Dict[str, t.Any] + ) -> None: + self.rules = rules + self.context = context + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + for rulefactory in self.rules: + for rule in rulefactory.get_rules(map): + new_defaults = subdomain = None + if rule.defaults: + new_defaults = {} + for key, value in rule.defaults.items(): + if isinstance(value, str): + value = Template(value).substitute(self.context) + new_defaults[key] = value + if rule.subdomain is not None: + subdomain = Template(rule.subdomain).substitute(self.context) + new_endpoint = rule.endpoint + if isinstance(new_endpoint, str): + new_endpoint = Template(new_endpoint).substitute(self.context) + yield Rule( + Template(rule.rule).substitute(self.context), + new_defaults, + subdomain, + rule.methods, + rule.build_only, + new_endpoint, + rule.strict_slashes, + ) + + +def _prefix_names(src: str) -> ast.stmt: + """ast parse and prefix names with `.` to avoid collision with user vars""" + tree = ast.parse(src).body[0] + if isinstance(tree, ast.Expr): + tree = tree.value # type: ignore + for node in ast.walk(tree): + if isinstance(node, ast.Name): + node.id = f".{node.id}" + return tree + + +_CALL_CONVERTER_CODE_FMT = "self._converters[{elem!r}].to_url()" +_IF_KWARGS_URL_ENCODE_CODE = """\ +if kwargs: + params = self._encode_query_vars(kwargs) + q = "?" if params else "" +else: + q = params = "" +""" +_IF_KWARGS_URL_ENCODE_AST = _prefix_names(_IF_KWARGS_URL_ENCODE_CODE) +_URL_ENCODE_AST_NAMES = (_prefix_names("q"), _prefix_names("params")) + + +class Rule(RuleFactory): + """A Rule represents one URL pattern. There are some options for `Rule` + that change the way it behaves and are passed to the `Rule` constructor. + Note that besides the rule-string all arguments *must* be keyword arguments + in order to not break the application on Werkzeug upgrades. + + `string` + Rule strings basically are just normal URL paths with placeholders in + the format ```` where the converter and the + arguments are optional. If no converter is defined the `default` + converter is used which means `string` in the normal configuration. + + URL rules that end with a slash are branch URLs, others are leaves. + If you have `strict_slashes` enabled (which is the default), all + branch URLs that are matched without a trailing slash will trigger a + redirect to the same URL with the missing slash appended. + + The converters are defined on the `Map`. + + `endpoint` + The endpoint for this rule. This can be anything. A reference to a + function, a string, a number etc. The preferred way is using a string + because the endpoint is used for URL generation. + + `defaults` + An optional dict with defaults for other rules with the same endpoint. + This is a bit tricky but useful if you want to have unique URLs:: + + url_map = Map([ + Rule('/all/', defaults={'page': 1}, endpoint='all_entries'), + Rule('/all/page/', endpoint='all_entries') + ]) + + If a user now visits ``http://example.com/all/page/1`` they will be + redirected to ``http://example.com/all/``. If `redirect_defaults` is + disabled on the `Map` instance this will only affect the URL + generation. + + `subdomain` + The subdomain rule string for this rule. If not specified the rule + only matches for the `default_subdomain` of the map. If the map is + not bound to a subdomain this feature is disabled. + + Can be useful if you want to have user profiles on different subdomains + and all subdomains are forwarded to your application:: + + url_map = Map([ + Rule('/', subdomain='', endpoint='user/homepage'), + Rule('/stats', subdomain='', endpoint='user/stats') + ]) + + `methods` + A sequence of http methods this rule applies to. If not specified, all + methods are allowed. For example this can be useful if you want different + endpoints for `POST` and `GET`. If methods are defined and the path + matches but the method matched against is not in this list or in the + list of another rule for that path the error raised is of the type + `MethodNotAllowed` rather than `NotFound`. If `GET` is present in the + list of methods and `HEAD` is not, `HEAD` is added automatically. + + `strict_slashes` + Override the `Map` setting for `strict_slashes` only for this rule. If + not specified the `Map` setting is used. + + `merge_slashes` + Override :attr:`Map.merge_slashes` for this rule. + + `build_only` + Set this to True and the rule will never match but will create a URL + that can be build. This is useful if you have resources on a subdomain + or folder that are not handled by the WSGI application (like static data) + + `redirect_to` + If given this must be either a string or callable. In case of a + callable it's called with the url adapter that triggered the match and + the values of the URL as keyword arguments and has to return the target + for the redirect, otherwise it has to be a string with placeholders in + rule syntax:: + + def foo_with_slug(adapter, id): + # ask the database for the slug for the old id. this of + # course has nothing to do with werkzeug. + return f'foo/{Foo.get_slug_for_id(id)}' + + url_map = Map([ + Rule('/foo/', endpoint='foo'), + Rule('/some/old/url/', redirect_to='foo/'), + Rule('/other/old/url/', redirect_to=foo_with_slug) + ]) + + When the rule is matched the routing system will raise a + `RequestRedirect` exception with the target for the redirect. + + Keep in mind that the URL will be joined against the URL root of the + script so don't use a leading slash on the target URL unless you + really mean root of that domain. + + `alias` + If enabled this rule serves as an alias for another rule with the same + endpoint and arguments. + + `host` + If provided and the URL map has host matching enabled this can be + used to provide a match rule for the whole host. This also means + that the subdomain feature is disabled. + + `websocket` + If ``True``, this rule is only matches for WebSocket (``ws://``, + ``wss://``) requests. By default, rules will only match for HTTP + requests. + + .. versionchanged:: 2.1 + Percent-encoded newlines (``%0a``), which are decoded by WSGI + servers, are considered when routing instead of terminating the + match early. + + .. versionadded:: 1.0 + Added ``websocket``. + + .. versionadded:: 1.0 + Added ``merge_slashes``. + + .. versionadded:: 0.7 + Added ``alias`` and ``host``. + + .. versionchanged:: 0.6.1 + ``HEAD`` is added to ``methods`` if ``GET`` is present. + """ + + def __init__( + self, + string: str, + defaults: t.Optional[t.Mapping[str, t.Any]] = None, + subdomain: t.Optional[str] = None, + methods: t.Optional[t.Iterable[str]] = None, + build_only: bool = False, + endpoint: t.Optional[str] = None, + strict_slashes: t.Optional[bool] = None, + merge_slashes: t.Optional[bool] = None, + redirect_to: t.Optional[t.Union[str, t.Callable[..., str]]] = None, + alias: bool = False, + host: t.Optional[str] = None, + websocket: bool = False, + ) -> None: + if not string.startswith("/"): + raise ValueError("urls must start with a leading slash") + self.rule = string + self.is_leaf = not string.endswith("/") + self.is_branch = string.endswith("/") + + self.map: "Map" = None # type: ignore + self.strict_slashes = strict_slashes + self.merge_slashes = merge_slashes + self.subdomain = subdomain + self.host = host + self.defaults = defaults + self.build_only = build_only + self.alias = alias + self.websocket = websocket + + if methods is not None: + if isinstance(methods, str): + raise TypeError("'methods' should be a list of strings.") + + methods = {x.upper() for x in methods} + + if "HEAD" not in methods and "GET" in methods: + methods.add("HEAD") + + if websocket and methods - {"GET", "HEAD", "OPTIONS"}: + raise ValueError( + "WebSocket rules can only use 'GET', 'HEAD', and 'OPTIONS' methods." + ) + + self.methods = methods + self.endpoint: str = endpoint # type: ignore + self.redirect_to = redirect_to + + if defaults: + self.arguments = set(map(str, defaults)) + else: + self.arguments = set() + + self._converters: t.Dict[str, "BaseConverter"] = {} + self._trace: t.List[t.Tuple[bool, str]] = [] + self._parts: t.List[RulePart] = [] + + def empty(self) -> "Rule": + """ + Return an unbound copy of this rule. + + This can be useful if want to reuse an already bound URL for another + map. See ``get_empty_kwargs`` to override what keyword arguments are + provided to the new copy. + """ + return type(self)(self.rule, **self.get_empty_kwargs()) + + def get_empty_kwargs(self) -> t.Mapping[str, t.Any]: + """ + Provides kwargs for instantiating empty copy with empty() + + Use this method to provide custom keyword arguments to the subclass of + ``Rule`` when calling ``some_rule.empty()``. Helpful when the subclass + has custom keyword arguments that are needed at instantiation. + + Must return a ``dict`` that will be provided as kwargs to the new + instance of ``Rule``, following the initial ``self.rule`` value which + is always provided as the first, required positional argument. + """ + defaults = None + if self.defaults: + defaults = dict(self.defaults) + return dict( + defaults=defaults, + subdomain=self.subdomain, + methods=self.methods, + build_only=self.build_only, + endpoint=self.endpoint, + strict_slashes=self.strict_slashes, + redirect_to=self.redirect_to, + alias=self.alias, + host=self.host, + ) + + def get_rules(self, map: "Map") -> t.Iterator["Rule"]: + yield self + + def refresh(self) -> None: + """Rebinds and refreshes the URL. Call this if you modified the + rule in place. + + :internal: + """ + self.bind(self.map, rebind=True) + + def bind(self, map: "Map", rebind: bool = False) -> None: + """Bind the url to a map and create a regular expression based on + the information from the rule itself and the defaults from the map. + + :internal: + """ + if self.map is not None and not rebind: + raise RuntimeError(f"url rule {self!r} already bound to map {self.map!r}") + self.map = map + if self.strict_slashes is None: + self.strict_slashes = map.strict_slashes + if self.merge_slashes is None: + self.merge_slashes = map.merge_slashes + if self.subdomain is None: + self.subdomain = map.default_subdomain + self.compile() + + def get_converter( + self, + variable_name: str, + converter_name: str, + args: t.Tuple, + kwargs: t.Mapping[str, t.Any], + ) -> "BaseConverter": + """Looks up the converter for the given parameter. + + .. versionadded:: 0.9 + """ + if converter_name not in self.map.converters: + raise LookupError(f"the converter {converter_name!r} does not exist") + return self.map.converters[converter_name](self.map, *args, **kwargs) + + def _encode_query_vars(self, query_vars: t.Mapping[str, t.Any]) -> str: + return url_encode( + query_vars, + charset=self.map.charset, + sort=self.map.sort_parameters, + key=self.map.sort_key, + ) + + def _parse_rule(self, rule: str) -> t.Iterable[RulePart]: + content = "" + static = True + argument_weights = [] + static_weights: t.List[t.Tuple[int, int]] = [] + final = False + + pos = 0 + while pos < len(rule): + match = _part_re.match(rule, pos) + if match is None: + raise ValueError(f"malformed url rule: {rule!r}") + + data = match.groupdict() + if data["static"] is not None: + static_weights.append((len(static_weights), -len(data["static"]))) + self._trace.append((False, data["static"])) + content += data["static"] if static else re.escape(data["static"]) + + if data["variable"] is not None: + if static: + # Switching content to represent regex, hence the need to escape + content = re.escape(content) + static = False + c_args, c_kwargs = parse_converter_args(data["arguments"] or "") + convobj = self.get_converter( + data["variable"], data["converter"] or "default", c_args, c_kwargs + ) + self._converters[data["variable"]] = convobj + self.arguments.add(data["variable"]) + if not convobj.part_isolating: + final = True + content += f"({convobj.regex})" + argument_weights.append(convobj.weight) + self._trace.append((True, data["variable"])) + + if data["slash"] is not None: + self._trace.append((False, "/")) + if final: + content += "/" + else: + if not static: + content += r"\Z" + weight = Weighting( + -len(static_weights), + static_weights, + -len(argument_weights), + argument_weights, + ) + yield RulePart( + content=content, + final=final, + static=static, + suffixed=False, + weight=weight, + ) + content = "" + static = True + argument_weights = [] + static_weights = [] + final = False + + pos = match.end() + + suffixed = False + if final and content[-1] == "/": + # If a converter is part_isolating=False (matches slashes) and ends with a + # slash, augment the regex to support slash redirects. + suffixed = True + content = content[:-1] + "(? None: + """Compiles the regular expression and stores it.""" + assert self.map is not None, "rule not bound" + + if self.map.host_matching: + domain_rule = self.host or "" + else: + domain_rule = self.subdomain or "" + self._parts = [] + self._trace = [] + self._converters = {} + if domain_rule == "": + self._parts = [ + RulePart( + content="", + final=False, + static=True, + suffixed=False, + weight=Weighting(0, [], 0, []), + ) + ] + else: + self._parts.extend(self._parse_rule(domain_rule)) + self._trace.append((False, "|")) + rule = self.rule + if self.merge_slashes: + rule = re.sub("/{2,}?", "/", self.rule) + self._parts.extend(self._parse_rule(rule)) + + self._build: t.Callable[..., t.Tuple[str, str]] + self._build = self._compile_builder(False).__get__(self, None) + self._build_unknown: t.Callable[..., t.Tuple[str, str]] + self._build_unknown = self._compile_builder(True).__get__(self, None) + + @staticmethod + def _get_func_code(code: CodeType, name: str) -> t.Callable[..., t.Tuple[str, str]]: + globs: t.Dict[str, t.Any] = {} + locs: t.Dict[str, t.Any] = {} + exec(code, globs, locs) + return locs[name] # type: ignore + + def _compile_builder( + self, append_unknown: bool = True + ) -> t.Callable[..., t.Tuple[str, str]]: + defaults = self.defaults or {} + dom_ops: t.List[t.Tuple[bool, str]] = [] + url_ops: t.List[t.Tuple[bool, str]] = [] + + opl = dom_ops + for is_dynamic, data in self._trace: + if data == "|" and opl is dom_ops: + opl = url_ops + continue + # this seems like a silly case to ever come up but: + # if a default is given for a value that appears in the rule, + # resolve it to a constant ahead of time + if is_dynamic and data in defaults: + data = self._converters[data].to_url(defaults[data]) + opl.append((False, data)) + elif not is_dynamic: + opl.append( + (False, url_quote(_to_bytes(data, self.map.charset), safe="/:|+")) + ) + else: + opl.append((True, data)) + + def _convert(elem: str) -> ast.stmt: + ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem)) + ret.args = [ast.Name(str(elem), ast.Load())] # type: ignore # str for py2 + return ret + + def _parts(ops: t.List[t.Tuple[bool, str]]) -> t.List[ast.AST]: + parts = [ + _convert(elem) if is_dynamic else ast.Str(s=elem) + for is_dynamic, elem in ops + ] + parts = parts or [ast.Str("")] + # constant fold + ret = [parts[0]] + for p in parts[1:]: + if isinstance(p, ast.Str) and isinstance(ret[-1], ast.Str): + ret[-1] = ast.Str(ret[-1].s + p.s) + else: + ret.append(p) + return ret + + dom_parts = _parts(dom_ops) + url_parts = _parts(url_ops) + if not append_unknown: + body = [] + else: + body = [_IF_KWARGS_URL_ENCODE_AST] + url_parts.extend(_URL_ENCODE_AST_NAMES) + + def _join(parts: t.List[ast.AST]) -> ast.AST: + if len(parts) == 1: # shortcut + return parts[0] + return ast.JoinedStr(parts) + + body.append( + ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())) + ) + + pargs = [ + elem + for is_dynamic, elem in dom_ops + url_ops + if is_dynamic and elem not in defaults + ] + kargs = [str(k) for k in defaults] + + func_ast: ast.FunctionDef = _prefix_names("def _(): pass") # type: ignore + func_ast.name = f"" + func_ast.args.args.append(ast.arg(".self", None)) + for arg in pargs + kargs: + func_ast.args.args.append(ast.arg(arg, None)) + func_ast.args.kwarg = ast.arg(".kwargs", None) + for _ in kargs: + func_ast.args.defaults.append(ast.Str("")) + func_ast.body = body + + # use `ast.parse` instead of `ast.Module` for better portability + # Python 3.8 changes the signature of `ast.Module` + module = ast.parse("") + module.body = [func_ast] + + # mark everything as on line 1, offset 0 + # less error-prone than `ast.fix_missing_locations` + # bad line numbers cause an assert to fail in debug builds + for node in ast.walk(module): + if "lineno" in node._attributes: + node.lineno = 1 + if "end_lineno" in node._attributes: + node.end_lineno = node.lineno # type: ignore[attr-defined] + if "col_offset" in node._attributes: + node.col_offset = 0 + if "end_col_offset" in node._attributes: + node.end_col_offset = node.col_offset # type: ignore[attr-defined] + + code = compile(module, "", "exec") + return self._get_func_code(code, func_ast.name) + + def build( + self, values: t.Mapping[str, t.Any], append_unknown: bool = True + ) -> t.Optional[t.Tuple[str, str]]: + """Assembles the relative url for that rule and the subdomain. + If building doesn't work for some reasons `None` is returned. + + :internal: + """ + try: + if append_unknown: + return self._build_unknown(**values) + else: + return self._build(**values) + except ValidationError: + return None + + def provides_defaults_for(self, rule: "Rule") -> bool: + """Check if this rule has defaults for a given rule. + + :internal: + """ + return bool( + not self.build_only + and self.defaults + and self.endpoint == rule.endpoint + and self != rule + and self.arguments == rule.arguments + ) + + def suitable_for( + self, values: t.Mapping[str, t.Any], method: t.Optional[str] = None + ) -> bool: + """Check if the dict of values has enough data for url generation. + + :internal: + """ + # if a method was given explicitly and that method is not supported + # by this rule, this rule is not suitable. + if ( + method is not None + and self.methods is not None + and method not in self.methods + ): + return False + + defaults = self.defaults or () + + # all arguments required must be either in the defaults dict or + # the value dictionary otherwise it's not suitable + for key in self.arguments: + if key not in defaults and key not in values: + return False + + # in case defaults are given we ensure that either the value was + # skipped or the value is the same as the default value. + if defaults: + for key, value in defaults.items(): + if key in values and value != values[key]: + return False + + return True + + def build_compare_key(self) -> t.Tuple[int, int, int]: + """The build compare key for sorting. + + :internal: + """ + return (1 if self.alias else 0, -len(self.arguments), -len(self.defaults or ())) + + def __eq__(self, other: object) -> bool: + return isinstance(other, type(self)) and self._trace == other._trace + + __hash__ = None # type: ignore + + def __str__(self) -> str: + return self.rule + + def __repr__(self) -> str: + if self.map is None: + return f"<{type(self).__name__} (unbound)>" + parts = [] + for is_dynamic, data in self._trace: + if is_dynamic: + parts.append(f"<{data}>") + else: + parts.append(data) + parts = "".join(parts).lstrip("|") + methods = f" ({', '.join(self.methods)})" if self.methods is not None else "" + return f"<{type(self).__name__} {parts!r}{methods} -> {self.endpoint}>" diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__init__.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..ea179bcf Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/http.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/http.cpython-310.pyc new file mode 100644 index 00000000..d667eecf Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/http.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-310.pyc new file mode 100644 index 00000000..51cf8940 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/request.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/request.cpython-310.pyc new file mode 100644 index 00000000..1b780784 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/request.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/response.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/response.cpython-310.pyc new file mode 100644 index 00000000..893b037b Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/response.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/utils.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/utils.cpython-310.pyc new file mode 100644 index 00000000..8ae072bb Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/__pycache__/utils.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/http.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/http.py new file mode 100644 index 00000000..6b227383 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/http.py @@ -0,0 +1,136 @@ +import re +import typing as t +from datetime import datetime + +from .._internal import _cookie_parse_impl +from .._internal import _dt_as_utc +from .._internal import _to_str +from ..http import generate_etag +from ..http import parse_date +from ..http import parse_etags +from ..http import parse_if_range_header +from ..http import unquote_etag + +_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)') + + +def is_resource_modified( + http_range: t.Optional[str] = None, + http_if_range: t.Optional[str] = None, + http_if_modified_since: t.Optional[str] = None, + http_if_none_match: t.Optional[str] = None, + http_if_match: t.Optional[str] = None, + etag: t.Optional[str] = None, + data: t.Optional[bytes] = None, + last_modified: t.Optional[t.Union[datetime, str]] = None, + ignore_if_range: bool = True, +) -> bool: + """Convenience method for conditional requests. + :param http_range: Range HTTP header + :param http_if_range: If-Range HTTP header + :param http_if_modified_since: If-Modified-Since HTTP header + :param http_if_none_match: If-None-Match HTTP header + :param http_if_match: If-Match HTTP header + :param etag: the etag for the response for comparison. + :param data: or alternatively the data of the response to automatically + generate an etag using :func:`generate_etag`. + :param last_modified: an optional date of the last modification. + :param ignore_if_range: If `False`, `If-Range` header will be taken into + account. + :return: `True` if the resource was modified, otherwise `False`. + + .. versionadded:: 2.2 + """ + if etag is None and data is not None: + etag = generate_etag(data) + elif data is not None: + raise TypeError("both data and etag given") + + unmodified = False + if isinstance(last_modified, str): + last_modified = parse_date(last_modified) + + # HTTP doesn't use microsecond, remove it to avoid false positive + # comparisons. Mark naive datetimes as UTC. + if last_modified is not None: + last_modified = _dt_as_utc(last_modified.replace(microsecond=0)) + + if_range = None + if not ignore_if_range and http_range is not None: + # https://tools.ietf.org/html/rfc7233#section-3.2 + # A server MUST ignore an If-Range header field received in a request + # that does not contain a Range header field. + if_range = parse_if_range_header(http_if_range) + + if if_range is not None and if_range.date is not None: + modified_since: t.Optional[datetime] = if_range.date + else: + modified_since = parse_date(http_if_modified_since) + + if modified_since and last_modified and last_modified <= modified_since: + unmodified = True + + if etag: + etag, _ = unquote_etag(etag) + etag = t.cast(str, etag) + + if if_range is not None and if_range.etag is not None: + unmodified = parse_etags(if_range.etag).contains(etag) + else: + if_none_match = parse_etags(http_if_none_match) + if if_none_match: + # https://tools.ietf.org/html/rfc7232#section-3.2 + # "A recipient MUST use the weak comparison function when comparing + # entity-tags for If-None-Match" + unmodified = if_none_match.contains_weak(etag) + + # https://tools.ietf.org/html/rfc7232#section-3.1 + # "Origin server MUST use the strong comparison function when + # comparing entity-tags for If-Match" + if_match = parse_etags(http_if_match) + if if_match: + unmodified = not if_match.is_strong(etag) + + return not unmodified + + +def parse_cookie( + cookie: t.Union[bytes, str, None] = "", + charset: str = "utf-8", + errors: str = "replace", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, +) -> "ds.MultiDict[str, str]": + """Parse a cookie from a string. + + The same key can be provided multiple times, the values are stored + in-order. The default :class:`MultiDict` will have the first value + first, and all values can be retrieved with + :meth:`MultiDict.getlist`. + + :param cookie: The cookie header as a string. + :param charset: The charset for the cookie values. + :param errors: The error behavior for the charset decoding. + :param cls: A dict-like class to store the parsed cookies in. + Defaults to :class:`MultiDict`. + + .. versionadded:: 2.2 + """ + # PEP 3333 sends headers through the environ as latin1 decoded + # strings. Encode strings back to bytes for parsing. + if isinstance(cookie, str): + cookie = cookie.encode("latin1", "replace") + + if cls is None: + cls = ds.MultiDict + + def _parse_pairs() -> t.Iterator[t.Tuple[str, str]]: + for key, val in _cookie_parse_impl(cookie): # type: ignore + key_str = _to_str(key, charset, errors, allow_none_charset=True) + val_str = _to_str(val, charset, errors, allow_none_charset=True) + yield key_str, val_str + + return cls(_parse_pairs()) + + +# circular dependencies +from .. import datastructures as ds diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/multipart.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/multipart.py new file mode 100644 index 00000000..2684e5dd --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/multipart.py @@ -0,0 +1,287 @@ +import re +from dataclasses import dataclass +from enum import auto +from enum import Enum +from typing import cast +from typing import List +from typing import Optional +from typing import Tuple + +from .._internal import _to_bytes +from .._internal import _to_str +from ..datastructures import Headers +from ..exceptions import RequestEntityTooLarge +from ..http import parse_options_header + + +class Event: + pass + + +@dataclass(frozen=True) +class Preamble(Event): + data: bytes + + +@dataclass(frozen=True) +class Field(Event): + name: str + headers: Headers + + +@dataclass(frozen=True) +class File(Event): + name: str + filename: str + headers: Headers + + +@dataclass(frozen=True) +class Data(Event): + data: bytes + more_data: bool + + +@dataclass(frozen=True) +class Epilogue(Event): + data: bytes + + +class NeedData(Event): + pass + + +NEED_DATA = NeedData() + + +class State(Enum): + PREAMBLE = auto() + PART = auto() + DATA = auto() + EPILOGUE = auto() + COMPLETE = auto() + + +# Multipart line breaks MUST be CRLF (\r\n) by RFC-7578, except that +# many implementations break this and either use CR or LF alone. +LINE_BREAK = b"(?:\r\n|\n|\r)" +BLANK_LINE_RE = re.compile(b"(?:\r\n\r\n|\r\r|\n\n)", re.MULTILINE) +LINE_BREAK_RE = re.compile(LINE_BREAK, re.MULTILINE) +# Header values can be continued via a space or tab after the linebreak, as +# per RFC2231 +HEADER_CONTINUATION_RE = re.compile(b"%s[ \t]" % LINE_BREAK, re.MULTILINE) +# This must be long enough to contain any line breaks plus any +# additional boundary markers (--) such that they will be found in a +# subsequent search +SEARCH_EXTRA_LENGTH = 8 + + +class MultipartDecoder: + """Decodes a multipart message as bytes into Python events. + + The part data is returned as available to allow the caller to save + the data from memory to disk, if desired. + """ + + def __init__( + self, + boundary: bytes, + max_form_memory_size: Optional[int] = None, + *, + max_parts: Optional[int] = None, + ) -> None: + self.buffer = bytearray() + self.complete = False + self.max_form_memory_size = max_form_memory_size + self.max_parts = max_parts + self.state = State.PREAMBLE + self.boundary = boundary + + # Note in the below \h i.e. horizontal whitespace is used + # as [^\S\n\r] as \h isn't supported in python. + + # The preamble must end with a boundary where the boundary is + # prefixed by a line break, RFC2046. Except that many + # implementations including Werkzeug's tests omit the line + # break prefix. In addition the first boundary could be the + # epilogue boundary (for empty form-data) hence the matching + # group to understand if it is an epilogue boundary. + self.preamble_re = re.compile( + rb"%s?--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + # A boundary must include a line break prefix and suffix, and + # may include trailing whitespace. In addition the boundary + # could be the epilogue boundary hence the matching group to + # understand if it is an epilogue boundary. + self.boundary_re = re.compile( + rb"%s--%s(--[^\S\n\r]*%s?|[^\S\n\r]*%s)" + % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK), + re.MULTILINE, + ) + self._search_position = 0 + self._parts_decoded = 0 + + def last_newline(self) -> int: + try: + last_nl = self.buffer.rindex(b"\n") + except ValueError: + last_nl = len(self.buffer) + try: + last_cr = self.buffer.rindex(b"\r") + except ValueError: + last_cr = len(self.buffer) + + return min(last_nl, last_cr) + + def receive_data(self, data: Optional[bytes]) -> None: + if data is None: + self.complete = True + elif ( + self.max_form_memory_size is not None + and len(self.buffer) + len(data) > self.max_form_memory_size + ): + raise RequestEntityTooLarge() + else: + self.buffer.extend(data) + + def next_event(self) -> Event: + event: Event = NEED_DATA + + if self.state == State.PREAMBLE: + match = self.preamble_re.search(self.buffer, self._search_position) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data = bytes(self.buffer[: match.start()]) + del self.buffer[: match.end()] + event = Preamble(data=data) + self._search_position = 0 + else: + # Update the search start position to be equal to the + # current buffer length (already searched) minus a + # safe buffer for part of the search target. + self._search_position = max( + 0, len(self.buffer) - len(self.boundary) - SEARCH_EXTRA_LENGTH + ) + + elif self.state == State.PART: + match = BLANK_LINE_RE.search(self.buffer, self._search_position) + if match is not None: + headers = self._parse_headers(self.buffer[: match.start()]) + del self.buffer[: match.end()] + + if "content-disposition" not in headers: + raise ValueError("Missing Content-Disposition header") + + disposition, extra = parse_options_header( + headers["content-disposition"] + ) + name = cast(str, extra.get("name")) + filename = extra.get("filename") + if filename is not None: + event = File( + filename=filename, + headers=headers, + name=name, + ) + else: + event = Field( + headers=headers, + name=name, + ) + self.state = State.DATA + self._search_position = 0 + self._parts_decoded += 1 + + if self.max_parts is not None and self._parts_decoded > self.max_parts: + raise RequestEntityTooLarge() + else: + # Update the search start position to be equal to the + # current buffer length (already searched) minus a + # safe buffer for part of the search target. + self._search_position = max(0, len(self.buffer) - SEARCH_EXTRA_LENGTH) + + elif self.state == State.DATA: + if self.buffer.find(b"--" + self.boundary) == -1: + # No complete boundary in the buffer, but there may be + # a partial boundary at the end. As the boundary + # starts with either a nl or cr find the earliest and + # return up to that as data. + data_length = del_index = self.last_newline() + more_data = True + else: + match = self.boundary_re.search(self.buffer) + if match is not None: + if match.group(1).startswith(b"--"): + self.state = State.EPILOGUE + else: + self.state = State.PART + data_length = match.start() + del_index = match.end() + else: + data_length = del_index = self.last_newline() + more_data = match is None + + data = bytes(self.buffer[:data_length]) + del self.buffer[:del_index] + if data or not more_data: + event = Data(data=data, more_data=more_data) + + elif self.state == State.EPILOGUE and self.complete: + event = Epilogue(data=bytes(self.buffer)) + del self.buffer[:] + self.state = State.COMPLETE + + if self.complete and isinstance(event, NeedData): + raise ValueError(f"Invalid form-data cannot parse beyond {self.state}") + + return event + + def _parse_headers(self, data: bytes) -> Headers: + headers: List[Tuple[str, str]] = [] + # Merge the continued headers into one line + data = HEADER_CONTINUATION_RE.sub(b" ", data) + # Now there is one header per line + for line in data.splitlines(): + if line.strip() != b"": + name, value = _to_str(line).strip().split(":", 1) + headers.append((name.strip(), value.strip())) + return Headers(headers) + + +class MultipartEncoder: + def __init__(self, boundary: bytes) -> None: + self.boundary = boundary + self.state = State.PREAMBLE + + def send_event(self, event: Event) -> bytes: + if isinstance(event, Preamble) and self.state == State.PREAMBLE: + self.state = State.PART + return event.data + elif isinstance(event, (Field, File)) and self.state in { + State.PREAMBLE, + State.PART, + State.DATA, + }: + self.state = State.DATA + data = b"\r\n--" + self.boundary + b"\r\n" + data += b'Content-Disposition: form-data; name="%s"' % _to_bytes(event.name) + if isinstance(event, File): + data += b'; filename="%s"' % _to_bytes(event.filename) + data += b"\r\n" + for name, value in cast(Field, event).headers: + if name.lower() != "content-disposition": + data += _to_bytes(f"{name}: {value}\r\n") + data += b"\r\n" + return data + elif isinstance(event, Data) and self.state == State.DATA: + return event.data + elif isinstance(event, Epilogue): + self.state = State.COMPLETE + return b"\r\n--" + self.boundary + b"--\r\n" + event.data + else: + raise ValueError(f"Cannot generate {event} in state: {self.state}") diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/request.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/request.py new file mode 100644 index 00000000..8832baaf --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/request.py @@ -0,0 +1,547 @@ +import typing as t +from datetime import datetime + +from .._internal import _to_str +from ..datastructures import Accept +from ..datastructures import Authorization +from ..datastructures import CharsetAccept +from ..datastructures import ETags +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..datastructures import IfRange +from ..datastructures import ImmutableList +from ..datastructures import ImmutableMultiDict +from ..datastructures import LanguageAccept +from ..datastructures import MIMEAccept +from ..datastructures import MultiDict +from ..datastructures import Range +from ..datastructures import RequestCacheControl +from ..http import parse_accept_header +from ..http import parse_authorization_header +from ..http import parse_cache_control_header +from ..http import parse_date +from ..http import parse_etags +from ..http import parse_if_range_header +from ..http import parse_list_header +from ..http import parse_options_header +from ..http import parse_range_header +from ..http import parse_set_header +from ..urls import url_decode +from ..user_agent import UserAgent +from ..utils import cached_property +from ..utils import header_property +from .http import parse_cookie +from .utils import get_current_url +from .utils import get_host + + +class Request: + """Represents the non-IO parts of a HTTP request, including the + method, URL info, and headers. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Request`. + + :param method: The method the request was made with, such as + ``GET``. + :param scheme: The URL scheme of the protocol the request used, such + as ``https`` or ``wss``. + :param server: The address of the server. ``(host, port)``, + ``(path, None)`` for unix sockets, or ``None`` if not known. + :param root_path: The prefix that the application is mounted under. + This is prepended to generated URLs, but is not part of route + matching. + :param path: The path part of the URL after ``root_path``. + :param query_string: The part of the URL after the "?". + :param headers: The headers received with the request. + :param remote_addr: The address of the client sending the request. + + .. versionadded:: 2.0 + """ + + #: The charset used to decode most data in the request. + charset = "utf-8" + + #: the error handling procedure for errors, defaults to 'replace' + encoding_errors = "replace" + + #: the class to use for `args` and `form`. The default is an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` which supports + #: multiple values per key. alternatively it makes sense to use an + #: :class:`~werkzeug.datastructures.ImmutableOrderedMultiDict` which + #: preserves order or a :class:`~werkzeug.datastructures.ImmutableDict` + #: which is the fastest but only remembers the last key. It is also + #: possible to use mutable structures, but this is not recommended. + #: + #: .. versionadded:: 0.6 + parameter_storage_class: t.Type[MultiDict] = ImmutableMultiDict + + #: The type to be used for dict values from the incoming WSGI + #: environment. (For example for :attr:`cookies`.) By default an + #: :class:`~werkzeug.datastructures.ImmutableMultiDict` is used. + #: + #: .. versionchanged:: 1.0.0 + #: Changed to ``ImmutableMultiDict`` to support multiple values. + #: + #: .. versionadded:: 0.6 + dict_storage_class: t.Type[MultiDict] = ImmutableMultiDict + + #: the type to be used for list values from the incoming WSGI environment. + #: By default an :class:`~werkzeug.datastructures.ImmutableList` is used + #: (for example for :attr:`access_list`). + #: + #: .. versionadded:: 0.6 + list_storage_class: t.Type[t.List] = ImmutableList + + user_agent_class: t.Type[UserAgent] = UserAgent + """The class used and returned by the :attr:`user_agent` property to + parse the header. Defaults to + :class:`~werkzeug.user_agent.UserAgent`, which does no parsing. An + extension can provide a subclass that uses a parser to provide other + data. + + .. versionadded:: 2.0 + """ + + #: Valid host names when handling requests. By default all hosts are + #: trusted, which means that whatever the client says the host is + #: will be accepted. + #: + #: Because ``Host`` and ``X-Forwarded-Host`` headers can be set to + #: any value by a malicious client, it is recommended to either set + #: this property or implement similar validation in the proxy (if + #: the application is being run behind one). + #: + #: .. versionadded:: 0.9 + trusted_hosts: t.Optional[t.List[str]] = None + + def __init__( + self, + method: str, + scheme: str, + server: t.Optional[t.Tuple[str, t.Optional[int]]], + root_path: str, + path: str, + query_string: bytes, + headers: Headers, + remote_addr: t.Optional[str], + ) -> None: + #: The method the request was made with, such as ``GET``. + self.method = method.upper() + #: The URL scheme of the protocol the request used, such as + #: ``https`` or ``wss``. + self.scheme = scheme + #: The address of the server. ``(host, port)``, ``(path, None)`` + #: for unix sockets, or ``None`` if not known. + self.server = server + #: The prefix that the application is mounted under, without a + #: trailing slash. :attr:`path` comes after this. + self.root_path = root_path.rstrip("/") + #: The path part of the URL after :attr:`root_path`. This is the + #: path used for routing within the application. + self.path = "/" + path.lstrip("/") + #: The part of the URL after the "?". This is the raw value, use + #: :attr:`args` for the parsed values. + self.query_string = query_string + #: The headers received with the request. + self.headers = headers + #: The address of the client sending the request. + self.remote_addr = remote_addr + + def __repr__(self) -> str: + try: + url = self.url + except Exception as e: + url = f"(invalid URL: {e})" + + return f"<{type(self).__name__} {url!r} [{self.method}]>" + + @property + def url_charset(self) -> str: + """The charset that is assumed for URLs. Defaults to the value + of :attr:`charset`. + + .. versionadded:: 0.6 + """ + return self.charset + + @cached_property + def args(self) -> "MultiDict[str, str]": + """The parsed URL parameters (the part in the URL after the question + mark). + + By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + """ + return url_decode( + self.query_string, + self.url_charset, + errors=self.encoding_errors, + cls=self.parameter_storage_class, + ) + + @cached_property + def access_route(self) -> t.List[str]: + """If a forwarded header exists this is a list of all ip addresses + from the client ip to the last proxy server. + """ + if "X-Forwarded-For" in self.headers: + return self.list_storage_class( + parse_list_header(self.headers["X-Forwarded-For"]) + ) + elif self.remote_addr is not None: + return self.list_storage_class([self.remote_addr]) + return self.list_storage_class() + + @cached_property + def full_path(self) -> str: + """Requested path, including the query string.""" + return f"{self.path}?{_to_str(self.query_string, self.url_charset)}" + + @property + def is_secure(self) -> bool: + """``True`` if the request was made with a secure protocol + (HTTPS or WSS). + """ + return self.scheme in {"https", "wss"} + + @cached_property + def url(self) -> str: + """The full request URL with the scheme, host, root path, path, + and query string.""" + return get_current_url( + self.scheme, self.host, self.root_path, self.path, self.query_string + ) + + @cached_property + def base_url(self) -> str: + """Like :attr:`url` but without the query string.""" + return get_current_url(self.scheme, self.host, self.root_path, self.path) + + @cached_property + def root_url(self) -> str: + """The request URL scheme, host, and root path. This is the root + that the application is accessed from. + """ + return get_current_url(self.scheme, self.host, self.root_path) + + @cached_property + def host_url(self) -> str: + """The request URL scheme and host only.""" + return get_current_url(self.scheme, self.host) + + @cached_property + def host(self) -> str: + """The host name the request was made to, including the port if + it's non-standard. Validated with :attr:`trusted_hosts`. + """ + return get_host( + self.scheme, self.headers.get("host"), self.server, self.trusted_hosts + ) + + @cached_property + def cookies(self) -> "ImmutableMultiDict[str, str]": + """A :class:`dict` with the contents of all cookies transmitted with + the request.""" + wsgi_combined_cookie = ";".join(self.headers.getlist("Cookie")) + return parse_cookie( # type: ignore + wsgi_combined_cookie, + self.charset, + self.encoding_errors, + cls=self.dict_storage_class, + ) + + # Common Descriptors + + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + read_only=True, + ) + + @cached_property + def content_length(self) -> t.Optional[int]: + """The Content-Length entity-header field indicates the size of the + entity-body in bytes or, in the case of the HEAD method, the size of + the entity-body that would have been sent had the request been a + GET. + """ + if self.headers.get("Transfer-Encoding", "") == "chunked": + return None + + content_length = self.headers.get("Content-Length") + if content_length is not None: + try: + return max(0, int(content_length)) + except (ValueError, TypeError): + pass + + return None + + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field. + + .. versionadded:: 0.9""", + read_only=True, + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.) + + .. versionadded:: 0.9""", + read_only=True, + ) + referrer = header_property[str]( + "Referer", + doc="""The Referer[sic] request-header field allows the client + to specify, for the server's benefit, the address (URI) of the + resource from which the Request-URI was obtained (the + "referrer", although the header field is misspelled).""", + read_only=True, + ) + date = header_property( + "Date", + None, + parse_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + read_only=True, + ) + max_forwards = header_property( + "Max-Forwards", + None, + int, + doc="""The Max-Forwards request-header field provides a + mechanism with the TRACE and OPTIONS methods to limit the number + of proxies or gateways that can forward the request to the next + inbound server.""", + read_only=True, + ) + + def _parse_content_type(self) -> None: + if not hasattr(self, "_parsed_content_type"): + self._parsed_content_type = parse_options_header( + self.headers.get("Content-Type", "") + ) + + @property + def mimetype(self) -> str: + """Like :attr:`content_type`, but without parameters (eg, without + charset, type etc.) and always lowercase. For example if the content + type is ``text/HTML; charset=utf-8`` the mimetype would be + ``'text/html'``. + """ + self._parse_content_type() + return self._parsed_content_type[0].lower() + + @property + def mimetype_params(self) -> t.Dict[str, str]: + """The mimetype parameters as dict. For example if the content + type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + """ + self._parse_content_type() + return self._parsed_content_type[1] + + @cached_property + def pragma(self) -> HeaderSet: + """The Pragma general-header field is used to include + implementation-specific directives that might apply to any recipient + along the request/response chain. All pragma directives specify + optional behavior from the viewpoint of the protocol; however, some + systems MAY require that behavior be consistent with the directives. + """ + return parse_set_header(self.headers.get("Pragma", "")) + + # Accept + + @cached_property + def accept_mimetypes(self) -> MIMEAccept: + """List of mimetypes this client supports as + :class:`~werkzeug.datastructures.MIMEAccept` object. + """ + return parse_accept_header(self.headers.get("Accept"), MIMEAccept) + + @cached_property + def accept_charsets(self) -> CharsetAccept: + """List of charsets this client supports as + :class:`~werkzeug.datastructures.CharsetAccept` object. + """ + return parse_accept_header(self.headers.get("Accept-Charset"), CharsetAccept) + + @cached_property + def accept_encodings(self) -> Accept: + """List of encodings this client accepts. Encodings in a HTTP term + are compression encodings such as gzip. For charsets have a look at + :attr:`accept_charset`. + """ + return parse_accept_header(self.headers.get("Accept-Encoding")) + + @cached_property + def accept_languages(self) -> LanguageAccept: + """List of languages this client accepts as + :class:`~werkzeug.datastructures.LanguageAccept` object. + + .. versionchanged 0.5 + In previous versions this was a regular + :class:`~werkzeug.datastructures.Accept` object. + """ + return parse_accept_header(self.headers.get("Accept-Language"), LanguageAccept) + + # ETag + + @cached_property + def cache_control(self) -> RequestCacheControl: + """A :class:`~werkzeug.datastructures.RequestCacheControl` object + for the incoming cache control headers. + """ + cache_control = self.headers.get("Cache-Control") + return parse_cache_control_header(cache_control, None, RequestCacheControl) + + @cached_property + def if_match(self) -> ETags: + """An object containing all the etags in the `If-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-Match")) + + @cached_property + def if_none_match(self) -> ETags: + """An object containing all the etags in the `If-None-Match` header. + + :rtype: :class:`~werkzeug.datastructures.ETags` + """ + return parse_etags(self.headers.get("If-None-Match")) + + @cached_property + def if_modified_since(self) -> t.Optional[datetime]: + """The parsed `If-Modified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Modified-Since")) + + @cached_property + def if_unmodified_since(self) -> t.Optional[datetime]: + """The parsed `If-Unmodified-Since` header as a datetime object. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + return parse_date(self.headers.get("If-Unmodified-Since")) + + @cached_property + def if_range(self) -> IfRange: + """The parsed ``If-Range`` header. + + .. versionchanged:: 2.0 + ``IfRange.date`` is timezone-aware. + + .. versionadded:: 0.7 + """ + return parse_if_range_header(self.headers.get("If-Range")) + + @cached_property + def range(self) -> t.Optional[Range]: + """The parsed `Range` header. + + .. versionadded:: 0.7 + + :rtype: :class:`~werkzeug.datastructures.Range` + """ + return parse_range_header(self.headers.get("Range")) + + # User Agent + + @cached_property + def user_agent(self) -> UserAgent: + """The user agent. Use ``user_agent.string`` to get the header + value. Set :attr:`user_agent_class` to a subclass of + :class:`~werkzeug.user_agent.UserAgent` to provide parsing for + the other properties or other extended data. + + .. versionchanged:: 2.0 + The built in parser is deprecated and will be removed in + Werkzeug 2.1. A ``UserAgent`` subclass must be set to parse + data from the string. + """ + return self.user_agent_class(self.headers.get("User-Agent", "")) + + # Authorization + + @cached_property + def authorization(self) -> t.Optional[Authorization]: + """The `Authorization` object in parsed form.""" + return parse_authorization_header(self.headers.get("Authorization")) + + # CORS + + origin = header_property[str]( + "Origin", + doc=( + "The host that the request originated from. Set" + " :attr:`~CORSResponseMixin.access_control_allow_origin` on" + " the response to indicate which origins are allowed." + ), + read_only=True, + ) + + access_control_request_headers = header_property( + "Access-Control-Request-Headers", + load_func=parse_set_header, + doc=( + "Sent with a preflight request to indicate which headers" + " will be sent with the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_headers`" + " on the response to indicate which headers are allowed." + ), + read_only=True, + ) + + access_control_request_method = header_property[str]( + "Access-Control-Request-Method", + doc=( + "Sent with a preflight request to indicate which method" + " will be used for the cross origin request. Set" + " :attr:`~CORSResponseMixin.access_control_allow_methods`" + " on the response to indicate which methods are allowed." + ), + read_only=True, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/response.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/response.py new file mode 100644 index 00000000..de0bec29 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/response.py @@ -0,0 +1,704 @@ +import typing as t +from datetime import datetime +from datetime import timedelta +from datetime import timezone +from http import HTTPStatus + +from .._internal import _to_str +from ..datastructures import Headers +from ..datastructures import HeaderSet +from ..http import dump_cookie +from ..http import HTTP_STATUS_CODES +from ..utils import get_content_type +from werkzeug.datastructures import CallbackDict +from werkzeug.datastructures import ContentRange +from werkzeug.datastructures import ContentSecurityPolicy +from werkzeug.datastructures import ResponseCacheControl +from werkzeug.datastructures import WWWAuthenticate +from werkzeug.http import COEP +from werkzeug.http import COOP +from werkzeug.http import dump_age +from werkzeug.http import dump_header +from werkzeug.http import dump_options_header +from werkzeug.http import http_date +from werkzeug.http import parse_age +from werkzeug.http import parse_cache_control_header +from werkzeug.http import parse_content_range_header +from werkzeug.http import parse_csp_header +from werkzeug.http import parse_date +from werkzeug.http import parse_options_header +from werkzeug.http import parse_set_header +from werkzeug.http import parse_www_authenticate_header +from werkzeug.http import quote_etag +from werkzeug.http import unquote_etag +from werkzeug.utils import header_property + + +def _set_property(name: str, doc: t.Optional[str] = None) -> property: + def fget(self: "Response") -> HeaderSet: + def on_update(header_set: HeaderSet) -> None: + if not header_set and name in self.headers: + del self.headers[name] + elif header_set: + self.headers[name] = header_set.to_header() + + return parse_set_header(self.headers.get(name), on_update) + + def fset( + self: "Response", + value: t.Optional[ + t.Union[str, t.Dict[str, t.Union[str, int]], t.Iterable[str]] + ], + ) -> None: + if not value: + del self.headers[name] + elif isinstance(value, str): + self.headers[name] = value + else: + self.headers[name] = dump_header(value) + + return property(fget, fset, doc=doc) + + +class Response: + """Represents the non-IO parts of an HTTP response, specifically the + status and headers but not the body. + + This class is not meant for general use. It should only be used when + implementing WSGI, ASGI, or another HTTP application spec. Werkzeug + provides a WSGI implementation at :cls:`werkzeug.wrappers.Response`. + + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + + .. versionadded:: 2.0 + """ + + #: the charset of the response. + charset = "utf-8" + + #: the default status if none is provided. + default_status = 200 + + #: the default mimetype if none is provided. + default_mimetype: t.Optional[str] = "text/plain" + + #: Warn if a cookie header exceeds this size. The default, 4093, should be + #: safely `supported by most browsers `_. A cookie larger than + #: this size will still be sent, but it may be ignored or handled + #: incorrectly by some browsers. Set to 0 to disable this check. + #: + #: .. versionadded:: 0.13 + #: + #: .. _`cookie`: http://browsercookielimits.squawky.net/ + max_cookie_size = 4093 + + # A :class:`Headers` object representing the response headers. + headers: Headers + + def __init__( + self, + status: t.Optional[t.Union[int, str, HTTPStatus]] = None, + headers: t.Optional[ + t.Union[ + t.Mapping[str, t.Union[str, int, t.Iterable[t.Union[str, int]]]], + t.Iterable[t.Tuple[str, t.Union[str, int]]], + ] + ] = None, + mimetype: t.Optional[str] = None, + content_type: t.Optional[str] = None, + ) -> None: + if isinstance(headers, Headers): + self.headers = headers + elif not headers: + self.headers = Headers() + else: + self.headers = Headers(headers) + + if content_type is None: + if mimetype is None and "content-type" not in self.headers: + mimetype = self.default_mimetype + if mimetype is not None: + mimetype = get_content_type(mimetype, self.charset) + content_type = mimetype + if content_type is not None: + self.headers["Content-Type"] = content_type + if status is None: + status = self.default_status + self.status = status # type: ignore + + def __repr__(self) -> str: + return f"<{type(self).__name__} [{self.status}]>" + + @property + def status_code(self) -> int: + """The HTTP status code as a number.""" + return self._status_code + + @status_code.setter + def status_code(self, code: int) -> None: + self.status = code # type: ignore + + @property + def status(self) -> str: + """The HTTP status code as a string.""" + return self._status + + @status.setter + def status(self, value: t.Union[str, int, HTTPStatus]) -> None: + if not isinstance(value, (str, bytes, int, HTTPStatus)): + raise TypeError("Invalid status argument") + + self._status, self._status_code = self._clean_status(value) + + def _clean_status(self, value: t.Union[str, int, HTTPStatus]) -> t.Tuple[str, int]: + if isinstance(value, HTTPStatus): + value = int(value) + status = _to_str(value, self.charset) + split_status = status.split(None, 1) + + if len(split_status) == 0: + raise ValueError("Empty status argument") + + try: + status_code = int(split_status[0]) + except ValueError: + # only message + return f"0 {status}", 0 + + if len(split_status) > 1: + # code and message + return status, status_code + + # only code, look up message + try: + status = f"{status_code} {HTTP_STATUS_CODES[status_code].upper()}" + except KeyError: + status = f"{status_code} UNKNOWN" + + return status, status_code + + def set_cookie( + self, + key: str, + value: str = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: t.Optional[str] = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Sets a cookie. + + A warning is raised if the size of the cookie header exceeds + :attr:`max_cookie_size`, but the header will still be set. + + :param key: the key (name) of the cookie to be set. + :param value: the value of the cookie. + :param max_age: should be a number of seconds, or `None` (default) if + the cookie should last only as long as the client's + browser session. + :param expires: should be a `datetime` object or UNIX timestamp. + :param path: limits the cookie to a given path, per default it will + span the whole domain. + :param domain: if you want to set a cross-domain cookie. For example, + ``domain=".example.com"`` will set a cookie that is + readable by the domain ``www.example.com``, + ``foo.example.com`` etc. Otherwise, a cookie will only + be readable by the domain that set it. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.headers.add( + "Set-Cookie", + dump_cookie( + key, + value=value, + max_age=max_age, + expires=expires, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + charset=self.charset, + max_size=self.max_cookie_size, + samesite=samesite, + ), + ) + + def delete_cookie( + self, + key: str, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Delete a cookie. Fails silently if key doesn't exist. + + :param key: the key (name) of the cookie to be deleted. + :param path: if the cookie that should be deleted was limited to a + path, the path has to be defined here. + :param domain: if the cookie that should be deleted was limited to a + domain, that domain has to be defined here. + :param secure: If ``True``, the cookie will only be available + via HTTPS. + :param httponly: Disallow JavaScript access to the cookie. + :param samesite: Limit the scope of the cookie to only be + attached to requests that are "same-site". + """ + self.set_cookie( + key, + expires=0, + max_age=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + @property + def is_json(self) -> bool: + """Check if the mimetype indicates JSON data, either + :mimetype:`application/json` or :mimetype:`application/*+json`. + """ + mt = self.mimetype + return mt is not None and ( + mt == "application/json" + or mt.startswith("application/") + and mt.endswith("+json") + ) + + # Common Descriptors + + @property + def mimetype(self) -> t.Optional[str]: + """The mimetype (content type without charset etc.)""" + ct = self.headers.get("content-type") + + if ct: + return ct.split(";")[0].strip() + else: + return None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.headers["Content-Type"] = get_content_type(value, self.charset) + + @property + def mimetype_params(self) -> t.Dict[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.5 + """ + + def on_update(d: CallbackDict) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + location = header_property[str]( + "Location", + doc="""The Location response-header field is used to redirect + the recipient to a location other than the Request-URI for + completion of the request or identification of a new + resource.""", + ) + age = header_property( + "Age", + None, + parse_age, + dump_age, # type: ignore + doc="""The Age response-header field conveys the sender's + estimate of the amount of time since the response (or its + revalidation) was generated at the origin server. + + Age values are non-negative decimal integers, representing time + in seconds.""", + ) + content_type = header_property[str]( + "Content-Type", + doc="""The Content-Type entity-header field indicates the media + type of the entity-body sent to the recipient or, in the case of + the HEAD method, the media type that would have been sent had + the request been a GET.""", + ) + content_length = header_property( + "Content-Length", + None, + int, + str, + doc="""The Content-Length entity-header field indicates the size + of the entity-body, in decimal number of OCTETs, sent to the + recipient or, in the case of the HEAD method, the size of the + entity-body that would have been sent had the request been a + GET.""", + ) + content_location = header_property[str]( + "Content-Location", + doc="""The Content-Location entity-header field MAY be used to + supply the resource location for the entity enclosed in the + message when that entity is accessible from a location separate + from the requested resource's URI.""", + ) + content_encoding = header_property[str]( + "Content-Encoding", + doc="""The Content-Encoding entity-header field is used as a + modifier to the media-type. When present, its value indicates + what additional content codings have been applied to the + entity-body, and thus what decoding mechanisms must be applied + in order to obtain the media-type referenced by the Content-Type + header field.""", + ) + content_md5 = header_property[str]( + "Content-MD5", + doc="""The Content-MD5 entity-header field, as defined in + RFC 1864, is an MD5 digest of the entity-body for the purpose of + providing an end-to-end message integrity check (MIC) of the + entity-body. (Note: a MIC is good for detecting accidental + modification of the entity-body in transit, but is not proof + against malicious attacks.)""", + ) + date = header_property( + "Date", + None, + parse_date, + http_date, + doc="""The Date general-header field represents the date and + time at which the message was originated, having the same + semantics as orig-date in RFC 822. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + expires = header_property( + "Expires", + None, + parse_date, + http_date, + doc="""The Expires entity-header field gives the date/time after + which the response is considered stale. A stale cache entry may + not normally be returned by a cache. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + last_modified = header_property( + "Last-Modified", + None, + parse_date, + http_date, + doc="""The Last-Modified entity-header field indicates the date + and time at which the origin server believes the variant was + last modified. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """, + ) + + @property + def retry_after(self) -> t.Optional[datetime]: + """The Retry-After response-header field can be used with a + 503 (Service Unavailable) response to indicate how long the + service is expected to be unavailable to the requesting client. + + Time in seconds until expiration or date. + + .. versionchanged:: 2.0 + The datetime object is timezone-aware. + """ + value = self.headers.get("retry-after") + if value is None: + return None + + try: + seconds = int(value) + except ValueError: + return parse_date(value) + + return datetime.now(timezone.utc) + timedelta(seconds=seconds) + + @retry_after.setter + def retry_after(self, value: t.Optional[t.Union[datetime, int, str]]) -> None: + if value is None: + if "retry-after" in self.headers: + del self.headers["retry-after"] + return + elif isinstance(value, datetime): + value = http_date(value) + else: + value = str(value) + self.headers["Retry-After"] = value + + vary = _set_property( + "Vary", + doc="""The Vary field value indicates the set of request-header + fields that fully determines, while the response is fresh, + whether a cache is permitted to use the response to reply to a + subsequent request without revalidation.""", + ) + content_language = _set_property( + "Content-Language", + doc="""The Content-Language entity-header field describes the + natural language(s) of the intended audience for the enclosed + entity. Note that this might not be equivalent to all the + languages used within the entity-body.""", + ) + allow = _set_property( + "Allow", + doc="""The Allow entity-header field lists the set of methods + supported by the resource identified by the Request-URI. The + purpose of this field is strictly to inform the recipient of + valid methods associated with the resource. An Allow header + field MUST be present in a 405 (Method Not Allowed) + response.""", + ) + + # ETag + + @property + def cache_control(self) -> ResponseCacheControl: + """The Cache-Control general-header field is used to specify + directives that MUST be obeyed by all caching mechanisms along the + request/response chain. + """ + + def on_update(cache_control: ResponseCacheControl) -> None: + if not cache_control and "cache-control" in self.headers: + del self.headers["cache-control"] + elif cache_control: + self.headers["Cache-Control"] = cache_control.to_header() + + return parse_cache_control_header( + self.headers.get("cache-control"), on_update, ResponseCacheControl + ) + + def set_etag(self, etag: str, weak: bool = False) -> None: + """Set the etag, and override the old one if there was one.""" + self.headers["ETag"] = quote_etag(etag, weak) + + def get_etag(self) -> t.Union[t.Tuple[str, bool], t.Tuple[None, None]]: + """Return a tuple in the form ``(etag, is_weak)``. If there is no + ETag the return value is ``(None, None)``. + """ + return unquote_etag(self.headers.get("ETag")) + + accept_ranges = header_property[str]( + "Accept-Ranges", + doc="""The `Accept-Ranges` header. Even though the name would + indicate that multiple values are supported, it must be one + string token only. + + The values ``'bytes'`` and ``'none'`` are common. + + .. versionadded:: 0.7""", + ) + + @property + def content_range(self) -> ContentRange: + """The ``Content-Range`` header as a + :class:`~werkzeug.datastructures.ContentRange` object. Available + even if the header is not set. + + .. versionadded:: 0.7 + """ + + def on_update(rng: ContentRange) -> None: + if not rng: + del self.headers["content-range"] + else: + self.headers["Content-Range"] = rng.to_header() + + rv = parse_content_range_header(self.headers.get("content-range"), on_update) + # always provide a content range object to make the descriptor + # more user friendly. It provides an unset() method that can be + # used to remove the header quickly. + if rv is None: + rv = ContentRange(None, None, None, on_update=on_update) + return rv + + @content_range.setter + def content_range(self, value: t.Optional[t.Union[ContentRange, str]]) -> None: + if not value: + del self.headers["content-range"] + elif isinstance(value, str): + self.headers["Content-Range"] = value + else: + self.headers["Content-Range"] = value.to_header() + + # Authorization + + @property + def www_authenticate(self) -> WWWAuthenticate: + """The ``WWW-Authenticate`` header in a parsed form.""" + + def on_update(www_auth: WWWAuthenticate) -> None: + if not www_auth and "www-authenticate" in self.headers: + del self.headers["www-authenticate"] + elif www_auth: + self.headers["WWW-Authenticate"] = www_auth.to_header() + + header = self.headers.get("www-authenticate") + return parse_www_authenticate_header(header, on_update) + + # CSP + + @property + def content_security_policy(self) -> ContentSecurityPolicy: + """The ``Content-Security-Policy`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy header adds an additional layer of + security to help detect and mitigate certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy"] + else: + self.headers["Content-Security-Policy"] = csp.to_header() + + rv = parse_csp_header(self.headers.get("content-security-policy"), on_update) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy.setter + def content_security_policy( + self, value: t.Optional[t.Union[ContentSecurityPolicy, str]] + ) -> None: + if not value: + del self.headers["content-security-policy"] + elif isinstance(value, str): + self.headers["Content-Security-Policy"] = value + else: + self.headers["Content-Security-Policy"] = value.to_header() + + @property + def content_security_policy_report_only(self) -> ContentSecurityPolicy: + """The ``Content-Security-policy-report-only`` header as a + :class:`~werkzeug.datastructures.ContentSecurityPolicy` object. Available + even if the header is not set. + + The Content-Security-Policy-Report-Only header adds a csp policy + that is not enforced but is reported thereby helping detect + certain types of attacks. + """ + + def on_update(csp: ContentSecurityPolicy) -> None: + if not csp: + del self.headers["content-security-policy-report-only"] + else: + self.headers["Content-Security-policy-report-only"] = csp.to_header() + + rv = parse_csp_header( + self.headers.get("content-security-policy-report-only"), on_update + ) + if rv is None: + rv = ContentSecurityPolicy(None, on_update=on_update) + return rv + + @content_security_policy_report_only.setter + def content_security_policy_report_only( + self, value: t.Optional[t.Union[ContentSecurityPolicy, str]] + ) -> None: + if not value: + del self.headers["content-security-policy-report-only"] + elif isinstance(value, str): + self.headers["Content-Security-policy-report-only"] = value + else: + self.headers["Content-Security-policy-report-only"] = value.to_header() + + # CORS + + @property + def access_control_allow_credentials(self) -> bool: + """Whether credentials can be shared by the browser to + JavaScript code. As part of the preflight request it indicates + whether credentials can be used on the cross origin request. + """ + return "Access-Control-Allow-Credentials" in self.headers + + @access_control_allow_credentials.setter + def access_control_allow_credentials(self, value: t.Optional[bool]) -> None: + if value is True: + self.headers["Access-Control-Allow-Credentials"] = "true" + else: + self.headers.pop("Access-Control-Allow-Credentials", None) + + access_control_allow_headers = header_property( + "Access-Control-Allow-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be sent with the cross origin request.", + ) + + access_control_allow_methods = header_property( + "Access-Control-Allow-Methods", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which methods can be used for the cross origin request.", + ) + + access_control_allow_origin = header_property[str]( + "Access-Control-Allow-Origin", + doc="The origin or '*' for any origin that may make cross origin requests.", + ) + + access_control_expose_headers = header_property( + "Access-Control-Expose-Headers", + load_func=parse_set_header, + dump_func=dump_header, + doc="Which headers can be shared by the browser to JavaScript code.", + ) + + access_control_max_age = header_property( + "Access-Control-Max-Age", + load_func=int, + dump_func=str, + doc="The maximum age in seconds the access control settings can be cached for.", + ) + + cross_origin_opener_policy = header_property[COOP]( + "Cross-Origin-Opener-Policy", + load_func=lambda value: COOP(value), + dump_func=lambda value: value.value, + default=COOP.UNSAFE_NONE, + doc="""Allows control over sharing of browsing context group with cross-origin + documents. Values must be a member of the :class:`werkzeug.http.COOP` enum.""", + ) + + cross_origin_embedder_policy = header_property[COEP]( + "Cross-Origin-Embedder-Policy", + load_func=lambda value: COEP(value), + dump_func=lambda value: value.value, + default=COEP.UNSAFE_NONE, + doc="""Prevents a document from loading any cross-origin resources that do not + explicitly grant the document permission. Values must be a member of the + :class:`werkzeug.http.COEP` enum.""", + ) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/utils.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/utils.py new file mode 100644 index 00000000..e639dcb4 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/sansio/utils.py @@ -0,0 +1,165 @@ +import typing as t + +from .._internal import _encode_idna +from ..exceptions import SecurityError +from ..urls import uri_to_iri +from ..urls import url_quote + + +def host_is_trusted(hostname: str, trusted_list: t.Iterable[str]) -> bool: + """Check if a host matches a list of trusted names. + + :param hostname: The name to check. + :param trusted_list: A list of valid names to match. If a name + starts with a dot it will match all subdomains. + + .. versionadded:: 0.9 + """ + if not hostname: + return False + + if isinstance(trusted_list, str): + trusted_list = [trusted_list] + + def _normalize(hostname: str) -> bytes: + if ":" in hostname: + hostname = hostname.rsplit(":", 1)[0] + + return _encode_idna(hostname) + + try: + hostname_bytes = _normalize(hostname) + except UnicodeError: + return False + + for ref in trusted_list: + if ref.startswith("."): + ref = ref[1:] + suffix_match = True + else: + suffix_match = False + + try: + ref_bytes = _normalize(ref) + except UnicodeError: + return False + + if ref_bytes == hostname_bytes: + return True + + if suffix_match and hostname_bytes.endswith(b"." + ref_bytes): + return True + + return False + + +def get_host( + scheme: str, + host_header: t.Optional[str], + server: t.Optional[t.Tuple[str, t.Optional[int]]] = None, + trusted_hosts: t.Optional[t.Iterable[str]] = None, +) -> str: + """Return the host for the given parameters. + + This first checks the ``host_header``. If it's not present, then + ``server`` is used. The host will only contain the port if it is + different than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param scheme: The protocol the request used, like ``"https"``. + :param host_header: The ``Host`` header value. + :param server: Address of the server. ``(host, port)``, or + ``(path, None)`` for unix sockets. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + host = "" + + if host_header is not None: + host = host_header + elif server is not None: + host = server[0] + + if server[1] is not None: + host = f"{host}:{server[1]}" + + if scheme in {"http", "ws"} and host.endswith(":80"): + host = host[:-3] + elif scheme in {"https", "wss"} and host.endswith(":443"): + host = host[:-4] + + if trusted_hosts is not None: + if not host_is_trusted(host, trusted_hosts): + raise SecurityError(f"Host {host!r} is not trusted.") + + return host + + +def get_current_url( + scheme: str, + host: str, + root_path: t.Optional[str] = None, + path: t.Optional[str] = None, + query_string: t.Optional[bytes] = None, +) -> str: + """Recreate the URL for a request. If an optional part isn't + provided, it and subsequent parts are not included in the URL. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param scheme: The protocol the request used, like ``"https"``. + :param host: The host the request was made to. See :func:`get_host`. + :param root_path: Prefix that the application is mounted under. This + is prepended to ``path``. + :param path: The path part of the URL after ``root_path``. + :param query_string: The portion of the URL after the "?". + """ + url = [scheme, "://", host] + + if root_path is None: + url.append("/") + return uri_to_iri("".join(url)) + + url.append(url_quote(root_path.rstrip("/"))) + url.append("/") + + if path is None: + return uri_to_iri("".join(url)) + + url.append(url_quote(path.lstrip("/"))) + + if query_string: + url.append("?") + url.append(url_quote(query_string, safe=":&%=+$!*'(),")) + + return uri_to_iri("".join(url)) + + +def get_content_length( + http_content_length: t.Union[str, None] = None, + http_transfer_encoding: t.Union[str, None] = "", +) -> t.Optional[int]: + """Returns the content length as an integer or ``None`` if + unavailable or chunked transfer encoding is used. + + :param http_content_length: The Content-Length HTTP header. + :param http_transfer_encoding: The Transfer-Encoding HTTP header. + + .. versionadded:: 2.2 + """ + if http_transfer_encoding == "chunked": + return None + + if http_content_length is not None: + try: + return max(0, int(http_content_length)) + except (ValueError, TypeError): + pass + return None diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/security.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/security.py new file mode 100644 index 00000000..4599fb3e --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/security.py @@ -0,0 +1,140 @@ +import hashlib +import hmac +import os +import posixpath +import secrets +import typing as t + +if t.TYPE_CHECKING: + pass + +SALT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +DEFAULT_PBKDF2_ITERATIONS = 260000 + +_os_alt_seps: t.List[str] = list( + sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/" +) + + +def gen_salt(length: int) -> str: + """Generate a random string of SALT_CHARS with specified ``length``.""" + if length <= 0: + raise ValueError("Salt length must be positive") + + return "".join(secrets.choice(SALT_CHARS) for _ in range(length)) + + +def _hash_internal(method: str, salt: str, password: str) -> t.Tuple[str, str]: + """Internal password hash helper. Supports plaintext without salt, + unsalted and salted passwords. In case salted passwords are used + hmac is used. + """ + if method == "plain": + return password, method + + salt = salt.encode("utf-8") + password = password.encode("utf-8") + + if method.startswith("pbkdf2:"): + if not salt: + raise ValueError("Salt is required for PBKDF2") + + args = method[7:].split(":") + + if len(args) not in (1, 2): + raise ValueError("Invalid number of arguments for PBKDF2") + + method = args.pop(0) + iterations = int(args[0] or 0) if args else DEFAULT_PBKDF2_ITERATIONS + return ( + hashlib.pbkdf2_hmac(method, password, salt, iterations).hex(), + f"pbkdf2:{method}:{iterations}", + ) + + if salt: + return hmac.new(salt, password, method).hexdigest(), method + + return hashlib.new(method, password).hexdigest(), method + + +def generate_password_hash( + password: str, method: str = "pbkdf2:sha256", salt_length: int = 16 +) -> str: + """Hash a password with the given method and salt with a string of + the given length. The format of the string returned includes the method + that was used so that :func:`check_password_hash` can check the hash. + + The format for the hashed string looks like this:: + + method$salt$hash + + This method can **not** generate unsalted passwords but it is possible + to set param method='plain' in order to enforce plaintext passwords. + If a salt is used, hmac is used internally to salt the password. + + If PBKDF2 is wanted it can be enabled by setting the method to + ``pbkdf2:method:iterations`` where iterations is optional:: + + pbkdf2:sha256:80000$salt$hash + pbkdf2:sha256$salt$hash + + :param password: the password to hash. + :param method: the hash method to use (one that hashlib supports). Can + optionally be in the format ``pbkdf2:method:iterations`` + to enable PBKDF2. + :param salt_length: the length of the salt in letters. + """ + salt = gen_salt(salt_length) if method != "plain" else "" + h, actual_method = _hash_internal(method, salt, password) + return f"{actual_method}${salt}${h}" + + +def check_password_hash(pwhash: str, password: str) -> bool: + """Check a password against a given salted and hashed password value. + In order to support unsalted legacy passwords this method supports + plain text passwords, md5 and sha1 hashes (both salted and unsalted). + + Returns `True` if the password matched, `False` otherwise. + + :param pwhash: a hashed string like returned by + :func:`generate_password_hash`. + :param password: the plaintext password to compare against the hash. + """ + if pwhash.count("$") < 2: + return False + + method, salt, hashval = pwhash.split("$", 2) + return hmac.compare_digest(_hash_internal(method, salt, password)[0], hashval) + + +def safe_join(directory: str, *pathnames: str) -> t.Optional[str]: + """Safely join zero or more untrusted path components to a base + directory to avoid escaping the base directory. + + :param directory: The trusted base directory. + :param pathnames: The untrusted path components relative to the + base directory. + :return: A safe path, otherwise ``None``. + """ + if not directory: + # Ensure we end up with ./path if directory="" is given, + # otherwise the first untrusted part could become trusted. + directory = "." + + parts = [directory] + + for filename in pathnames: + if filename != "": + filename = posixpath.normpath(filename) + + if ( + any(sep in filename for sep in _os_alt_seps) + or os.path.isabs(filename) + or filename == ".." + or filename.startswith("../") + ): + return None + + parts.append(filename) + + return posixpath.join(*parts) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/serving.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/serving.py new file mode 100644 index 00000000..2a2e74de --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/serving.py @@ -0,0 +1,1069 @@ +"""A WSGI and HTTP server for use **during development only**. This +server is convenient to use, but is not designed to be particularly +stable, secure, or efficient. Use a dedicate WSGI server and HTTP +server when deploying to production. + +It provides features like interactive debugging and code reloading. Use +``run_simple`` to start the server. Put this in a ``run.py`` script: + +.. code-block:: python + + from myapp import create_app + from werkzeug import run_simple +""" +import errno +import io +import os +import socket +import socketserver +import sys +import typing as t +from datetime import datetime as dt +from datetime import timedelta +from datetime import timezone +from http.server import BaseHTTPRequestHandler +from http.server import HTTPServer + +from ._internal import _log +from ._internal import _wsgi_encoding_dance +from .exceptions import InternalServerError +from .urls import uri_to_iri +from .urls import url_parse +from .urls import url_unquote + +try: + import ssl +except ImportError: + + class _SslDummy: + def __getattr__(self, name: str) -> t.Any: + raise RuntimeError( # noqa: B904 + "SSL is unavailable because this Python runtime was not" + " compiled with SSL/TLS support." + ) + + ssl = _SslDummy() # type: ignore + +_log_add_style = True + +if os.name == "nt": + try: + __import__("colorama") + except ImportError: + _log_add_style = False + +can_fork = hasattr(os, "fork") + +if can_fork: + ForkingMixIn = socketserver.ForkingMixIn +else: + + class ForkingMixIn: # type: ignore + pass + + +try: + af_unix = socket.AF_UNIX +except AttributeError: + af_unix = None # type: ignore + +LISTEN_QUEUE = 128 + +_TSSLContextArg = t.Optional[ + t.Union["ssl.SSLContext", t.Tuple[str, t.Optional[str]], "te.Literal['adhoc']"] +] + +if t.TYPE_CHECKING: + import typing_extensions as te # noqa: F401 + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from cryptography.hazmat.primitives.asymmetric.rsa import ( + RSAPrivateKeyWithSerialization, + ) + from cryptography.x509 import Certificate + + +class DechunkedInput(io.RawIOBase): + """An input stream that handles Transfer-Encoding 'chunked'""" + + def __init__(self, rfile: t.IO[bytes]) -> None: + self._rfile = rfile + self._done = False + self._len = 0 + + def readable(self) -> bool: + return True + + def read_chunk_len(self) -> int: + try: + line = self._rfile.readline().decode("latin1") + _len = int(line.strip(), 16) + except ValueError as e: + raise OSError("Invalid chunk header") from e + if _len < 0: + raise OSError("Negative chunk length not allowed") + return _len + + def readinto(self, buf: bytearray) -> int: # type: ignore + read = 0 + while not self._done and read < len(buf): + if self._len == 0: + # This is the first chunk or we fully consumed the previous + # one. Read the next length of the next chunk + self._len = self.read_chunk_len() + + if self._len == 0: + # Found the final chunk of size 0. The stream is now exhausted, + # but there is still a final newline that should be consumed + self._done = True + + if self._len > 0: + # There is data (left) in this chunk, so append it to the + # buffer. If this operation fully consumes the chunk, this will + # reset self._len to 0. + n = min(len(buf), self._len) + + # If (read + chunk size) becomes more than len(buf), buf will + # grow beyond the original size and read more data than + # required. So only read as much data as can fit in buf. + if read + n > len(buf): + buf[read:] = self._rfile.read(len(buf) - read) + self._len -= len(buf) - read + read = len(buf) + else: + buf[read : read + n] = self._rfile.read(n) + self._len -= n + read += n + + if self._len == 0: + # Skip the terminating newline of a chunk that has been fully + # consumed. This also applies to the 0-sized final chunk + terminator = self._rfile.readline() + if terminator not in (b"\n", b"\r\n", b"\r"): + raise OSError("Missing chunk terminating newline") + + return read + + +class WSGIRequestHandler(BaseHTTPRequestHandler): + """A request handler that implements WSGI dispatching.""" + + server: "BaseWSGIServer" + + @property + def server_version(self) -> str: # type: ignore + from . import __version__ + + return f"Werkzeug/{__version__}" + + def make_environ(self) -> "WSGIEnvironment": + request_url = url_parse(self.path) + url_scheme = "http" if self.server.ssl_context is None else "https" + + if not self.client_address: + self.client_address = ("", 0) + elif isinstance(self.client_address, str): + self.client_address = (self.client_address, 0) + + # If there was no scheme but the path started with two slashes, + # the first segment may have been incorrectly parsed as the + # netloc, prepend it to the path again. + if not request_url.scheme and request_url.netloc: + path_info = f"/{request_url.netloc}{request_url.path}" + else: + path_info = request_url.path + + path_info = url_unquote(path_info) + + environ: "WSGIEnvironment" = { + "wsgi.version": (1, 0), + "wsgi.url_scheme": url_scheme, + "wsgi.input": self.rfile, + "wsgi.errors": sys.stderr, + "wsgi.multithread": self.server.multithread, + "wsgi.multiprocess": self.server.multiprocess, + "wsgi.run_once": False, + "werkzeug.socket": self.connection, + "SERVER_SOFTWARE": self.server_version, + "REQUEST_METHOD": self.command, + "SCRIPT_NAME": "", + "PATH_INFO": _wsgi_encoding_dance(path_info), + "QUERY_STRING": _wsgi_encoding_dance(request_url.query), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": _wsgi_encoding_dance(self.path), + # Non-standard, added by gunicorn + "RAW_URI": _wsgi_encoding_dance(self.path), + "REMOTE_ADDR": self.address_string(), + "REMOTE_PORT": self.port_integer(), + "SERVER_NAME": self.server.server_address[0], + "SERVER_PORT": str(self.server.server_address[1]), + "SERVER_PROTOCOL": self.request_version, + } + + for key, value in self.headers.items(): + key = key.upper().replace("-", "_") + value = value.replace("\r\n", "") + if key not in ("CONTENT_TYPE", "CONTENT_LENGTH"): + key = f"HTTP_{key}" + if key in environ: + value = f"{environ[key]},{value}" + environ[key] = value + + if environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked": + environ["wsgi.input_terminated"] = True + environ["wsgi.input"] = DechunkedInput(environ["wsgi.input"]) + + # Per RFC 2616, if the URL is absolute, use that as the host. + # We're using "has a scheme" to indicate an absolute URL. + if request_url.scheme and request_url.netloc: + environ["HTTP_HOST"] = request_url.netloc + + try: + # binary_form=False gives nicer information, but wouldn't be compatible with + # what Nginx or Apache could return. + peer_cert = self.connection.getpeercert(binary_form=True) + if peer_cert is not None: + # Nginx and Apache use PEM format. + environ["SSL_CLIENT_CERT"] = ssl.DER_cert_to_PEM_cert(peer_cert) + except ValueError: + # SSL handshake hasn't finished. + self.server.log("error", "Cannot fetch SSL peer certificate info") + except AttributeError: + # Not using TLS, the socket will not have getpeercert(). + pass + + return environ + + def run_wsgi(self) -> None: + if self.headers.get("Expect", "").lower().strip() == "100-continue": + self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n") + + self.environ = environ = self.make_environ() + status_set: t.Optional[str] = None + headers_set: t.Optional[t.List[t.Tuple[str, str]]] = None + status_sent: t.Optional[str] = None + headers_sent: t.Optional[t.List[t.Tuple[str, str]]] = None + chunk_response: bool = False + + def write(data: bytes) -> None: + nonlocal status_sent, headers_sent, chunk_response + assert status_set is not None, "write() before start_response" + assert headers_set is not None, "write() before start_response" + if status_sent is None: + status_sent = status_set + headers_sent = headers_set + try: + code_str, msg = status_sent.split(None, 1) + except ValueError: + code_str, msg = status_sent, "" + code = int(code_str) + self.send_response(code, msg) + header_keys = set() + for key, value in headers_sent: + self.send_header(key, value) + header_keys.add(key.lower()) + + # Use chunked transfer encoding if there is no content + # length. Do not use for 1xx and 204 responses. 304 + # responses and HEAD requests are also excluded, which + # is the more conservative behavior and matches other + # parts of the code. + # https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.1 + if ( + not ( + "content-length" in header_keys + or environ["REQUEST_METHOD"] == "HEAD" + or (100 <= code < 200) + or code in {204, 304} + ) + and self.protocol_version >= "HTTP/1.1" + ): + chunk_response = True + self.send_header("Transfer-Encoding", "chunked") + + # Always close the connection. This disables HTTP/1.1 + # keep-alive connections. They aren't handled well by + # Python's http.server because it doesn't know how to + # drain the stream before the next request line. + self.send_header("Connection", "close") + self.end_headers() + + assert isinstance(data, bytes), "applications must write bytes" + + if data: + if chunk_response: + self.wfile.write(hex(len(data))[2:].encode()) + self.wfile.write(b"\r\n") + + self.wfile.write(data) + + if chunk_response: + self.wfile.write(b"\r\n") + + self.wfile.flush() + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal status_set, headers_set + if exc_info: + try: + if headers_sent: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + elif headers_set: + raise AssertionError("Headers already set") + status_set = status + headers_set = headers + return write + + def execute(app: "WSGIApplication") -> None: + application_iter = app(environ, start_response) + try: + for data in application_iter: + write(data) + if not headers_sent: + write(b"") + if chunk_response: + self.wfile.write(b"0\r\n\r\n") + finally: + if hasattr(application_iter, "close"): + application_iter.close() + + try: + execute(self.server.app) + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e, environ) + except Exception as e: + if self.server.passthrough_errors: + raise + + if status_sent is not None and chunk_response: + self.close_connection = True + + try: + # if we haven't yet sent the headers but they are set + # we roll back to be able to set them again. + if status_sent is None: + status_set = None + headers_set = None + execute(InternalServerError()) + except Exception: + pass + + from .debug.tbtools import DebugTraceback + + msg = DebugTraceback(e).render_traceback_text() + self.server.log("error", f"Error on request:\n{msg}") + + def handle(self) -> None: + """Handles a request ignoring dropped connections.""" + try: + super().handle() + except (ConnectionError, socket.timeout) as e: + self.connection_dropped(e) + except Exception as e: + if self.server.ssl_context is not None and is_ssl_error(e): + self.log_error("SSL error occurred: %s", e) + else: + raise + + def connection_dropped( + self, error: BaseException, environ: t.Optional["WSGIEnvironment"] = None + ) -> None: + """Called if the connection was closed by the client. By default + nothing happens. + """ + + def __getattr__(self, name: str) -> t.Any: + # All HTTP methods are handled by run_wsgi. + if name.startswith("do_"): + return self.run_wsgi + + # All other attributes are forwarded to the base class. + return getattr(super(), name) + + def address_string(self) -> str: + if getattr(self, "environ", None): + return self.environ["REMOTE_ADDR"] # type: ignore + + if not self.client_address: + return "" + + return self.client_address[0] + + def port_integer(self) -> int: + return self.client_address[1] + + def log_request( + self, code: t.Union[int, str] = "-", size: t.Union[int, str] = "-" + ) -> None: + try: + path = uri_to_iri(self.path) + msg = f"{self.command} {path} {self.request_version}" + except AttributeError: + # path isn't set if the requestline was bad + msg = self.requestline + + code = str(code) + + if code[0] == "1": # 1xx - Informational + msg = _ansi_style(msg, "bold") + elif code == "200": # 2xx - Success + pass + elif code == "304": # 304 - Resource Not Modified + msg = _ansi_style(msg, "cyan") + elif code[0] == "3": # 3xx - Redirection + msg = _ansi_style(msg, "green") + elif code == "404": # 404 - Resource Not Found + msg = _ansi_style(msg, "yellow") + elif code[0] == "4": # 4xx - Client Error + msg = _ansi_style(msg, "bold", "red") + else: # 5xx, or any other response + msg = _ansi_style(msg, "bold", "magenta") + + self.log("info", '"%s" %s %s', msg, code, size) + + def log_error(self, format: str, *args: t.Any) -> None: + self.log("error", format, *args) + + def log_message(self, format: str, *args: t.Any) -> None: + self.log("info", format, *args) + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log( + type, + f"{self.address_string()} - - [{self.log_date_time_string()}] {message}\n", + *args, + ) + + +def _ansi_style(value: str, *styles: str) -> str: + if not _log_add_style: + return value + + codes = { + "bold": 1, + "red": 31, + "green": 32, + "yellow": 33, + "magenta": 35, + "cyan": 36, + } + + for style in styles: + value = f"\x1b[{codes[style]}m{value}" + + return f"{value}\x1b[0m" + + +def generate_adhoc_ssl_pair( + cn: t.Optional[str] = None, +) -> t.Tuple["Certificate", "RSAPrivateKeyWithSerialization"]: + try: + from cryptography import x509 + from cryptography.x509.oid import NameOID + from cryptography.hazmat.backends import default_backend + from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives.asymmetric import rsa + except ImportError: + raise TypeError( + "Using ad-hoc certificates requires the cryptography library." + ) from None + + backend = default_backend() + pkey = rsa.generate_private_key( + public_exponent=65537, key_size=2048, backend=backend + ) + + # pretty damn sure that this is not actually accepted by anyone + if cn is None: + cn = "*" + + subject = x509.Name( + [ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Dummy Certificate"), + x509.NameAttribute(NameOID.COMMON_NAME, cn), + ] + ) + + backend = default_backend() + cert = ( + x509.CertificateBuilder() + .subject_name(subject) + .issuer_name(subject) + .public_key(pkey.public_key()) + .serial_number(x509.random_serial_number()) + .not_valid_before(dt.now(timezone.utc)) + .not_valid_after(dt.now(timezone.utc) + timedelta(days=365)) + .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False) + .add_extension(x509.SubjectAlternativeName([x509.DNSName(cn)]), critical=False) + .sign(pkey, hashes.SHA256(), backend) + ) + return cert, pkey + + +def make_ssl_devcert( + base_path: str, host: t.Optional[str] = None, cn: t.Optional[str] = None +) -> t.Tuple[str, str]: + """Creates an SSL key for development. This should be used instead of + the ``'adhoc'`` key which generates a new cert on each server start. + It accepts a path for where it should store the key and cert and + either a host or CN. If a host is given it will use the CN + ``*.host/CN=host``. + + For more information see :func:`run_simple`. + + .. versionadded:: 0.9 + + :param base_path: the path to the certificate and key. The extension + ``.crt`` is added for the certificate, ``.key`` is + added for the key. + :param host: the name of the host. This can be used as an alternative + for the `cn`. + :param cn: the `CN` to use. + """ + + if host is not None: + cn = f"*.{host}/CN={host}" + cert, pkey = generate_adhoc_ssl_pair(cn=cn) + + from cryptography.hazmat.primitives import serialization + + cert_file = f"{base_path}.crt" + pkey_file = f"{base_path}.key" + + with open(cert_file, "wb") as f: + f.write(cert.public_bytes(serialization.Encoding.PEM)) + with open(pkey_file, "wb") as f: + f.write( + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ) + ) + + return cert_file, pkey_file + + +def generate_adhoc_ssl_context() -> "ssl.SSLContext": + """Generates an adhoc SSL context for the development server.""" + import tempfile + import atexit + + cert, pkey = generate_adhoc_ssl_pair() + + from cryptography.hazmat.primitives import serialization + + cert_handle, cert_file = tempfile.mkstemp() + pkey_handle, pkey_file = tempfile.mkstemp() + atexit.register(os.remove, pkey_file) + atexit.register(os.remove, cert_file) + + os.write(cert_handle, cert.public_bytes(serialization.Encoding.PEM)) + os.write( + pkey_handle, + pkey.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption(), + ), + ) + + os.close(cert_handle) + os.close(pkey_handle) + ctx = load_ssl_context(cert_file, pkey_file) + return ctx + + +def load_ssl_context( + cert_file: str, pkey_file: t.Optional[str] = None, protocol: t.Optional[int] = None +) -> "ssl.SSLContext": + """Loads SSL context from cert/private key files and optional protocol. + Many parameters are directly taken from the API of + :py:class:`ssl.SSLContext`. + + :param cert_file: Path of the certificate to use. + :param pkey_file: Path of the private key to use. If not given, the key + will be obtained from the certificate file. + :param protocol: A ``PROTOCOL`` constant from the :mod:`ssl` module. + Defaults to :data:`ssl.PROTOCOL_TLS_SERVER`. + """ + if protocol is None: + protocol = ssl.PROTOCOL_TLS_SERVER + + ctx = ssl.SSLContext(protocol) + ctx.load_cert_chain(cert_file, pkey_file) + return ctx + + +def is_ssl_error(error: t.Optional[Exception] = None) -> bool: + """Checks if the given error (or the current one) is an SSL error.""" + if error is None: + error = t.cast(Exception, sys.exc_info()[1]) + return isinstance(error, ssl.SSLError) + + +def select_address_family(host: str, port: int) -> socket.AddressFamily: + """Return ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending on + the host and port.""" + if host.startswith("unix://"): + return socket.AF_UNIX + elif ":" in host and hasattr(socket, "AF_INET6"): + return socket.AF_INET6 + return socket.AF_INET + + +def get_sockaddr( + host: str, port: int, family: socket.AddressFamily +) -> t.Union[t.Tuple[str, int], str]: + """Return a fully qualified socket address that can be passed to + :func:`socket.bind`.""" + if family == af_unix: + return host.split("://", 1)[1] + try: + res = socket.getaddrinfo( + host, port, family, socket.SOCK_STREAM, socket.IPPROTO_TCP + ) + except socket.gaierror: + return host, port + return res[0][4] # type: ignore + + +def get_interface_ip(family: socket.AddressFamily) -> str: + """Get the IP address of an external interface. Used when binding to + 0.0.0.0 or ::1 to show a more useful URL. + + :meta private: + """ + # arbitrary private address + host = "fd31:f903:5ab5:1::1" if family == socket.AF_INET6 else "10.253.155.219" + + with socket.socket(family, socket.SOCK_DGRAM) as s: + try: + s.connect((host, 58162)) + except OSError: + return "::1" if family == socket.AF_INET6 else "127.0.0.1" + + return s.getsockname()[0] # type: ignore + + +class BaseWSGIServer(HTTPServer): + """A WSGI server that that handles one request at a time. + + Use :func:`make_server` to create a server instance. + """ + + multithread = False + multiprocess = False + request_queue_size = LISTEN_QUEUE + allow_reuse_address = True + + def __init__( + self, + host: str, + port: int, + app: "WSGIApplication", + handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, + ) -> None: + if handler is None: + handler = WSGIRequestHandler + + # If the handler doesn't directly set a protocol version and + # thread or process workers are used, then allow chunked + # responses and keep-alive connections by enabling HTTP/1.1. + if "protocol_version" not in vars(handler) and ( + self.multithread or self.multiprocess + ): + handler.protocol_version = "HTTP/1.1" + + self.host = host + self.port = port + self.app = app + self.passthrough_errors = passthrough_errors + + self.address_family = address_family = select_address_family(host, port) + server_address = get_sockaddr(host, int(port), address_family) + + # Remove a leftover Unix socket file from a previous run. Don't + # remove a file that was set up by run_simple. + if address_family == af_unix and fd is None: + server_address = t.cast(str, server_address) + + if os.path.exists(server_address): + os.unlink(server_address) + + # Bind and activate will be handled manually, it should only + # happen if we're not using a socket that was already set up. + super().__init__( + server_address, # type: ignore[arg-type] + handler, + bind_and_activate=False, + ) + + if fd is None: + # No existing socket descriptor, do bind_and_activate=True. + try: + self.server_bind() + self.server_activate() + except OSError as e: + # Catch connection issues and show them without the traceback. Show + # extra instructions for address not found, and for macOS. + self.server_close() + print(e.strerror, file=sys.stderr) + + if e.errno == errno.EADDRINUSE: + print( + f"Port {port} is in use by another program. Either identify and" + " stop that program, or start the server with a different" + " port.", + file=sys.stderr, + ) + + if sys.platform == "darwin" and port == 5000: + print( + "On macOS, try disabling the 'AirPlay Receiver' service" + " from System Preferences -> Sharing.", + file=sys.stderr, + ) + + sys.exit(1) + except BaseException: + self.server_close() + raise + else: + # TCPServer automatically opens a socket even if bind_and_activate is False. + # Close it to silence a ResourceWarning. + self.server_close() + + # Use the passed in socket directly. + self.socket = socket.fromfd(fd, address_family, socket.SOCK_STREAM) + self.server_address = self.socket.getsockname() + + if address_family != af_unix: + # If port was 0, this will record the bound port. + self.port = self.server_address[1] + + if ssl_context is not None: + if isinstance(ssl_context, tuple): + ssl_context = load_ssl_context(*ssl_context) + elif ssl_context == "adhoc": + ssl_context = generate_adhoc_ssl_context() + + self.socket = ssl_context.wrap_socket(self.socket, server_side=True) + self.ssl_context: t.Optional["ssl.SSLContext"] = ssl_context + else: + self.ssl_context = None + + def log(self, type: str, message: str, *args: t.Any) -> None: + _log(type, message, *args) + + def serve_forever(self, poll_interval: float = 0.5) -> None: + try: + super().serve_forever(poll_interval=poll_interval) + except KeyboardInterrupt: + pass + finally: + self.server_close() + + def handle_error( + self, request: t.Any, client_address: t.Union[t.Tuple[str, int], str] + ) -> None: + if self.passthrough_errors: + raise + + return super().handle_error(request, client_address) + + def log_startup(self) -> None: + """Show information about the address when starting the server.""" + dev_warning = ( + "WARNING: This is a development server. Do not use it in a production" + " deployment. Use a production WSGI server instead." + ) + dev_warning = _ansi_style(dev_warning, "bold", "red") + messages = [dev_warning] + + if self.address_family == af_unix: + messages.append(f" * Running on {self.host}") + else: + scheme = "http" if self.ssl_context is None else "https" + display_hostname = self.host + + if self.host in {"0.0.0.0", "::"}: + messages.append(f" * Running on all addresses ({self.host})") + + if self.host == "0.0.0.0": + localhost = "127.0.0.1" + display_hostname = get_interface_ip(socket.AF_INET) + else: + localhost = "[::1]" + display_hostname = get_interface_ip(socket.AF_INET6) + + messages.append(f" * Running on {scheme}://{localhost}:{self.port}") + + if ":" in display_hostname: + display_hostname = f"[{display_hostname}]" + + messages.append(f" * Running on {scheme}://{display_hostname}:{self.port}") + + _log("info", "\n".join(messages)) + + +class ThreadedWSGIServer(socketserver.ThreadingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate + threads. + + Use :func:`make_server` to create a server instance. + """ + + multithread = True + daemon_threads = True + + +class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer): + """A WSGI server that handles concurrent requests in separate forked + processes. + + Use :func:`make_server` to create a server instance. + """ + + multiprocess = True + + def __init__( + self, + host: str, + port: int, + app: "WSGIApplication", + processes: int = 40, + handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, + ) -> None: + if not can_fork: + raise ValueError("Your platform does not support forking.") + + super().__init__(host, port, app, handler, passthrough_errors, ssl_context, fd) + self.max_children = processes + + +def make_server( + host: str, + port: int, + app: "WSGIApplication", + threaded: bool = False, + processes: int = 1, + request_handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, + fd: t.Optional[int] = None, +) -> BaseWSGIServer: + """Create an appropriate WSGI server instance based on the value of + ``threaded`` and ``processes``. + + This is called from :func:`run_simple`, but can be used separately + to have access to the server object, such as to run it in a separate + thread. + + See :func:`run_simple` for parameter docs. + """ + if threaded and processes > 1: + raise ValueError("Cannot have a multi-thread and multi-process server.") + + if threaded: + return ThreadedWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + if processes > 1: + return ForkingWSGIServer( + host, + port, + app, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + + return BaseWSGIServer( + host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd + ) + + +def is_running_from_reloader() -> bool: + """Check if the server is running as a subprocess within the + Werkzeug reloader. + + .. versionadded:: 0.10 + """ + return os.environ.get("WERKZEUG_RUN_MAIN") == "true" + + +def run_simple( + hostname: str, + port: int, + application: "WSGIApplication", + use_reloader: bool = False, + use_debugger: bool = False, + use_evalex: bool = True, + extra_files: t.Optional[t.Iterable[str]] = None, + exclude_patterns: t.Optional[t.Iterable[str]] = None, + reloader_interval: int = 1, + reloader_type: str = "auto", + threaded: bool = False, + processes: int = 1, + request_handler: t.Optional[t.Type[WSGIRequestHandler]] = None, + static_files: t.Optional[t.Dict[str, t.Union[str, t.Tuple[str, str]]]] = None, + passthrough_errors: bool = False, + ssl_context: t.Optional[_TSSLContextArg] = None, +) -> None: + """Start a development server for a WSGI application. Various + optional features can be enabled. + + .. warning:: + + Do not use the development server when deploying to production. + It is intended for use only during local development. It is not + designed to be particularly efficient, stable, or secure. + + :param hostname: The host to bind to, for example ``'localhost'``. + Can be a domain, IPv4 or IPv6 address, or file path starting + with ``unix://`` for a Unix socket. + :param port: The port to bind to, for example ``8080``. Using ``0`` + tells the OS to pick a random free port. + :param application: The WSGI application to run. + :param use_reloader: Use a reloader process to restart the server + process when files are changed. + :param use_debugger: Use Werkzeug's debugger, which will show + formatted tracebacks on unhandled exceptions. + :param use_evalex: Make the debugger interactive. A Python terminal + can be opened for any frame in the traceback. Some protection is + provided by requiring a PIN, but this should never be enabled + on a publicly visible server. + :param extra_files: The reloader will watch these files for changes + in addition to Python modules. For example, watch a + configuration file. + :param exclude_patterns: The reloader will ignore changes to any + files matching these :mod:`fnmatch` patterns. For example, + ignore cache files. + :param reloader_interval: How often the reloader tries to check for + changes. + :param reloader_type: The reloader to use. The ``'stat'`` reloader + is built in, but may require significant CPU to watch files. The + ``'watchdog'`` reloader is much more efficient but requires + installing the ``watchdog`` package first. + :param threaded: Handle concurrent requests using threads. Cannot be + used with ``processes``. + :param processes: Handle concurrent requests using up to this number + of processes. Cannot be used with ``threaded``. + :param request_handler: Use a different + :class:`~BaseHTTPServer.BaseHTTPRequestHandler` subclass to + handle requests. + :param static_files: A dict mapping URL prefixes to directories to + serve static files from using + :class:`~werkzeug.middleware.SharedDataMiddleware`. + :param passthrough_errors: Don't catch unhandled exceptions at the + server level, let the serve crash instead. If ``use_debugger`` + is enabled, the debugger will still catch such errors. + :param ssl_context: Configure TLS to serve over HTTPS. Can be an + :class:`ssl.SSLContext` object, a ``(cert_file, key_file)`` + tuple to create a typical context, or the string ``'adhoc'`` to + generate a temporary self-signed certificate. + + .. versionchanged:: 2.1 + Instructions are shown for dealing with an "address already in + use" error. + + .. versionchanged:: 2.1 + Running on ``0.0.0.0`` or ``::`` shows the loopback IP in + addition to a real IP. + + .. versionchanged:: 2.1 + The command-line interface was removed. + + .. versionchanged:: 2.0 + Running on ``0.0.0.0`` or ``::`` shows a real IP address that + was bound as well as a warning not to run the development server + in production. + + .. versionchanged:: 2.0 + The ``exclude_patterns`` parameter was added. + + .. versionchanged:: 0.15 + Bind to a Unix socket by passing a ``hostname`` that starts with + ``unix://``. + + .. versionchanged:: 0.10 + Improved the reloader and added support for changing the backend + through the ``reloader_type`` parameter. + + .. versionchanged:: 0.9 + A command-line interface was added. + + .. versionchanged:: 0.8 + ``ssl_context`` can be a tuple of paths to the certificate and + private key files. + + .. versionchanged:: 0.6 + The ``ssl_context`` parameter was added. + + .. versionchanged:: 0.5 + The ``static_files`` and ``passthrough_errors`` parameters were + added. + """ + if not isinstance(port, int): + raise TypeError("port must be an integer") + + if static_files: + from .middleware.shared_data import SharedDataMiddleware + + application = SharedDataMiddleware(application, static_files) + + if use_debugger: + from .debug import DebuggedApplication + + application = DebuggedApplication(application, evalex=use_evalex) + + if not is_running_from_reloader(): + fd = None + else: + fd = int(os.environ["WERKZEUG_SERVER_FD"]) + + srv = make_server( + hostname, + port, + application, + threaded, + processes, + request_handler, + passthrough_errors, + ssl_context, + fd=fd, + ) + srv.socket.set_inheritable(True) + os.environ["WERKZEUG_SERVER_FD"] = str(srv.fileno()) + + if not is_running_from_reloader(): + srv.log_startup() + _log("info", _ansi_style("Press CTRL+C to quit", "yellow")) + + if use_reloader: + from ._reloader import run_with_reloader + + try: + run_with_reloader( + srv.serve_forever, + extra_files=extra_files, + exclude_patterns=exclude_patterns, + interval=reloader_interval, + reloader_type=reloader_type, + ) + finally: + srv.server_close() + else: + srv.serve_forever() diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/test.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/test.py new file mode 100644 index 00000000..996f4389 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/test.py @@ -0,0 +1,1338 @@ +import mimetypes +import sys +import typing as t +from collections import defaultdict +from datetime import datetime +from datetime import timedelta +from http.cookiejar import CookieJar +from io import BytesIO +from itertools import chain +from random import random +from tempfile import TemporaryFile +from time import time +from urllib.request import Request as _UrllibRequest + +from ._internal import _get_environ +from ._internal import _make_encode_wrapper +from ._internal import _wsgi_decoding_dance +from ._internal import _wsgi_encoding_dance +from .datastructures import Authorization +from .datastructures import CallbackDict +from .datastructures import CombinedMultiDict +from .datastructures import EnvironHeaders +from .datastructures import FileMultiDict +from .datastructures import Headers +from .datastructures import MultiDict +from .http import dump_cookie +from .http import dump_options_header +from .http import parse_options_header +from .sansio.multipart import Data +from .sansio.multipart import Epilogue +from .sansio.multipart import Field +from .sansio.multipart import File +from .sansio.multipart import MultipartEncoder +from .sansio.multipart import Preamble +from .urls import iri_to_uri +from .urls import url_encode +from .urls import url_fix +from .urls import url_parse +from .urls import url_unparse +from .urls import url_unquote +from .utils import cached_property +from .utils import get_content_type +from .wrappers.request import Request +from .wrappers.response import Response +from .wsgi import ClosingIterator +from .wsgi import get_current_url + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def stream_encode_multipart( + data: t.Mapping[str, t.Any], + use_tempfile: bool = True, + threshold: int = 1024 * 500, + boundary: t.Optional[str] = None, + charset: str = "utf-8", +) -> t.Tuple[t.IO[bytes], int, str]: + """Encode a dict of values (either strings or file descriptors or + :class:`FileStorage` objects.) into a multipart encoded string stored + in a file descriptor. + """ + if boundary is None: + boundary = f"---------------WerkzeugFormPart_{time()}{random()}" + + stream: t.IO[bytes] = BytesIO() + total_length = 0 + on_disk = False + write_binary: t.Callable[[bytes], int] + + if use_tempfile: + + def write_binary(s: bytes) -> int: + nonlocal stream, total_length, on_disk + + if on_disk: + return stream.write(s) + else: + length = len(s) + + if length + total_length <= threshold: + stream.write(s) + else: + new_stream = t.cast(t.IO[bytes], TemporaryFile("wb+")) + new_stream.write(stream.getvalue()) # type: ignore + new_stream.write(s) + stream = new_stream + on_disk = True + + total_length += length + return length + + else: + write_binary = stream.write + + encoder = MultipartEncoder(boundary.encode()) + write_binary(encoder.send_event(Preamble(data=b""))) + for key, value in _iter_data(data): + reader = getattr(value, "read", None) + if reader is not None: + filename = getattr(value, "filename", getattr(value, "name", None)) + content_type = getattr(value, "content_type", None) + if content_type is None: + content_type = ( + filename + and mimetypes.guess_type(filename)[0] + or "application/octet-stream" + ) + headers = value.headers + headers.update([("Content-Type", content_type)]) + if filename is None: + write_binary(encoder.send_event(Field(name=key, headers=headers))) + else: + write_binary( + encoder.send_event( + File(name=key, filename=filename, headers=headers) + ) + ) + while True: + chunk = reader(16384) + + if not chunk: + break + + write_binary(encoder.send_event(Data(data=chunk, more_data=True))) + else: + if not isinstance(value, str): + value = str(value) + write_binary(encoder.send_event(Field(name=key, headers=Headers()))) + write_binary( + encoder.send_event(Data(data=value.encode(charset), more_data=False)) + ) + + write_binary(encoder.send_event(Epilogue(data=b""))) + + length = stream.tell() + stream.seek(0) + return stream, length, boundary + + +def encode_multipart( + values: t.Mapping[str, t.Any], + boundary: t.Optional[str] = None, + charset: str = "utf-8", +) -> t.Tuple[str, bytes]: + """Like `stream_encode_multipart` but returns a tuple in the form + (``boundary``, ``data``) where data is bytes. + """ + stream, length, boundary = stream_encode_multipart( + values, use_tempfile=False, boundary=boundary, charset=charset + ) + return boundary, stream.read() + + +class _TestCookieHeaders: + """A headers adapter for cookielib""" + + def __init__(self, headers: t.Union[Headers, t.List[t.Tuple[str, str]]]) -> None: + self.headers = headers + + def getheaders(self, name: str) -> t.Iterable[str]: + headers = [] + name = name.lower() + for k, v in self.headers: + if k.lower() == name: + headers.append(v) + return headers + + def get_all( + self, name: str, default: t.Optional[t.Iterable[str]] = None + ) -> t.Iterable[str]: + headers = self.getheaders(name) + + if not headers: + return default # type: ignore + + return headers + + +class _TestCookieResponse: + """Something that looks like a httplib.HTTPResponse, but is actually just an + adapter for our test responses to make them available for cookielib. + """ + + def __init__(self, headers: t.Union[Headers, t.List[t.Tuple[str, str]]]) -> None: + self.headers = _TestCookieHeaders(headers) + + def info(self) -> _TestCookieHeaders: + return self.headers + + +class _TestCookieJar(CookieJar): + """A cookielib.CookieJar modified to inject and read cookie headers from + and to wsgi environments, and wsgi application responses. + """ + + def inject_wsgi(self, environ: "WSGIEnvironment") -> None: + """Inject the cookies as client headers into the server's wsgi + environment. + """ + cvals = [f"{c.name}={c.value}" for c in self] + + if cvals: + environ["HTTP_COOKIE"] = "; ".join(cvals) + else: + environ.pop("HTTP_COOKIE", None) + + def extract_wsgi( + self, + environ: "WSGIEnvironment", + headers: t.Union[Headers, t.List[t.Tuple[str, str]]], + ) -> None: + """Extract the server's set-cookie headers as cookies into the + cookie jar. + """ + self.extract_cookies( + _TestCookieResponse(headers), # type: ignore + _UrllibRequest(get_current_url(environ)), + ) + + +def _iter_data(data: t.Mapping[str, t.Any]) -> t.Iterator[t.Tuple[str, t.Any]]: + """Iterate over a mapping that might have a list of values, yielding + all key, value pairs. Almost like iter_multi_items but only allows + lists, not tuples, of values so tuples can be used for files. + """ + if isinstance(data, MultiDict): + yield from data.items(multi=True) + else: + for key, value in data.items(): + if isinstance(value, list): + for v in value: + yield key, v + else: + yield key, value + + +_TAnyMultiDict = t.TypeVar("_TAnyMultiDict", bound=MultiDict) + + +class EnvironBuilder: + """This class can be used to conveniently create a WSGI environment + for testing purposes. It can be used to quickly create WSGI environments + or request objects from arbitrary data. + + The signature of this class is also used in some other places as of + Werkzeug 0.5 (:func:`create_environ`, :meth:`Response.from_values`, + :meth:`Client.open`). Because of this most of the functionality is + available through the constructor alone. + + Files and regular form data can be manipulated independently of each + other with the :attr:`form` and :attr:`files` attributes, but are + passed with the same argument to the constructor: `data`. + + `data` can be any of these values: + + - a `str` or `bytes` object: The object is converted into an + :attr:`input_stream`, the :attr:`content_length` is set and you have to + provide a :attr:`content_type`. + - a `dict` or :class:`MultiDict`: The keys have to be strings. The values + have to be either any of the following objects, or a list of any of the + following objects: + + - a :class:`file`-like object: These are converted into + :class:`FileStorage` objects automatically. + - a `tuple`: The :meth:`~FileMultiDict.add_file` method is called + with the key and the unpacked `tuple` items as positional + arguments. + - a `str`: The string is set as form data for the associated key. + - a file-like object: The object content is loaded in memory and then + handled like a regular `str` or a `bytes`. + + :param path: the path of the request. In the WSGI environment this will + end up as `PATH_INFO`. If the `query_string` is not defined + and there is a question mark in the `path` everything after + it is used as query string. + :param base_url: the base URL is a URL that is used to extract the WSGI + URL scheme, host (server name + server port) and the + script root (`SCRIPT_NAME`). + :param query_string: an optional string or dict with URL parameters. + :param method: the HTTP method to use, defaults to `GET`. + :param input_stream: an optional input stream. Do not specify this and + `data`. As soon as an input stream is set you can't + modify :attr:`args` and :attr:`files` unless you + set the :attr:`input_stream` to `None` again. + :param content_type: The content type for the request. As of 0.5 you + don't have to provide this when specifying files + and form data via `data`. + :param content_length: The content length for the request. You don't + have to specify this when providing data via + `data`. + :param errors_stream: an optional error stream that is used for + `wsgi.errors`. Defaults to :data:`stderr`. + :param multithread: controls `wsgi.multithread`. Defaults to `False`. + :param multiprocess: controls `wsgi.multiprocess`. Defaults to `False`. + :param run_once: controls `wsgi.run_once`. Defaults to `False`. + :param headers: an optional list or :class:`Headers` object of headers. + :param data: a string or dict of form data or a file-object. + See explanation above. + :param json: An object to be serialized and assigned to ``data``. + Defaults the content type to ``"application/json"``. + Serialized with the function assigned to :attr:`json_dumps`. + :param environ_base: an optional dict of environment defaults. + :param environ_overrides: an optional dict of environment overrides. + :param charset: the charset used to encode string data. + :param auth: An authorization object to use for the + ``Authorization`` header value. A ``(username, password)`` tuple + is a shortcut for ``Basic`` authorization. + + .. versionchanged:: 2.1 + ``CONTENT_TYPE`` and ``CONTENT_LENGTH`` are not duplicated as + header keys in the environ. + + .. versionchanged:: 2.0 + ``REQUEST_URI`` and ``RAW_URI`` is the full raw URI including + the query string, not only the path. + + .. versionchanged:: 2.0 + The default :attr:`request_class` is ``Request`` instead of + ``BaseRequest``. + + .. versionadded:: 2.0 + Added the ``auth`` parameter. + + .. versionadded:: 0.15 + The ``json`` param and :meth:`json_dumps` method. + + .. versionadded:: 0.15 + The environ has keys ``REQUEST_URI`` and ``RAW_URI`` containing + the path before percent-decoding. This is not part of the WSGI + PEP, but many WSGI servers include it. + + .. versionchanged:: 0.6 + ``path`` and ``base_url`` can now be unicode strings that are + encoded with :func:`iri_to_uri`. + """ + + #: the server protocol to use. defaults to HTTP/1.1 + server_protocol = "HTTP/1.1" + + #: the wsgi version to use. defaults to (1, 0) + wsgi_version = (1, 0) + + #: The default request class used by :meth:`get_request`. + request_class = Request + + import json + + #: The serialization function used when ``json`` is passed. + json_dumps = staticmethod(json.dumps) + del json + + _args: t.Optional[MultiDict] + _query_string: t.Optional[str] + _input_stream: t.Optional[t.IO[bytes]] + _form: t.Optional[MultiDict] + _files: t.Optional[FileMultiDict] + + def __init__( + self, + path: str = "/", + base_url: t.Optional[str] = None, + query_string: t.Optional[t.Union[t.Mapping[str, str], str]] = None, + method: str = "GET", + input_stream: t.Optional[t.IO[bytes]] = None, + content_type: t.Optional[str] = None, + content_length: t.Optional[int] = None, + errors_stream: t.Optional[t.IO[str]] = None, + multithread: bool = False, + multiprocess: bool = False, + run_once: bool = False, + headers: t.Optional[t.Union[Headers, t.Iterable[t.Tuple[str, str]]]] = None, + data: t.Optional[ + t.Union[t.IO[bytes], str, bytes, t.Mapping[str, t.Any]] + ] = None, + environ_base: t.Optional[t.Mapping[str, t.Any]] = None, + environ_overrides: t.Optional[t.Mapping[str, t.Any]] = None, + charset: str = "utf-8", + mimetype: t.Optional[str] = None, + json: t.Optional[t.Mapping[str, t.Any]] = None, + auth: t.Optional[t.Union[Authorization, t.Tuple[str, str]]] = None, + ) -> None: + path_s = _make_encode_wrapper(path) + if query_string is not None and path_s("?") in path: + raise ValueError("Query string is defined in the path and as an argument") + request_uri = url_parse(path) + if query_string is None and path_s("?") in path: + query_string = request_uri.query + self.charset = charset + self.path = iri_to_uri(request_uri.path) + self.request_uri = path + if base_url is not None: + base_url = url_fix(iri_to_uri(base_url, charset), charset) + self.base_url = base_url # type: ignore + if isinstance(query_string, (bytes, str)): + self.query_string = query_string + else: + if query_string is None: + query_string = MultiDict() + elif not isinstance(query_string, MultiDict): + query_string = MultiDict(query_string) + self.args = query_string + self.method = method + if headers is None: + headers = Headers() + elif not isinstance(headers, Headers): + headers = Headers(headers) + self.headers = headers + if content_type is not None: + self.content_type = content_type + if errors_stream is None: + errors_stream = sys.stderr + self.errors_stream = errors_stream + self.multithread = multithread + self.multiprocess = multiprocess + self.run_once = run_once + self.environ_base = environ_base + self.environ_overrides = environ_overrides + self.input_stream = input_stream + self.content_length = content_length + self.closed = False + + if auth is not None: + if isinstance(auth, tuple): + auth = Authorization( + "basic", {"username": auth[0], "password": auth[1]} + ) + + self.headers.set("Authorization", auth.to_header()) + + if json is not None: + if data is not None: + raise TypeError("can't provide both json and data") + + data = self.json_dumps(json) + + if self.content_type is None: + self.content_type = "application/json" + + if data: + if input_stream is not None: + raise TypeError("can't provide input stream and data") + if hasattr(data, "read"): + data = data.read() + if isinstance(data, str): + data = data.encode(self.charset) + if isinstance(data, bytes): + self.input_stream = BytesIO(data) + if self.content_length is None: + self.content_length = len(data) + else: + for key, value in _iter_data(data): + if isinstance(value, (tuple, dict)) or hasattr(value, "read"): + self._add_file_from_data(key, value) + else: + self.form.setlistdefault(key).append(value) + + if mimetype is not None: + self.mimetype = mimetype + + @classmethod + def from_environ( + cls, environ: "WSGIEnvironment", **kwargs: t.Any + ) -> "EnvironBuilder": + """Turn an environ dict back into a builder. Any extra kwargs + override the args extracted from the environ. + + .. versionchanged:: 2.0 + Path and query values are passed through the WSGI decoding + dance to avoid double encoding. + + .. versionadded:: 0.15 + """ + headers = Headers(EnvironHeaders(environ)) + out = { + "path": _wsgi_decoding_dance(environ["PATH_INFO"]), + "base_url": cls._make_base_url( + environ["wsgi.url_scheme"], + headers.pop("Host"), + _wsgi_decoding_dance(environ["SCRIPT_NAME"]), + ), + "query_string": _wsgi_decoding_dance(environ["QUERY_STRING"]), + "method": environ["REQUEST_METHOD"], + "input_stream": environ["wsgi.input"], + "content_type": headers.pop("Content-Type", None), + "content_length": headers.pop("Content-Length", None), + "errors_stream": environ["wsgi.errors"], + "multithread": environ["wsgi.multithread"], + "multiprocess": environ["wsgi.multiprocess"], + "run_once": environ["wsgi.run_once"], + "headers": headers, + } + out.update(kwargs) + return cls(**out) + + def _add_file_from_data( + self, + key: str, + value: t.Union[ + t.IO[bytes], t.Tuple[t.IO[bytes], str], t.Tuple[t.IO[bytes], str, str] + ], + ) -> None: + """Called in the EnvironBuilder to add files from the data dict.""" + if isinstance(value, tuple): + self.files.add_file(key, *value) + else: + self.files.add_file(key, value) + + @staticmethod + def _make_base_url(scheme: str, host: str, script_root: str) -> str: + return url_unparse((scheme, host, script_root, "", "")).rstrip("/") + "/" + + @property + def base_url(self) -> str: + """The base URL is used to extract the URL scheme, host name, + port, and root path. + """ + return self._make_base_url(self.url_scheme, self.host, self.script_root) + + @base_url.setter + def base_url(self, value: t.Optional[str]) -> None: + if value is None: + scheme = "http" + netloc = "localhost" + script_root = "" + else: + scheme, netloc, script_root, qs, anchor = url_parse(value) + if qs or anchor: + raise ValueError("base url must not contain a query string or fragment") + self.script_root = script_root.rstrip("/") + self.host = netloc + self.url_scheme = scheme + + @property + def content_type(self) -> t.Optional[str]: + """The content type for the request. Reflected from and to + the :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + ct = self.headers.get("Content-Type") + if ct is None and not self._input_stream: + if self._files: + return "multipart/form-data" + if self._form: + return "application/x-www-form-urlencoded" + return None + return ct + + @content_type.setter + def content_type(self, value: t.Optional[str]) -> None: + if value is None: + self.headers.pop("Content-Type", None) + else: + self.headers["Content-Type"] = value + + @property + def mimetype(self) -> t.Optional[str]: + """The mimetype (content type without charset etc.) + + .. versionadded:: 0.14 + """ + ct = self.content_type + return ct.split(";")[0].strip() if ct else None + + @mimetype.setter + def mimetype(self, value: str) -> None: + self.content_type = get_content_type(value, self.charset) + + @property + def mimetype_params(self) -> t.Mapping[str, str]: + """The mimetype parameters as dict. For example if the + content type is ``text/html; charset=utf-8`` the params would be + ``{'charset': 'utf-8'}``. + + .. versionadded:: 0.14 + """ + + def on_update(d: CallbackDict) -> None: + self.headers["Content-Type"] = dump_options_header(self.mimetype, d) + + d = parse_options_header(self.headers.get("content-type", ""))[1] + return CallbackDict(d, on_update) + + @property + def content_length(self) -> t.Optional[int]: + """The content length as integer. Reflected from and to the + :attr:`headers`. Do not set if you set :attr:`files` or + :attr:`form` for auto detection. + """ + return self.headers.get("Content-Length", type=int) + + @content_length.setter + def content_length(self, value: t.Optional[int]) -> None: + if value is None: + self.headers.pop("Content-Length", None) + else: + self.headers["Content-Length"] = str(value) + + def _get_form(self, name: str, storage: t.Type[_TAnyMultiDict]) -> _TAnyMultiDict: + """Common behavior for getting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param storage: Storage class used for the data. + """ + if self.input_stream is not None: + raise AttributeError("an input stream is defined") + + rv = getattr(self, name) + + if rv is None: + rv = storage() + setattr(self, name, rv) + + return rv # type: ignore + + def _set_form(self, name: str, value: MultiDict) -> None: + """Common behavior for setting the :attr:`form` and + :attr:`files` properties. + + :param name: Name of the internal cached attribute. + :param value: Value to assign to the attribute. + """ + self._input_stream = None + setattr(self, name, value) + + @property + def form(self) -> MultiDict: + """A :class:`MultiDict` of form values.""" + return self._get_form("_form", MultiDict) + + @form.setter + def form(self, value: MultiDict) -> None: + self._set_form("_form", value) + + @property + def files(self) -> FileMultiDict: + """A :class:`FileMultiDict` of uploaded files. Use + :meth:`~FileMultiDict.add_file` to add new files. + """ + return self._get_form("_files", FileMultiDict) + + @files.setter + def files(self, value: FileMultiDict) -> None: + self._set_form("_files", value) + + @property + def input_stream(self) -> t.Optional[t.IO[bytes]]: + """An optional input stream. This is mutually exclusive with + setting :attr:`form` and :attr:`files`, setting it will clear + those. Do not provide this if the method is not ``POST`` or + another method that has a body. + """ + return self._input_stream + + @input_stream.setter + def input_stream(self, value: t.Optional[t.IO[bytes]]) -> None: + self._input_stream = value + self._form = None + self._files = None + + @property + def query_string(self) -> str: + """The query string. If you set this to a string + :attr:`args` will no longer be available. + """ + if self._query_string is None: + if self._args is not None: + return url_encode(self._args, charset=self.charset) + return "" + return self._query_string + + @query_string.setter + def query_string(self, value: t.Optional[str]) -> None: + self._query_string = value + self._args = None + + @property + def args(self) -> MultiDict: + """The URL arguments as :class:`MultiDict`.""" + if self._query_string is not None: + raise AttributeError("a query string is defined") + if self._args is None: + self._args = MultiDict() + return self._args + + @args.setter + def args(self, value: t.Optional[MultiDict]) -> None: + self._query_string = None + self._args = value + + @property + def server_name(self) -> str: + """The server name (read-only, use :attr:`host` to set)""" + return self.host.split(":", 1)[0] + + @property + def server_port(self) -> int: + """The server port as integer (read-only, use :attr:`host` to set)""" + pieces = self.host.split(":", 1) + + if len(pieces) == 2: + try: + return int(pieces[1]) + except ValueError: + pass + + if self.url_scheme == "https": + return 443 + return 80 + + def __del__(self) -> None: + try: + self.close() + except Exception: + pass + + def close(self) -> None: + """Closes all files. If you put real :class:`file` objects into the + :attr:`files` dict you can call this method to automatically close + them all in one go. + """ + if self.closed: + return + try: + files = self.files.values() + except AttributeError: + files = () # type: ignore + for f in files: + try: + f.close() + except Exception: + pass + self.closed = True + + def get_environ(self) -> "WSGIEnvironment": + """Return the built environ. + + .. versionchanged:: 0.15 + The content type and length headers are set based on + input stream detection. Previously this only set the WSGI + keys. + """ + input_stream = self.input_stream + content_length = self.content_length + + mimetype = self.mimetype + content_type = self.content_type + + if input_stream is not None: + start_pos = input_stream.tell() + input_stream.seek(0, 2) + end_pos = input_stream.tell() + input_stream.seek(start_pos) + content_length = end_pos - start_pos + elif mimetype == "multipart/form-data": + input_stream, content_length, boundary = stream_encode_multipart( + CombinedMultiDict([self.form, self.files]), charset=self.charset + ) + content_type = f'{mimetype}; boundary="{boundary}"' + elif mimetype == "application/x-www-form-urlencoded": + form_encoded = url_encode(self.form, charset=self.charset).encode("ascii") + content_length = len(form_encoded) + input_stream = BytesIO(form_encoded) + else: + input_stream = BytesIO() + + result: "WSGIEnvironment" = {} + if self.environ_base: + result.update(self.environ_base) + + def _path_encode(x: str) -> str: + return _wsgi_encoding_dance(url_unquote(x, self.charset), self.charset) + + raw_uri = _wsgi_encoding_dance(self.request_uri, self.charset) + result.update( + { + "REQUEST_METHOD": self.method, + "SCRIPT_NAME": _path_encode(self.script_root), + "PATH_INFO": _path_encode(self.path), + "QUERY_STRING": _wsgi_encoding_dance(self.query_string, self.charset), + # Non-standard, added by mod_wsgi, uWSGI + "REQUEST_URI": raw_uri, + # Non-standard, added by gunicorn + "RAW_URI": raw_uri, + "SERVER_NAME": self.server_name, + "SERVER_PORT": str(self.server_port), + "HTTP_HOST": self.host, + "SERVER_PROTOCOL": self.server_protocol, + "wsgi.version": self.wsgi_version, + "wsgi.url_scheme": self.url_scheme, + "wsgi.input": input_stream, + "wsgi.errors": self.errors_stream, + "wsgi.multithread": self.multithread, + "wsgi.multiprocess": self.multiprocess, + "wsgi.run_once": self.run_once, + } + ) + + headers = self.headers.copy() + # Don't send these as headers, they're part of the environ. + headers.remove("Content-Type") + headers.remove("Content-Length") + + if content_type is not None: + result["CONTENT_TYPE"] = content_type + + if content_length is not None: + result["CONTENT_LENGTH"] = str(content_length) + + combined_headers = defaultdict(list) + + for key, value in headers.to_wsgi_list(): + combined_headers[f"HTTP_{key.upper().replace('-', '_')}"].append(value) + + for key, values in combined_headers.items(): + result[key] = ", ".join(values) + + if self.environ_overrides: + result.update(self.environ_overrides) + + return result + + def get_request(self, cls: t.Optional[t.Type[Request]] = None) -> Request: + """Returns a request with the data. If the request class is not + specified :attr:`request_class` is used. + + :param cls: The request wrapper to use. + """ + if cls is None: + cls = self.request_class + + return cls(self.get_environ()) + + +class ClientRedirectError(Exception): + """If a redirect loop is detected when using follow_redirects=True with + the :cls:`Client`, then this exception is raised. + """ + + +class Client: + """This class allows you to send requests to a wrapped application. + + The use_cookies parameter indicates whether cookies should be stored and + sent for subsequent requests. This is True by default, but passing False + will disable this behaviour. + + If you want to request some subdomain of your application you may set + `allow_subdomain_redirects` to `True` as if not no external redirects + are allowed. + + .. versionchanged:: 2.1 + Removed deprecated behavior of treating the response as a + tuple. All data is available as properties on the returned + response object. + + .. versionchanged:: 2.0 + ``response_wrapper`` is always a subclass of + :class:``TestResponse``. + + .. versionchanged:: 0.5 + Added the ``use_cookies`` parameter. + """ + + def __init__( + self, + application: "WSGIApplication", + response_wrapper: t.Optional[t.Type["Response"]] = None, + use_cookies: bool = True, + allow_subdomain_redirects: bool = False, + ) -> None: + self.application = application + + if response_wrapper in {None, Response}: + response_wrapper = TestResponse + elif not isinstance(response_wrapper, TestResponse): + response_wrapper = type( + "WrapperTestResponse", + (TestResponse, response_wrapper), # type: ignore + {}, + ) + + self.response_wrapper = t.cast(t.Type["TestResponse"], response_wrapper) + + if use_cookies: + self.cookie_jar: t.Optional[_TestCookieJar] = _TestCookieJar() + else: + self.cookie_jar = None + + self.allow_subdomain_redirects = allow_subdomain_redirects + + def set_cookie( + self, + server_name: str, + key: str, + value: str = "", + max_age: t.Optional[t.Union[timedelta, int]] = None, + expires: t.Optional[t.Union[str, datetime, int, float]] = None, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + charset: str = "utf-8", + ) -> None: + """Sets a cookie in the client's cookie jar. The server name + is required and has to match the one that is also passed to + the open call. + """ + assert self.cookie_jar is not None, "cookies disabled" + header = dump_cookie( + key, + value, + max_age, + expires, + path, + domain, + secure, + httponly, + charset, + samesite=samesite, + ) + environ = create_environ(path, base_url=f"http://{server_name}") + headers = [("Set-Cookie", header)] + self.cookie_jar.extract_wsgi(environ, headers) + + def delete_cookie( + self, + server_name: str, + key: str, + path: str = "/", + domain: t.Optional[str] = None, + secure: bool = False, + httponly: bool = False, + samesite: t.Optional[str] = None, + ) -> None: + """Deletes a cookie in the test client.""" + self.set_cookie( + server_name, + key, + expires=0, + max_age=0, + path=path, + domain=domain, + secure=secure, + httponly=httponly, + samesite=samesite, + ) + + def run_wsgi_app( + self, environ: "WSGIEnvironment", buffered: bool = False + ) -> t.Tuple[t.Iterable[bytes], str, Headers]: + """Runs the wrapped WSGI app with the given environment. + + :meta private: + """ + if self.cookie_jar is not None: + self.cookie_jar.inject_wsgi(environ) + + rv = run_wsgi_app(self.application, environ, buffered=buffered) + + if self.cookie_jar is not None: + self.cookie_jar.extract_wsgi(environ, rv[2]) + + return rv + + def resolve_redirect( + self, response: "TestResponse", buffered: bool = False + ) -> "TestResponse": + """Perform a new request to the location given by the redirect + response to the previous request. + + :meta private: + """ + scheme, netloc, path, qs, anchor = url_parse(response.location) + builder = EnvironBuilder.from_environ( + response.request.environ, path=path, query_string=qs + ) + + to_name_parts = netloc.split(":", 1)[0].split(".") + from_name_parts = builder.server_name.split(".") + + if to_name_parts != [""]: + # The new location has a host, use it for the base URL. + builder.url_scheme = scheme + builder.host = netloc + else: + # A local redirect with autocorrect_location_header=False + # doesn't have a host, so use the request's host. + to_name_parts = from_name_parts + + # Explain why a redirect to a different server name won't be followed. + if to_name_parts != from_name_parts: + if to_name_parts[-len(from_name_parts) :] == from_name_parts: + if not self.allow_subdomain_redirects: + raise RuntimeError("Following subdomain redirects is not enabled.") + else: + raise RuntimeError("Following external redirects is not supported.") + + path_parts = path.split("/") + root_parts = builder.script_root.split("/") + + if path_parts[: len(root_parts)] == root_parts: + # Strip the script root from the path. + builder.path = path[len(builder.script_root) :] + else: + # The new location is not under the script root, so use the + # whole path and clear the previous root. + builder.path = path + builder.script_root = "" + + # Only 307 and 308 preserve all of the original request. + if response.status_code not in {307, 308}: + # HEAD is preserved, everything else becomes GET. + if builder.method != "HEAD": + builder.method = "GET" + + # Clear the body and the headers that describe it. + + if builder.input_stream is not None: + builder.input_stream.close() + builder.input_stream = None + + builder.content_type = None + builder.content_length = None + builder.headers.pop("Transfer-Encoding", None) + + return self.open(builder, buffered=buffered) + + def open( + self, + *args: t.Any, + buffered: bool = False, + follow_redirects: bool = False, + **kwargs: t.Any, + ) -> "TestResponse": + """Generate an environ dict from the given arguments, make a + request to the application using it, and return the response. + + :param args: Passed to :class:`EnvironBuilder` to create the + environ for the request. If a single arg is passed, it can + be an existing :class:`EnvironBuilder` or an environ dict. + :param buffered: Convert the iterator returned by the app into + a list. If the iterator has a ``close()`` method, it is + called automatically. + :param follow_redirects: Make additional requests to follow HTTP + redirects until a non-redirect status is returned. + :attr:`TestResponse.history` lists the intermediate + responses. + + .. versionchanged:: 2.1 + Removed the ``as_tuple`` parameter. + + .. versionchanged:: 2.0 + ``as_tuple`` is deprecated and will be removed in Werkzeug + 2.1. Use :attr:`TestResponse.request` and + ``request.environ`` instead. + + .. versionchanged:: 2.0 + The request input stream is closed when calling + ``response.close()``. Input streams for redirects are + automatically closed. + + .. versionchanged:: 0.5 + If a dict is provided as file in the dict for the ``data`` + parameter the content type has to be called ``content_type`` + instead of ``mimetype``. This change was made for + consistency with :class:`werkzeug.FileWrapper`. + + .. versionchanged:: 0.5 + Added the ``follow_redirects`` parameter. + """ + request: t.Optional["Request"] = None + + if not kwargs and len(args) == 1: + arg = args[0] + + if isinstance(arg, EnvironBuilder): + request = arg.get_request() + elif isinstance(arg, dict): + request = EnvironBuilder.from_environ(arg).get_request() + elif isinstance(arg, Request): + request = arg + + if request is None: + builder = EnvironBuilder(*args, **kwargs) + + try: + request = builder.get_request() + finally: + builder.close() + + response = self.run_wsgi_app(request.environ, buffered=buffered) + response = self.response_wrapper(*response, request=request) + + redirects = set() + history: t.List["TestResponse"] = [] + + if not follow_redirects: + return response + + while response.status_code in { + 301, + 302, + 303, + 305, + 307, + 308, + }: + # Exhaust intermediate response bodies to ensure middleware + # that returns an iterator runs any cleanup code. + if not buffered: + response.make_sequence() + response.close() + + new_redirect_entry = (response.location, response.status_code) + + if new_redirect_entry in redirects: + raise ClientRedirectError( + f"Loop detected: A {response.status_code} redirect" + f" to {response.location} was already made." + ) + + redirects.add(new_redirect_entry) + response.history = tuple(history) + history.append(response) + response = self.resolve_redirect(response, buffered=buffered) + else: + # This is the final request after redirects. + response.history = tuple(history) + # Close the input stream when closing the response, in case + # the input is an open temporary file. + response.call_on_close(request.input_stream.close) + return response + + def get(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``GET``.""" + kw["method"] = "GET" + return self.open(*args, **kw) + + def post(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``POST``.""" + kw["method"] = "POST" + return self.open(*args, **kw) + + def put(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``PUT``.""" + kw["method"] = "PUT" + return self.open(*args, **kw) + + def delete(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``DELETE``.""" + kw["method"] = "DELETE" + return self.open(*args, **kw) + + def patch(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``PATCH``.""" + kw["method"] = "PATCH" + return self.open(*args, **kw) + + def options(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``OPTIONS``.""" + kw["method"] = "OPTIONS" + return self.open(*args, **kw) + + def head(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``HEAD``.""" + kw["method"] = "HEAD" + return self.open(*args, **kw) + + def trace(self, *args: t.Any, **kw: t.Any) -> "TestResponse": + """Call :meth:`open` with ``method`` set to ``TRACE``.""" + kw["method"] = "TRACE" + return self.open(*args, **kw) + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.application!r}>" + + +def create_environ(*args: t.Any, **kwargs: t.Any) -> "WSGIEnvironment": + """Create a new WSGI environ dict based on the values passed. The first + parameter should be the path of the request which defaults to '/'. The + second one can either be an absolute path (in that case the host is + localhost:80) or a full path to the request with scheme, netloc port and + the path to the script. + + This accepts the same arguments as the :class:`EnvironBuilder` + constructor. + + .. versionchanged:: 0.5 + This function is now a thin wrapper over :class:`EnvironBuilder` which + was added in 0.5. The `headers`, `environ_base`, `environ_overrides` + and `charset` parameters were added. + """ + builder = EnvironBuilder(*args, **kwargs) + + try: + return builder.get_environ() + finally: + builder.close() + + +def run_wsgi_app( + app: "WSGIApplication", environ: "WSGIEnvironment", buffered: bool = False +) -> t.Tuple[t.Iterable[bytes], str, Headers]: + """Return a tuple in the form (app_iter, status, headers) of the + application output. This works best if you pass it an application that + returns an iterator all the time. + + Sometimes applications may use the `write()` callable returned + by the `start_response` function. This tries to resolve such edge + cases automatically. But if you don't get the expected output you + should set `buffered` to `True` which enforces buffering. + + If passed an invalid WSGI application the behavior of this function is + undefined. Never pass non-conforming WSGI applications to this function. + + :param app: the application to execute. + :param buffered: set to `True` to enforce buffering. + :return: tuple in the form ``(app_iter, status, headers)`` + """ + # Copy environ to ensure any mutations by the app (ProxyFix, for + # example) don't affect subsequent requests (such as redirects). + environ = _get_environ(environ).copy() + status: str + response: t.Optional[t.Tuple[str, t.List[t.Tuple[str, str]]]] = None + buffer: t.List[bytes] = [] + + def start_response(status, headers, exc_info=None): # type: ignore + nonlocal response + + if exc_info: + try: + raise exc_info[1].with_traceback(exc_info[2]) + finally: + exc_info = None + + response = (status, headers) + return buffer.append + + app_rv = app(environ, start_response) + close_func = getattr(app_rv, "close", None) + app_iter: t.Iterable[bytes] = iter(app_rv) + + # when buffering we emit the close call early and convert the + # application iterator into a regular list + if buffered: + try: + app_iter = list(app_iter) + finally: + if close_func is not None: + close_func() + + # otherwise we iterate the application iter until we have a response, chain + # the already received data with the already collected data and wrap it in + # a new `ClosingIterator` if we need to restore a `close` callable from the + # original return value. + else: + for item in app_iter: + buffer.append(item) + + if response is not None: + break + + if buffer: + app_iter = chain(buffer, app_iter) + + if close_func is not None and app_iter is not app_rv: + app_iter = ClosingIterator(app_iter, close_func) + + status, headers = response # type: ignore + return app_iter, status, Headers(headers) + + +class TestResponse(Response): + """:class:`~werkzeug.wrappers.Response` subclass that provides extra + information about requests made with the test :class:`Client`. + + Test client requests will always return an instance of this class. + If a custom response class is passed to the client, it is + subclassed along with this to support test information. + + If the test request included large files, or if the application is + serving a file, call :meth:`close` to close any open files and + prevent Python showing a ``ResourceWarning``. + + .. versionchanged:: 2.2 + Set the ``default_mimetype`` to None to prevent a mimetype being + assumed if missing. + + .. versionchanged:: 2.1 + Removed deprecated behavior for treating the response instance + as a tuple. + + .. versionadded:: 2.0 + Test client methods always return instances of this class. + """ + + default_mimetype = None + # Don't assume a mimetype, instead use whatever the response provides + + request: Request + """A request object with the environ used to make the request that + resulted in this response. + """ + + history: t.Tuple["TestResponse", ...] + """A list of intermediate responses. Populated when the test request + is made with ``follow_redirects`` enabled. + """ + + # Tell Pytest to ignore this, it's not a test class. + __test__ = False + + def __init__( + self, + response: t.Iterable[bytes], + status: str, + headers: Headers, + request: Request, + history: t.Tuple["TestResponse"] = (), # type: ignore + **kwargs: t.Any, + ) -> None: + super().__init__(response, status, headers, **kwargs) + self.request = request + self.history = history + self._compat_tuple = response, status, headers + + @cached_property + def text(self) -> str: + """The response data as text. A shortcut for + ``response.get_data(as_text=True)``. + + .. versionadded:: 2.1 + """ + return self.get_data(as_text=True) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/testapp.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/testapp.py new file mode 100644 index 00000000..0d7ffbb1 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/testapp.py @@ -0,0 +1,241 @@ +"""A small application that can be used to test a WSGI server and check +it for WSGI compliance. +""" +import base64 +import os +import sys +import typing as t +from textwrap import wrap + +from markupsafe import escape + +from . import __version__ as _werkzeug_version +from .wrappers.request import Request +from .wrappers.response import Response + +if t.TYPE_CHECKING: + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIEnvironment + + +logo = Response( + base64.b64decode( + """ +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 +=""" + ), + mimetype="image/png", +) + + +TEMPLATE = """\ + + +WSGI Information + +
    + +

    WSGI Information

    +

    + This page displays all available information about the WSGI server and + the underlying Python interpreter. +

    Python Interpreter

    + + + + + + +
    Python Version + %(python_version)s +
    Platform + %(platform)s [%(os)s] +
    API Version + %(api_version)s +
    Byteorder + %(byteorder)s +
    Werkzeug Version + %(werkzeug_version)s +
    +

    WSGI Environment

    + %(wsgi_env)s
    +

    Installed Eggs

    +

    + The following python packages were installed on the system as + Python eggs: +

      %(python_eggs)s
    +

    System Path

    +

    + The following paths are the current contents of the load path. The + following entries are looked up for Python packages. Note that not + all items in this path are folders. Gray and underlined items are + entries pointing to invalid resources or used by custom import hooks + such as the zip importer. +

    + Items with a bright background were expanded for display from a relative + path. If you encounter such paths in the output you might want to check + your setup as relative paths are usually problematic in multithreaded + environments. +

      %(sys_path)s
    +
    +""" + + +def iter_sys_path() -> t.Iterator[t.Tuple[str, bool, bool]]: + if os.name == "posix": + + def strip(x: str) -> str: + prefix = os.path.expanduser("~") + if x.startswith(prefix): + x = f"~{x[len(prefix) :]}" + return x + + else: + + def strip(x: str) -> str: + return x + + cwd = os.path.abspath(os.getcwd()) + for item in sys.path: + path = os.path.join(cwd, item or os.path.curdir) + yield strip(os.path.normpath(path)), not os.path.isdir(path), path != item + + +def render_testapp(req: Request) -> bytes: + try: + import pkg_resources + except ImportError: + eggs: t.Iterable[t.Any] = () + else: + eggs = sorted( + pkg_resources.working_set, + key=lambda x: x.project_name.lower(), # type: ignore + ) + python_eggs = [] + for egg in eggs: + try: + version = egg.version + except (ValueError, AttributeError): + version = "unknown" + python_eggs.append( + f"
  • {escape(egg.project_name)} [{escape(version)}]" + ) + + wsgi_env = [] + sorted_environ = sorted(req.environ.items(), key=lambda x: repr(x[0]).lower()) + for key, value in sorted_environ: + value = "".join(wrap(str(escape(repr(value))))) + wsgi_env.append(f"{escape(key)}{value}") + + sys_path = [] + for item, virtual, expanded in iter_sys_path(): + class_ = [] + if virtual: + class_.append("virtual") + if expanded: + class_.append("exp") + class_ = f' class="{" ".join(class_)}"' if class_ else "" + sys_path.append(f"{escape(item)}") + + return ( + TEMPLATE + % { + "python_version": "
    ".join(escape(sys.version).splitlines()), + "platform": escape(sys.platform), + "os": escape(os.name), + "api_version": sys.api_version, + "byteorder": sys.byteorder, + "werkzeug_version": _werkzeug_version, + "python_eggs": "\n".join(python_eggs), + "wsgi_env": "\n".join(wsgi_env), + "sys_path": "\n".join(sys_path), + } + ).encode("utf-8") + + +def test_app( + environ: "WSGIEnvironment", start_response: "StartResponse" +) -> t.Iterable[bytes]: + """Simple test application that dumps the environment. You can use + it to check if Werkzeug is working properly: + + .. sourcecode:: pycon + + >>> from werkzeug.serving import run_simple + >>> from werkzeug.testapp import test_app + >>> run_simple('localhost', 3000, test_app) + * Running on http://localhost:3000/ + + The application displays important information from the WSGI environment, + the Python interpreter and the installed libraries. + """ + req = Request(environ, populate_request=False) + if req.args.get("resource") == "logo": + response = logo + else: + response = Response(render_testapp(req), mimetype="text/html") + return response(environ, start_response) + + +if __name__ == "__main__": + from .serving import run_simple + + run_simple("localhost", 5000, test_app, use_reloader=True) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/urls.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/urls.py new file mode 100644 index 00000000..67c08b0b --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/urls.py @@ -0,0 +1,1067 @@ +"""Functions for working with URLs. + +Contains implementations of functions from :mod:`urllib.parse` that +handle bytes and strings. +""" +import codecs +import os +import re +import typing as t + +from ._internal import _check_str_tuple +from ._internal import _decode_idna +from ._internal import _encode_idna +from ._internal import _make_encode_wrapper +from ._internal import _to_str + +if t.TYPE_CHECKING: + from . import datastructures as ds + +# A regular expression for what a valid schema looks like +_scheme_re = re.compile(r"^[a-zA-Z0-9+-.]+$") + +# Characters that are safe in any part of an URL. +_always_safe = frozenset( + bytearray( + b"abcdefghijklmnopqrstuvwxyz" + b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" + b"0123456789" + b"-._~" + b"$!'()*+,;" # RFC3986 sub-delims set, not including query string delimiters &= + ) +) + +_hexdigits = "0123456789ABCDEFabcdef" +_hextobyte = { + f"{a}{b}".encode("ascii"): int(f"{a}{b}", 16) + for a in _hexdigits + for b in _hexdigits +} +_bytetohex = [f"%{char:02X}".encode("ascii") for char in range(256)] + + +class _URLTuple(t.NamedTuple): + scheme: str + netloc: str + path: str + query: str + fragment: str + + +class BaseURL(_URLTuple): + """Superclass of :py:class:`URL` and :py:class:`BytesURL`.""" + + __slots__ = () + _at: str + _colon: str + _lbracket: str + _rbracket: str + + def __str__(self) -> str: + return self.to_url() + + def replace(self, **kwargs: t.Any) -> "BaseURL": + """Return an URL with the same values, except for those parameters + given new values by whichever keyword arguments are specified.""" + return self._replace(**kwargs) + + @property + def host(self) -> t.Optional[str]: + """The host part of the URL if available, otherwise `None`. The + host is either the hostname or the IP address mentioned in the + URL. It will not contain the port. + """ + return self._split_host()[0] + + @property + def ascii_host(self) -> t.Optional[str]: + """Works exactly like :attr:`host` but will return a result that + is restricted to ASCII. If it finds a netloc that is not ASCII + it will attempt to idna decode it. This is useful for socket + operations when the URL might include internationalized characters. + """ + rv = self.host + if rv is not None and isinstance(rv, str): + try: + rv = _encode_idna(rv) # type: ignore + except UnicodeError: + rv = rv.encode("ascii", "ignore") # type: ignore + return _to_str(rv, "ascii", "ignore") + + @property + def port(self) -> t.Optional[int]: + """The port in the URL as an integer if it was present, `None` + otherwise. This does not fill in default ports. + """ + try: + rv = int(_to_str(self._split_host()[1])) + if 0 <= rv <= 65535: + return rv + except (ValueError, TypeError): + pass + return None + + @property + def auth(self) -> t.Optional[str]: + """The authentication part in the URL if available, `None` + otherwise. + """ + return self._split_netloc()[0] + + @property + def username(self) -> t.Optional[str]: + """The username if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a string. + """ + rv = self._split_auth()[0] + if rv is not None: + return _url_unquote_legacy(rv) + return None + + @property + def raw_username(self) -> t.Optional[str]: + """The username if it was part of the URL, `None` otherwise. + Unlike :attr:`username` this one is not being decoded. + """ + return self._split_auth()[0] + + @property + def password(self) -> t.Optional[str]: + """The password if it was part of the URL, `None` otherwise. + This undergoes URL decoding and will always be a string. + """ + rv = self._split_auth()[1] + if rv is not None: + return _url_unquote_legacy(rv) + return None + + @property + def raw_password(self) -> t.Optional[str]: + """The password if it was part of the URL, `None` otherwise. + Unlike :attr:`password` this one is not being decoded. + """ + return self._split_auth()[1] + + def decode_query(self, *args: t.Any, **kwargs: t.Any) -> "ds.MultiDict[str, str]": + """Decodes the query part of the URL. Ths is a shortcut for + calling :func:`url_decode` on the query argument. The arguments and + keyword arguments are forwarded to :func:`url_decode` unchanged. + """ + return url_decode(self.query, *args, **kwargs) + + def join(self, *args: t.Any, **kwargs: t.Any) -> "BaseURL": + """Joins this URL with another one. This is just a convenience + function for calling into :meth:`url_join` and then parsing the + return value again. + """ + return url_parse(url_join(self, *args, **kwargs)) + + def to_url(self) -> str: + """Returns a URL string or bytes depending on the type of the + information stored. This is just a convenience function + for calling :meth:`url_unparse` for this URL. + """ + return url_unparse(self) + + def encode_netloc(self) -> str: + """Encodes the netloc part to an ASCII safe URL as bytes.""" + rv = self.ascii_host or "" + if ":" in rv: + rv = f"[{rv}]" + port = self.port + if port is not None: + rv = f"{rv}:{port}" + auth = ":".join( + filter( + None, + [ + url_quote(self.raw_username or "", "utf-8", "strict", "/:%"), + url_quote(self.raw_password or "", "utf-8", "strict", "/:%"), + ], + ) + ) + if auth: + rv = f"{auth}@{rv}" + return rv + + def decode_netloc(self) -> str: + """Decodes the netloc part into a string.""" + rv = _decode_idna(self.host or "") + + if ":" in rv: + rv = f"[{rv}]" + port = self.port + if port is not None: + rv = f"{rv}:{port}" + auth = ":".join( + filter( + None, + [ + _url_unquote_legacy(self.raw_username or "", "/:%@"), + _url_unquote_legacy(self.raw_password or "", "/:%@"), + ], + ) + ) + if auth: + rv = f"{auth}@{rv}" + return rv + + def to_uri_tuple(self) -> "BaseURL": + """Returns a :class:`BytesURL` tuple that holds a URI. This will + encode all the information in the URL properly to ASCII using the + rules a web browser would follow. + + It's usually more interesting to directly call :meth:`iri_to_uri` which + will return a string. + """ + return url_parse(iri_to_uri(self)) + + def to_iri_tuple(self) -> "BaseURL": + """Returns a :class:`URL` tuple that holds a IRI. This will try + to decode as much information as possible in the URL without + losing information similar to how a web browser does it for the + URL bar. + + It's usually more interesting to directly call :meth:`uri_to_iri` which + will return a string. + """ + return url_parse(uri_to_iri(self)) + + def get_file_location( + self, pathformat: t.Optional[str] = None + ) -> t.Tuple[t.Optional[str], t.Optional[str]]: + """Returns a tuple with the location of the file in the form + ``(server, location)``. If the netloc is empty in the URL or + points to localhost, it's represented as ``None``. + + The `pathformat` by default is autodetection but needs to be set + when working with URLs of a specific system. The supported values + are ``'windows'`` when working with Windows or DOS paths and + ``'posix'`` when working with posix paths. + + If the URL does not point to a local file, the server and location + are both represented as ``None``. + + :param pathformat: The expected format of the path component. + Currently ``'windows'`` and ``'posix'`` are + supported. Defaults to ``None`` which is + autodetect. + """ + if self.scheme != "file": + return None, None + + path = url_unquote(self.path) + host = self.netloc or None + + if pathformat is None: + if os.name == "nt": + pathformat = "windows" + else: + pathformat = "posix" + + if pathformat == "windows": + if path[:1] == "/" and path[1:2].isalpha() and path[2:3] in "|:": + path = f"{path[1:2]}:{path[3:]}" + windows_share = path[:3] in ("\\" * 3, "/" * 3) + import ntpath + + path = ntpath.normpath(path) + # Windows shared drives are represented as ``\\host\\directory``. + # That results in a URL like ``file://///host/directory``, and a + # path like ``///host/directory``. We need to special-case this + # because the path contains the hostname. + if windows_share and host is None: + parts = path.lstrip("\\").split("\\", 1) + if len(parts) == 2: + host, path = parts + else: + host = parts[0] + path = "" + elif pathformat == "posix": + import posixpath + + path = posixpath.normpath(path) + else: + raise TypeError(f"Invalid path format {pathformat!r}") + + if host in ("127.0.0.1", "::1", "localhost"): + host = None + + return host, path + + def _split_netloc(self) -> t.Tuple[t.Optional[str], str]: + if self._at in self.netloc: + auth, _, netloc = self.netloc.partition(self._at) + return auth, netloc + return None, self.netloc + + def _split_auth(self) -> t.Tuple[t.Optional[str], t.Optional[str]]: + auth = self._split_netloc()[0] + if not auth: + return None, None + if self._colon not in auth: + return auth, None + + username, _, password = auth.partition(self._colon) + return username, password + + def _split_host(self) -> t.Tuple[t.Optional[str], t.Optional[str]]: + rv = self._split_netloc()[1] + if not rv: + return None, None + + if not rv.startswith(self._lbracket): + if self._colon in rv: + host, _, port = rv.partition(self._colon) + return host, port + return rv, None + + idx = rv.find(self._rbracket) + if idx < 0: + return rv, None + + host = rv[1:idx] + rest = rv[idx + 1 :] + if rest.startswith(self._colon): + return host, rest[1:] + return host, None + + +class URL(BaseURL): + """Represents a parsed URL. This behaves like a regular tuple but + also has some extra attributes that give further insight into the + URL. + """ + + __slots__ = () + _at = "@" + _colon = ":" + _lbracket = "[" + _rbracket = "]" + + def encode(self, charset: str = "utf-8", errors: str = "replace") -> "BytesURL": + """Encodes the URL to a tuple made out of bytes. The charset is + only being used for the path, query and fragment. + """ + return BytesURL( + self.scheme.encode("ascii"), # type: ignore + self.encode_netloc(), + self.path.encode(charset, errors), # type: ignore + self.query.encode(charset, errors), # type: ignore + self.fragment.encode(charset, errors), # type: ignore + ) + + +class BytesURL(BaseURL): + """Represents a parsed URL in bytes.""" + + __slots__ = () + _at = b"@" # type: ignore + _colon = b":" # type: ignore + _lbracket = b"[" # type: ignore + _rbracket = b"]" # type: ignore + + def __str__(self) -> str: + return self.to_url().decode("utf-8", "replace") # type: ignore + + def encode_netloc(self) -> bytes: # type: ignore + """Returns the netloc unchanged as bytes.""" + return self.netloc # type: ignore + + def decode(self, charset: str = "utf-8", errors: str = "replace") -> "URL": + """Decodes the URL to a tuple made out of strings. The charset is + only being used for the path, query and fragment. + """ + return URL( + self.scheme.decode("ascii"), # type: ignore + self.decode_netloc(), + self.path.decode(charset, errors), # type: ignore + self.query.decode(charset, errors), # type: ignore + self.fragment.decode(charset, errors), # type: ignore + ) + + +_unquote_maps: t.Dict[t.FrozenSet[int], t.Dict[bytes, int]] = {frozenset(): _hextobyte} + + +def _unquote_to_bytes( + string: t.Union[str, bytes], unsafe: t.Union[str, bytes] = "" +) -> bytes: + if isinstance(string, str): + string = string.encode("utf-8") + + if isinstance(unsafe, str): + unsafe = unsafe.encode("utf-8") + + unsafe = frozenset(bytearray(unsafe)) + groups = iter(string.split(b"%")) + result = bytearray(next(groups, b"")) + + try: + hex_to_byte = _unquote_maps[unsafe] + except KeyError: + hex_to_byte = _unquote_maps[unsafe] = { + h: b for h, b in _hextobyte.items() if b not in unsafe + } + + for group in groups: + code = group[:2] + + if code in hex_to_byte: + result.append(hex_to_byte[code]) + result.extend(group[2:]) + else: + result.append(37) # % + result.extend(group) + + return bytes(result) + + +def _url_encode_impl( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + charset: str, + sort: bool, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]], +) -> t.Iterator[str]: + from .datastructures import iter_multi_items + + iterable: t.Iterable[t.Tuple[str, str]] = iter_multi_items(obj) + + if sort: + iterable = sorted(iterable, key=key) + + for key_str, value_str in iterable: + if value_str is None: + continue + + if not isinstance(key_str, bytes): + key_bytes = str(key_str).encode(charset) + else: + key_bytes = key_str + + if not isinstance(value_str, bytes): + value_bytes = str(value_str).encode(charset) + else: + value_bytes = value_str + + yield f"{_fast_url_quote_plus(key_bytes)}={_fast_url_quote_plus(value_bytes)}" + + +def _url_unquote_legacy(value: str, unsafe: str = "") -> str: + try: + return url_unquote(value, charset="utf-8", errors="strict", unsafe=unsafe) + except UnicodeError: + return url_unquote(value, charset="latin1", unsafe=unsafe) + + +def url_parse( + url: str, scheme: t.Optional[str] = None, allow_fragments: bool = True +) -> BaseURL: + """Parses a URL from a string into a :class:`URL` tuple. If the URL + is lacking a scheme it can be provided as second argument. Otherwise, + it is ignored. Optionally fragments can be stripped from the URL + by setting `allow_fragments` to `False`. + + The inverse of this function is :func:`url_unparse`. + + :param url: the URL to parse. + :param scheme: the default schema to use if the URL is schemaless. + :param allow_fragments: if set to `False` a fragment will be removed + from the URL. + """ + s = _make_encode_wrapper(url) + is_text_based = isinstance(url, str) + + if scheme is None: + scheme = s("") + netloc = query = fragment = s("") + i = url.find(s(":")) + if i > 0 and _scheme_re.match(_to_str(url[:i], errors="replace")): + # make sure "iri" is not actually a port number (in which case + # "scheme" is really part of the path) + rest = url[i + 1 :] + if not rest or any(c not in s("0123456789") for c in rest): + # not a port number + scheme, url = url[:i].lower(), rest + + if url[:2] == s("//"): + delim = len(url) + for c in s("/?#"): + wdelim = url.find(c, 2) + if wdelim >= 0: + delim = min(delim, wdelim) + netloc, url = url[2:delim], url[delim:] + if (s("[") in netloc and s("]") not in netloc) or ( + s("]") in netloc and s("[") not in netloc + ): + raise ValueError("Invalid IPv6 URL") + + if allow_fragments and s("#") in url: + url, fragment = url.split(s("#"), 1) + if s("?") in url: + url, query = url.split(s("?"), 1) + + result_type = URL if is_text_based else BytesURL + return result_type(scheme, netloc, url, query, fragment) + + +def _make_fast_url_quote( + charset: str = "utf-8", + errors: str = "strict", + safe: t.Union[str, bytes] = "/:", + unsafe: t.Union[str, bytes] = "", +) -> t.Callable[[bytes], str]: + """Precompile the translation table for a URL encoding function. + + Unlike :func:`url_quote`, the generated function only takes the + string to quote. + + :param charset: The charset to encode the result with. + :param errors: How to handle encoding errors. + :param safe: An optional sequence of safe characters to never encode. + :param unsafe: An optional sequence of unsafe characters to always encode. + """ + if isinstance(safe, str): + safe = safe.encode(charset, errors) + + if isinstance(unsafe, str): + unsafe = unsafe.encode(charset, errors) + + safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) + table = [chr(c) if c in safe else f"%{c:02X}" for c in range(256)] + + def quote(string: bytes) -> str: + return "".join([table[c] for c in string]) + + return quote + + +_fast_url_quote = _make_fast_url_quote() +_fast_quote_plus = _make_fast_url_quote(safe=" ", unsafe="+") + + +def _fast_url_quote_plus(string: bytes) -> str: + return _fast_quote_plus(string).replace(" ", "+") + + +def url_quote( + string: t.Union[str, bytes], + charset: str = "utf-8", + errors: str = "strict", + safe: t.Union[str, bytes] = "/:", + unsafe: t.Union[str, bytes] = "", +) -> str: + """URL encode a single string with a given encoding. + + :param s: the string to quote. + :param charset: the charset to be used. + :param safe: an optional sequence of safe characters. + :param unsafe: an optional sequence of unsafe characters. + + .. versionadded:: 0.9.2 + The `unsafe` parameter was added. + """ + if not isinstance(string, (str, bytes, bytearray)): + string = str(string) + if isinstance(string, str): + string = string.encode(charset, errors) + if isinstance(safe, str): + safe = safe.encode(charset, errors) + if isinstance(unsafe, str): + unsafe = unsafe.encode(charset, errors) + safe = (frozenset(bytearray(safe)) | _always_safe) - frozenset(bytearray(unsafe)) + rv = bytearray() + for char in bytearray(string): + if char in safe: + rv.append(char) + else: + rv.extend(_bytetohex[char]) + return bytes(rv).decode(charset) + + +def url_quote_plus( + string: str, charset: str = "utf-8", errors: str = "strict", safe: str = "" +) -> str: + """URL encode a single string with the given encoding and convert + whitespace to "+". + + :param s: The string to quote. + :param charset: The charset to be used. + :param safe: An optional sequence of safe characters. + """ + return url_quote(string, charset, errors, safe + " ", "+").replace(" ", "+") + + +def url_unparse(components: t.Tuple[str, str, str, str, str]) -> str: + """The reverse operation to :meth:`url_parse`. This accepts arbitrary + as well as :class:`URL` tuples and returns a URL as a string. + + :param components: the parsed URL as tuple which should be converted + into a URL string. + """ + _check_str_tuple(components) + scheme, netloc, path, query, fragment = components + s = _make_encode_wrapper(scheme) + url = s("") + + # We generally treat file:///x and file:/x the same which is also + # what browsers seem to do. This also allows us to ignore a schema + # register for netloc utilization or having to differentiate between + # empty and missing netloc. + if netloc or (scheme and path.startswith(s("/"))): + if path and path[:1] != s("/"): + path = s("/") + path + url = s("//") + (netloc or s("")) + path + elif path: + url += path + if scheme: + url = scheme + s(":") + url + if query: + url = url + s("?") + query + if fragment: + url = url + s("#") + fragment + return url + + +def url_unquote( + s: t.Union[str, bytes], + charset: str = "utf-8", + errors: str = "replace", + unsafe: str = "", +) -> str: + """URL decode a single string with a given encoding. If the charset + is set to `None` no decoding is performed and raw bytes are + returned. + + :param s: the string to unquote. + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param errors: the error handling for the charset decoding. + """ + rv = _unquote_to_bytes(s, unsafe) + if charset is None: + return rv + return rv.decode(charset, errors) + + +def url_unquote_plus( + s: t.Union[str, bytes], charset: str = "utf-8", errors: str = "replace" +) -> str: + """URL decode a single string with the given `charset` and decode "+" to + whitespace. + + Per default encoding errors are ignored. If you want a different behavior + you can set `errors` to ``'replace'`` or ``'strict'``. + + :param s: The string to unquote. + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param errors: The error handling for the `charset` decoding. + """ + if isinstance(s, str): + s = s.replace("+", " ") + else: + s = s.replace(b"+", b" ") + return url_unquote(s, charset, errors) + + +def url_fix(s: str, charset: str = "utf-8") -> str: + r"""Sometimes you get an URL by a user that just isn't a real URL because + it contains unsafe characters like ' ' and so on. This function can fix + some of the problems in a similar way browsers handle data entered by the + user: + + >>> url_fix('http://de.wikipedia.org/wiki/Elf (Begriffskl\xe4rung)') + 'http://de.wikipedia.org/wiki/Elf%20(Begriffskl%C3%A4rung)' + + :param s: the string with the URL to fix. + :param charset: The target charset for the URL if the url was given + as a string. + """ + # First step is to switch to text processing and to convert + # backslashes (which are invalid in URLs anyways) to slashes. This is + # consistent with what Chrome does. + s = _to_str(s, charset, "replace").replace("\\", "/") + + # For the specific case that we look like a malformed windows URL + # we want to fix this up manually: + if s.startswith("file://") and s[7:8].isalpha() and s[8:10] in (":/", "|/"): + s = f"file:///{s[7:]}" + + url = url_parse(s) + path = url_quote(url.path, charset, safe="/%+$!*'(),") + qs = url_quote_plus(url.query, charset, safe=":&%=+$!*'(),") + anchor = url_quote_plus(url.fragment, charset, safe=":&%=+$!*'(),") + return url_unparse((url.scheme, url.encode_netloc(), path, qs, anchor)) + + +# not-unreserved characters remain quoted when unquoting to IRI +_to_iri_unsafe = "".join([chr(c) for c in range(128) if c not in _always_safe]) + + +def _codec_error_url_quote(e: UnicodeError) -> t.Tuple[str, int]: + """Used in :func:`uri_to_iri` after unquoting to re-quote any + invalid bytes. + """ + # the docs state that UnicodeError does have these attributes, + # but mypy isn't picking them up + out = _fast_url_quote(e.object[e.start : e.end]) # type: ignore + return out, e.end # type: ignore + + +codecs.register_error("werkzeug.url_quote", _codec_error_url_quote) + + +def uri_to_iri( + uri: t.Union[str, t.Tuple[str, str, str, str, str]], + charset: str = "utf-8", + errors: str = "werkzeug.url_quote", +) -> str: + """Convert a URI to an IRI. All valid UTF-8 characters are unquoted, + leaving all reserved and invalid characters quoted. If the URL has + a domain, it is decoded from Punycode. + + >>> uri_to_iri("http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF") + 'http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF' + + :param uri: The URI to convert. + :param charset: The encoding to encode unquoted bytes with. + :param errors: Error handler to use during ``bytes.encode``. By + default, invalid bytes are left quoted. + + .. versionchanged:: 0.15 + All reserved and invalid characters remain quoted. Previously, + only some reserved characters were preserved, and invalid bytes + were replaced instead of left quoted. + + .. versionadded:: 0.6 + """ + if isinstance(uri, tuple): + uri = url_unparse(uri) + + uri = url_parse(_to_str(uri, charset)) + path = url_unquote(uri.path, charset, errors, _to_iri_unsafe) + query = url_unquote(uri.query, charset, errors, _to_iri_unsafe) + fragment = url_unquote(uri.fragment, charset, errors, _to_iri_unsafe) + return url_unparse((uri.scheme, uri.decode_netloc(), path, query, fragment)) + + +# reserved characters remain unquoted when quoting to URI +_to_uri_safe = ":/?#[]@!$&'()*+,;=%" + + +def iri_to_uri( + iri: t.Union[str, t.Tuple[str, str, str, str, str]], + charset: str = "utf-8", + errors: str = "strict", + safe_conversion: bool = False, +) -> str: + """Convert an IRI to a URI. All non-ASCII and unsafe characters are + quoted. If the URL has a domain, it is encoded to Punycode. + + >>> iri_to_uri('http://\\u2603.net/p\\xe5th?q=\\xe8ry%DF') + 'http://xn--n3h.net/p%C3%A5th?q=%C3%A8ry%DF' + + :param iri: The IRI to convert. + :param charset: The encoding of the IRI. + :param errors: Error handler to use during ``bytes.encode``. + :param safe_conversion: Return the URL unchanged if it only contains + ASCII characters and no whitespace. See the explanation below. + + There is a general problem with IRI conversion with some protocols + that are in violation of the URI specification. Consider the + following two IRIs:: + + magnet:?xt=uri:whatever + itms-services://?action=download-manifest + + After parsing, we don't know if the scheme requires the ``//``, + which is dropped if empty, but conveys different meanings in the + final URL if it's present or not. In this case, you can use + ``safe_conversion``, which will return the URL unchanged if it only + contains ASCII characters and no whitespace. This can result in a + URI with unquoted characters if it was not already quoted correctly, + but preserves the URL's semantics. Werkzeug uses this for the + ``Location`` header for redirects. + + .. versionchanged:: 0.15 + All reserved characters remain unquoted. Previously, only some + reserved characters were left unquoted. + + .. versionchanged:: 0.9.6 + The ``safe_conversion`` parameter was added. + + .. versionadded:: 0.6 + """ + if isinstance(iri, tuple): + iri = url_unparse(iri) + + if safe_conversion: + # If we're not sure if it's safe to convert the URL, and it only + # contains ASCII characters, return it unconverted. + try: + native_iri = _to_str(iri) + ascii_iri = native_iri.encode("ascii") + + # Only return if it doesn't have whitespace. (Why?) + if len(ascii_iri.split()) == 1: + return native_iri + except UnicodeError: + pass + + iri = url_parse(_to_str(iri, charset, errors)) + path = url_quote(iri.path, charset, errors, _to_uri_safe) + query = url_quote(iri.query, charset, errors, _to_uri_safe) + fragment = url_quote(iri.fragment, charset, errors, _to_uri_safe) + return url_unparse((iri.scheme, iri.encode_netloc(), path, query, fragment)) + + +def url_decode( + s: t.AnyStr, + charset: str = "utf-8", + include_empty: bool = True, + errors: str = "replace", + separator: str = "&", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, +) -> "ds.MultiDict[str, str]": + """Parse a query string and return it as a :class:`MultiDict`. + + :param s: The query string to parse. + :param charset: Decode bytes to string with this charset. If not + given, bytes are returned as-is. + :param include_empty: Include keys with empty values in the dict. + :param errors: Error handling behavior when decoding bytes. + :param separator: Separator character between pairs. + :param cls: Container to hold result instead of :class:`MultiDict`. + + .. versionchanged:: 2.0 + The ``decode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + In previous versions ";" and "&" could be used for url decoding. + Now only "&" is supported. If you want to use ";", a different + ``separator`` can be provided. + + .. versionchanged:: 0.5 + The ``cls`` parameter was added. + """ + if cls is None: + from .datastructures import MultiDict # noqa: F811 + + cls = MultiDict + if isinstance(s, str) and not isinstance(separator, str): + separator = separator.decode(charset or "ascii") + elif isinstance(s, bytes) and not isinstance(separator, bytes): + separator = separator.encode(charset or "ascii") # type: ignore + return cls( + _url_decode_impl( + s.split(separator), charset, include_empty, errors # type: ignore + ) + ) + + +def url_decode_stream( + stream: t.IO[bytes], + charset: str = "utf-8", + include_empty: bool = True, + errors: str = "replace", + separator: bytes = b"&", + cls: t.Optional[t.Type["ds.MultiDict"]] = None, + limit: t.Optional[int] = None, +) -> "ds.MultiDict[str, str]": + """Works like :func:`url_decode` but decodes a stream. The behavior + of stream and limit follows functions like + :func:`~werkzeug.wsgi.make_line_iter`. The generator of pairs is + directly fed to the `cls` so you can consume the data while it's + parsed. + + :param stream: a stream with the encoded querystring + :param charset: the charset of the query string. If set to `None` + no decoding will take place. + :param include_empty: Set to `False` if you don't want empty values to + appear in the dict. + :param errors: the decoding error behavior. + :param separator: the pair separator to be used, defaults to ``&`` + :param cls: an optional dict class to use. If this is not specified + or `None` the default :class:`MultiDict` is used. + :param limit: the content length of the URL data. Not necessary if + a limited stream is provided. + + .. versionchanged:: 2.0 + The ``decode_keys`` and ``return_iterator`` parameters are + deprecated and will be removed in Werkzeug 2.1. + + .. versionadded:: 0.8 + """ + from .wsgi import make_chunk_iter + + pair_iter = make_chunk_iter(stream, separator, limit) + decoder = _url_decode_impl(pair_iter, charset, include_empty, errors) + + if cls is None: + from .datastructures import MultiDict # noqa: F811 + + cls = MultiDict + + return cls(decoder) + + +def _url_decode_impl( + pair_iter: t.Iterable[t.AnyStr], charset: str, include_empty: bool, errors: str +) -> t.Iterator[t.Tuple[str, str]]: + for pair in pair_iter: + if not pair: + continue + s = _make_encode_wrapper(pair) + equal = s("=") + if equal in pair: + key, value = pair.split(equal, 1) + else: + if not include_empty: + continue + key = pair + value = s("") + yield ( + url_unquote_plus(key, charset, errors), + url_unquote_plus(value, charset, errors), + ) + + +def url_encode( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + charset: str = "utf-8", + sort: bool = False, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]] = None, + separator: str = "&", +) -> str: + """URL encode a dict/`MultiDict`. If a value is `None` it will not appear + in the result string. Per default only values are encoded into the target + charset strings. + + :param obj: the object to encode into a query string. + :param charset: the charset of the query string. + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + + .. versionchanged:: 2.0 + The ``encode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + Added the ``sort``, ``key``, and ``separator`` parameters. + """ + separator = _to_str(separator, "ascii") + return separator.join(_url_encode_impl(obj, charset, sort, key)) + + +def url_encode_stream( + obj: t.Union[t.Mapping[str, str], t.Iterable[t.Tuple[str, str]]], + stream: t.Optional[t.IO[str]] = None, + charset: str = "utf-8", + sort: bool = False, + key: t.Optional[t.Callable[[t.Tuple[str, str]], t.Any]] = None, + separator: str = "&", +) -> None: + """Like :meth:`url_encode` but writes the results to a stream + object. If the stream is `None` a generator over all encoded + pairs is returned. + + :param obj: the object to encode into a query string. + :param stream: a stream to write the encoded object into or `None` if + an iterator over the encoded pairs should be returned. In + that case the separator argument is ignored. + :param charset: the charset of the query string. + :param sort: set to `True` if you want parameters to be sorted by `key`. + :param separator: the separator to be used for the pairs. + :param key: an optional function to be used for sorting. For more details + check out the :func:`sorted` documentation. + + .. versionchanged:: 2.0 + The ``encode_keys`` parameter is deprecated and will be removed + in Werkzeug 2.1. + + .. versionadded:: 0.8 + """ + separator = _to_str(separator, "ascii") + gen = _url_encode_impl(obj, charset, sort, key) + if stream is None: + return gen # type: ignore + for idx, chunk in enumerate(gen): + if idx: + stream.write(separator) + stream.write(chunk) + return None + + +def url_join( + base: t.Union[str, t.Tuple[str, str, str, str, str]], + url: t.Union[str, t.Tuple[str, str, str, str, str]], + allow_fragments: bool = True, +) -> str: + """Join a base URL and a possibly relative URL to form an absolute + interpretation of the latter. + + :param base: the base URL for the join operation. + :param url: the URL to join. + :param allow_fragments: indicates whether fragments should be allowed. + """ + if isinstance(base, tuple): + base = url_unparse(base) + if isinstance(url, tuple): + url = url_unparse(url) + + _check_str_tuple((base, url)) + s = _make_encode_wrapper(base) + + if not base: + return url + if not url: + return base + + bscheme, bnetloc, bpath, bquery, bfragment = url_parse( + base, allow_fragments=allow_fragments + ) + scheme, netloc, path, query, fragment = url_parse(url, bscheme, allow_fragments) + if scheme != bscheme: + return url + if netloc: + return url_unparse((scheme, netloc, path, query, fragment)) + netloc = bnetloc + + if path[:1] == s("/"): + segments = path.split(s("/")) + elif not path: + segments = bpath.split(s("/")) + if not query: + query = bquery + else: + segments = bpath.split(s("/"))[:-1] + path.split(s("/")) + + # If the rightmost part is "./" we want to keep the slash but + # remove the dot. + if segments[-1] == s("."): + segments[-1] = s("") + + # Resolve ".." and "." + segments = [segment for segment in segments if segment != s(".")] + while True: + i = 1 + n = len(segments) - 1 + while i < n: + if segments[i] == s("..") and segments[i - 1] not in (s(""), s("..")): + del segments[i - 1 : i + 1] + break + i += 1 + else: + break + + # Remove trailing ".." if the URL is absolute + unwanted_marker = [s(""), s("..")] + while segments[:2] == unwanted_marker: + del segments[1] + + path = s("/").join(segments) + return url_unparse((scheme, netloc, path, query, fragment)) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/user_agent.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/user_agent.py new file mode 100644 index 00000000..66ffcbe0 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/user_agent.py @@ -0,0 +1,47 @@ +import typing as t + + +class UserAgent: + """Represents a parsed user agent header value. + + The default implementation does no parsing, only the :attr:`string` + attribute is set. A subclass may parse the string to set the + common attributes or expose other information. Set + :attr:`werkzeug.wrappers.Request.user_agent_class` to use a + subclass. + + :param string: The header value to parse. + + .. versionadded:: 2.0 + This replaces the previous ``useragents`` module, but does not + provide a built-in parser. + """ + + platform: t.Optional[str] = None + """The OS name, if it could be parsed from the string.""" + + browser: t.Optional[str] = None + """The browser name, if it could be parsed from the string.""" + + version: t.Optional[str] = None + """The browser version, if it could be parsed from the string.""" + + language: t.Optional[str] = None + """The browser language, if it could be parsed from the string.""" + + def __init__(self, string: str) -> None: + self.string: str = string + """The original header value.""" + + def __repr__(self) -> str: + return f"<{type(self).__name__} {self.browser}/{self.version}>" + + def __str__(self) -> str: + return self.string + + def __bool__(self) -> bool: + return bool(self.browser) + + def to_header(self) -> str: + """Convert to a header value.""" + return self.string diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/utils.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/utils.py new file mode 100644 index 00000000..4ef58371 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/utils.py @@ -0,0 +1,706 @@ +import io +import mimetypes +import os +import pkgutil +import re +import sys +import typing as t +import unicodedata +from datetime import datetime +from time import time +from zlib import adler32 + +from markupsafe import escape + +from ._internal import _DictAccessorProperty +from ._internal import _missing +from ._internal import _TAccessorValue +from .datastructures import Headers +from .exceptions import NotFound +from .exceptions import RequestedRangeNotSatisfiable +from .security import safe_join +from .urls import url_quote +from .wsgi import wrap_file + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIEnvironment + from .wrappers.request import Request + from .wrappers.response import Response + +_T = t.TypeVar("_T") + +_entity_re = re.compile(r"&([^;]+);") +_filename_ascii_strip_re = re.compile(r"[^A-Za-z0-9_.-]") +_windows_device_files = ( + "CON", + "AUX", + "COM1", + "COM2", + "COM3", + "COM4", + "LPT1", + "LPT2", + "LPT3", + "PRN", + "NUL", +) + + +class cached_property(property, t.Generic[_T]): + """A :func:`property` that is only evaluated once. Subsequent access + returns the cached value. Setting the property sets the cached + value. Deleting the property clears the cached value, accessing it + again will evaluate it again. + + .. code-block:: python + + class Example: + @cached_property + def value(self): + # calculate something important here + return 42 + + e = Example() + e.value # evaluates + e.value # uses cache + e.value = 16 # sets cache + del e.value # clears cache + + If the class defines ``__slots__``, it must add ``_cache_{name}`` as + a slot. Alternatively, it can add ``__dict__``, but that's usually + not desirable. + + .. versionchanged:: 2.1 + Works with ``__slots__``. + + .. versionchanged:: 2.0 + ``del obj.name`` clears the cached value. + """ + + def __init__( + self, + fget: t.Callable[[t.Any], _T], + name: t.Optional[str] = None, + doc: t.Optional[str] = None, + ) -> None: + super().__init__(fget, doc=doc) + self.__name__ = name or fget.__name__ + self.slot_name = f"_cache_{self.__name__}" + self.__module__ = fget.__module__ + + def __set__(self, obj: object, value: _T) -> None: + if hasattr(obj, "__dict__"): + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + def __get__(self, obj: object, type: type = None) -> _T: # type: ignore + if obj is None: + return self # type: ignore + + obj_dict = getattr(obj, "__dict__", None) + + if obj_dict is not None: + value: _T = obj_dict.get(self.__name__, _missing) + else: + value = getattr(obj, self.slot_name, _missing) # type: ignore[arg-type] + + if value is _missing: + value = self.fget(obj) # type: ignore + + if obj_dict is not None: + obj.__dict__[self.__name__] = value + else: + setattr(obj, self.slot_name, value) + + return value + + def __delete__(self, obj: object) -> None: + if hasattr(obj, "__dict__"): + del obj.__dict__[self.__name__] + else: + setattr(obj, self.slot_name, _missing) + + +class environ_property(_DictAccessorProperty[_TAccessorValue]): + """Maps request attributes to environment variables. This works not only + for the Werkzeug request object, but also any other class with an + environ attribute: + + >>> class Test(object): + ... environ = {'key': 'value'} + ... test = environ_property('key') + >>> var = Test() + >>> var.test + 'value' + + If you pass it a second value it's used as default if the key does not + exist, the third one can be a converter that takes a value and converts + it. If it raises :exc:`ValueError` or :exc:`TypeError` the default value + is used. If no default value is provided `None` is used. + + Per default the property is read only. You have to explicitly enable it + by passing ``read_only=False`` to the constructor. + """ + + read_only = True + + def lookup(self, obj: "Request") -> "WSGIEnvironment": + return obj.environ + + +class header_property(_DictAccessorProperty[_TAccessorValue]): + """Like `environ_property` but for headers.""" + + def lookup(self, obj: t.Union["Request", "Response"]) -> Headers: + return obj.headers + + +# https://cgit.freedesktop.org/xdg/shared-mime-info/tree/freedesktop.org.xml.in +# https://www.iana.org/assignments/media-types/media-types.xhtml +# Types listed in the XDG mime info that have a charset in the IANA registration. +_charset_mimetypes = { + "application/ecmascript", + "application/javascript", + "application/sql", + "application/xml", + "application/xml-dtd", + "application/xml-external-parsed-entity", +} + + +def get_content_type(mimetype: str, charset: str) -> str: + """Returns the full content type string with charset for a mimetype. + + If the mimetype represents text, the charset parameter will be + appended, otherwise the mimetype is returned unchanged. + + :param mimetype: The mimetype to be used as content type. + :param charset: The charset to be appended for text mimetypes. + :return: The content type. + + .. versionchanged:: 0.15 + Any type that ends with ``+xml`` gets a charset, not just those + that start with ``application/``. Known text types such as + ``application/javascript`` are also given charsets. + """ + if ( + mimetype.startswith("text/") + or mimetype in _charset_mimetypes + or mimetype.endswith("+xml") + ): + mimetype += f"; charset={charset}" + + return mimetype + + +def secure_filename(filename: str) -> str: + r"""Pass it a filename and it will return a secure version of it. This + filename can then safely be stored on a regular file system and passed + to :func:`os.path.join`. The filename returned is an ASCII only string + for maximum portability. + + On windows systems the function also makes sure that the file is not + named after one of the special device files. + + >>> secure_filename("My cool movie.mov") + 'My_cool_movie.mov' + >>> secure_filename("../../../etc/passwd") + 'etc_passwd' + >>> secure_filename('i contain cool \xfcml\xe4uts.txt') + 'i_contain_cool_umlauts.txt' + + The function might return an empty filename. It's your responsibility + to ensure that the filename is unique and that you abort or + generate a random filename if the function returned an empty one. + + .. versionadded:: 0.5 + + :param filename: the filename to secure + """ + filename = unicodedata.normalize("NFKD", filename) + filename = filename.encode("ascii", "ignore").decode("ascii") + + for sep in os.sep, os.path.altsep: + if sep: + filename = filename.replace(sep, " ") + filename = str(_filename_ascii_strip_re.sub("", "_".join(filename.split()))).strip( + "._" + ) + + # on nt a couple of special files are present in each folder. We + # have to ensure that the target file is not such a filename. In + # this case we prepend an underline + if ( + os.name == "nt" + and filename + and filename.split(".")[0].upper() in _windows_device_files + ): + filename = f"_{filename}" + + return filename + + +def redirect( + location: str, code: int = 302, Response: t.Optional[t.Type["Response"]] = None +) -> "Response": + """Returns a response object (a WSGI application) that, if called, + redirects the client to the target location. Supported codes are + 301, 302, 303, 305, 307, and 308. 300 is not supported because + it's not a real redirect and 304 because it's the answer for a + request with a request with defined If-Modified-Since headers. + + .. versionadded:: 0.6 + The location can now be a unicode string that is encoded using + the :func:`iri_to_uri` function. + + .. versionadded:: 0.10 + The class used for the Response object can now be passed in. + + :param location: the location the response should redirect to. + :param code: the redirect status code. defaults to 302. + :param class Response: a Response class to use when instantiating a + response. The default is :class:`werkzeug.wrappers.Response` if + unspecified. + """ + if Response is None: + from .wrappers import Response # type: ignore + + display_location = escape(location) + if isinstance(location, str): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + from .urls import iri_to_uri + + location = iri_to_uri(location, safe_conversion=True) + + response = Response( # type: ignore + "\n" + "\n" + "Redirecting...\n" + "

    Redirecting...

    \n" + "

    You should be redirected automatically to the target URL: " + f'{display_location}. If' + " not, click the link.\n", + code, + mimetype="text/html", + ) + response.headers["Location"] = location + return response + + +def append_slash_redirect(environ: "WSGIEnvironment", code: int = 308) -> "Response": + """Redirect to the current URL with a slash appended. + + If the current URL is ``/user/42``, the redirect URL will be + ``42/``. When joined to the current URL during response + processing or by the browser, this will produce ``/user/42/``. + + The behavior is undefined if the path ends with a slash already. If + called unconditionally on a URL, it may produce a redirect loop. + + :param environ: Use the path and query from this WSGI environment + to produce the redirect URL. + :param code: the status code for the redirect. + + .. versionchanged:: 2.1 + Produce a relative URL that only modifies the last segment. + Relevant when the current path has multiple segments. + + .. versionchanged:: 2.1 + The default status code is 308 instead of 301. This preserves + the request method and body. + """ + tail = environ["PATH_INFO"].rpartition("/")[2] + + if not tail: + new_path = "./" + else: + new_path = f"{tail}/" + + query_string = environ.get("QUERY_STRING") + + if query_string: + new_path = f"{new_path}?{query_string}" + + return redirect(new_path, code) + + +def send_file( + path_or_file: t.Union[os.PathLike, str, t.IO[bytes]], + environ: "WSGIEnvironment", + mimetype: t.Optional[str] = None, + as_attachment: bool = False, + download_name: t.Optional[str] = None, + conditional: bool = True, + etag: t.Union[bool, str] = True, + last_modified: t.Optional[t.Union[datetime, int, float]] = None, + max_age: t.Optional[ + t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]] + ] = None, + use_x_sendfile: bool = False, + response_class: t.Optional[t.Type["Response"]] = None, + _root_path: t.Optional[t.Union[os.PathLike, str]] = None, +) -> "Response": + """Send the contents of a file to the client. + + The first argument can be a file path or a file-like object. Paths + are preferred in most cases because Werkzeug can manage the file and + get extra information from the path. Passing a file-like object + requires that the file is opened in binary mode, and is mostly + useful when building a file in memory with :class:`io.BytesIO`. + + Never pass file paths provided by a user. The path is assumed to be + trusted, so a user could craft a path to access a file you didn't + intend. Use :func:`send_from_directory` to safely serve user-provided paths. + + If the WSGI server sets a ``file_wrapper`` in ``environ``, it is + used, otherwise Werkzeug's built-in wrapper is used. Alternatively, + if the HTTP server supports ``X-Sendfile``, ``use_x_sendfile=True`` + will tell the server to send the given path, which is much more + efficient than reading it in Python. + + :param path_or_file: The path to the file to send, relative to the + current working directory if a relative path is given. + Alternatively, a file-like object opened in binary mode. Make + sure the file pointer is seeked to the start of the data. + :param environ: The WSGI environ for the current request. + :param mimetype: The MIME type to send for the file. If not + provided, it will try to detect it from the file name. + :param as_attachment: Indicate to a browser that it should offer to + save the file instead of displaying it. + :param download_name: The default name browsers will use when saving + the file. Defaults to the passed file name. + :param conditional: Enable conditional and range responses based on + request headers. Requires passing a file path and ``environ``. + :param etag: Calculate an ETag for the file, which requires passing + a file path. Can also be a string to use instead. + :param last_modified: The last modified time to send for the file, + in seconds. If not provided, it will try to detect it from the + file path. + :param max_age: How long the client should cache the file, in + seconds. If set, ``Cache-Control`` will be ``public``, otherwise + it will be ``no-cache`` to prefer conditional caching. + :param use_x_sendfile: Set the ``X-Sendfile`` header to let the + server to efficiently send the file. Requires support from the + HTTP server. Requires passing a file path. + :param response_class: Build the response using this class. Defaults + to :class:`~werkzeug.wrappers.Response`. + :param _root_path: Do not use. For internal use only. Use + :func:`send_from_directory` to safely send files under a path. + + .. versionchanged:: 2.0.2 + ``send_file`` only sets a detected ``Content-Encoding`` if + ``as_attachment`` is disabled. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + + .. versionchanged:: 2.0 + ``download_name`` replaces Flask's ``attachment_filename`` + parameter. If ``as_attachment=False``, it is passed with + ``Content-Disposition: inline`` instead. + + .. versionchanged:: 2.0 + ``max_age`` replaces Flask's ``cache_timeout`` parameter. + ``conditional`` is enabled and ``max_age`` is not set by + default. + + .. versionchanged:: 2.0 + ``etag`` replaces Flask's ``add_etags`` parameter. It can be a + string to use instead of generating one. + + .. versionchanged:: 2.0 + If an encoding is returned when guessing ``mimetype`` from + ``download_name``, set the ``Content-Encoding`` header. + """ + if response_class is None: + from .wrappers import Response + + response_class = Response + + path: t.Optional[str] = None + file: t.Optional[t.IO[bytes]] = None + size: t.Optional[int] = None + mtime: t.Optional[float] = None + headers = Headers() + + if isinstance(path_or_file, (os.PathLike, str)) or hasattr( + path_or_file, "__fspath__" + ): + path_or_file = t.cast(t.Union[os.PathLike, str], path_or_file) + + # Flask will pass app.root_path, allowing its send_file wrapper + # to not have to deal with paths. + if _root_path is not None: + path = os.path.join(_root_path, path_or_file) + else: + path = os.path.abspath(path_or_file) + + stat = os.stat(path) + size = stat.st_size + mtime = stat.st_mtime + else: + file = path_or_file + + if download_name is None and path is not None: + download_name = os.path.basename(path) + + if mimetype is None: + if download_name is None: + raise TypeError( + "Unable to detect the MIME type because a file name is" + " not available. Either set 'download_name', pass a" + " path instead of a file, or set 'mimetype'." + ) + + mimetype, encoding = mimetypes.guess_type(download_name) + + if mimetype is None: + mimetype = "application/octet-stream" + + # Don't send encoding for attachments, it causes browsers to + # save decompress tar.gz files. + if encoding is not None and not as_attachment: + headers.set("Content-Encoding", encoding) + + if download_name is not None: + try: + download_name.encode("ascii") + except UnicodeEncodeError: + simple = unicodedata.normalize("NFKD", download_name) + simple = simple.encode("ascii", "ignore").decode("ascii") + quoted = url_quote(download_name, safe="") + names = {"filename": simple, "filename*": f"UTF-8''{quoted}"} + else: + names = {"filename": download_name} + + value = "attachment" if as_attachment else "inline" + headers.set("Content-Disposition", value, **names) + elif as_attachment: + raise TypeError( + "No name provided for attachment. Either set" + " 'download_name' or pass a path instead of a file." + ) + + if use_x_sendfile and path is not None: + headers["X-Sendfile"] = path + data = None + else: + if file is None: + file = open(path, "rb") # type: ignore + elif isinstance(file, io.BytesIO): + size = file.getbuffer().nbytes + elif isinstance(file, io.TextIOBase): + raise ValueError("Files must be opened in binary mode or use BytesIO.") + + data = wrap_file(environ, file) + + rv = response_class( + data, mimetype=mimetype, headers=headers, direct_passthrough=True + ) + + if size is not None: + rv.content_length = size + + if last_modified is not None: + rv.last_modified = last_modified # type: ignore + elif mtime is not None: + rv.last_modified = mtime # type: ignore + + rv.cache_control.no_cache = True + + # Flask will pass app.get_send_file_max_age, allowing its send_file + # wrapper to not have to deal with paths. + if callable(max_age): + max_age = max_age(path) + + if max_age is not None: + if max_age > 0: + rv.cache_control.no_cache = None + rv.cache_control.public = True + + rv.cache_control.max_age = max_age + rv.expires = int(time() + max_age) # type: ignore + + if isinstance(etag, str): + rv.set_etag(etag) + elif etag and path is not None: + check = adler32(path.encode("utf-8")) & 0xFFFFFFFF + rv.set_etag(f"{mtime}-{size}-{check}") + + if conditional: + try: + rv = rv.make_conditional(environ, accept_ranges=True, complete_length=size) + except RequestedRangeNotSatisfiable: + if file is not None: + file.close() + + raise + + # Some x-sendfile implementations incorrectly ignore the 304 + # status code and send the file anyway. + if rv.status_code == 304: + rv.headers.pop("x-sendfile", None) + + return rv + + +def send_from_directory( + directory: t.Union[os.PathLike, str], + path: t.Union[os.PathLike, str], + environ: "WSGIEnvironment", + **kwargs: t.Any, +) -> "Response": + """Send a file from within a directory using :func:`send_file`. + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + returns a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under. This *must not* + be a value provided by the client, otherwise it becomes insecure. + :param path: The path to the file to send, relative to ``directory``. This is the + part of the path provided by the client, which is checked for security. + :param environ: The WSGI environ for the current request. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionadded:: 2.0 + Adapted from Flask's implementation. + """ + path = safe_join(os.fspath(directory), os.fspath(path)) + + if path is None: + raise NotFound() + + # Flask will pass app.root_path, allowing its send_from_directory + # wrapper to not have to deal with paths. + if "_root_path" in kwargs: + path = os.path.join(kwargs["_root_path"], path) + + try: + if not os.path.isfile(path): + raise NotFound() + except ValueError: + # path contains null byte on Python < 3.8 + raise NotFound() from None + + return send_file(path, environ, **kwargs) + + +def import_string(import_name: str, silent: bool = False) -> t.Any: + """Imports an object based on a string. This is useful if you want to + use import paths as endpoints or something similar. An import path can + be specified either in dotted notation (``xml.sax.saxutils.escape``) + or with a colon as object delimiter (``xml.sax.saxutils:escape``). + + If `silent` is True the return value will be `None` if the import fails. + + :param import_name: the dotted name for the object to import. + :param silent: if set to `True` import errors are ignored and + `None` is returned instead. + :return: imported object + """ + import_name = import_name.replace(":", ".") + try: + try: + __import__(import_name) + except ImportError: + if "." not in import_name: + raise + else: + return sys.modules[import_name] + + module_name, obj_name = import_name.rsplit(".", 1) + module = __import__(module_name, globals(), locals(), [obj_name]) + try: + return getattr(module, obj_name) + except AttributeError as e: + raise ImportError(e) from None + + except ImportError as e: + if not silent: + raise ImportStringError(import_name, e).with_traceback( + sys.exc_info()[2] + ) from None + + return None + + +def find_modules( + import_path: str, include_packages: bool = False, recursive: bool = False +) -> t.Iterator[str]: + """Finds all the modules below a package. This can be useful to + automatically import all views / controllers so that their metaclasses / + function decorators have a chance to register themselves on the + application. + + Packages are not returned unless `include_packages` is `True`. This can + also recursively list modules but in that case it will import all the + packages to get the correct load path of that module. + + :param import_path: the dotted name for the package to find child modules. + :param include_packages: set to `True` if packages should be returned, too. + :param recursive: set to `True` if recursion should happen. + :return: generator + """ + module = import_string(import_path) + path = getattr(module, "__path__", None) + if path is None: + raise ValueError(f"{import_path!r} is not a package") + basename = f"{module.__name__}." + for _importer, modname, ispkg in pkgutil.iter_modules(path): + modname = basename + modname + if ispkg: + if include_packages: + yield modname + if recursive: + yield from find_modules(modname, include_packages, True) + else: + yield modname + + +class ImportStringError(ImportError): + """Provides information about a failed :func:`import_string` attempt.""" + + #: String in dotted notation that failed to be imported. + import_name: str + #: Wrapped exception. + exception: BaseException + + def __init__(self, import_name: str, exception: BaseException) -> None: + self.import_name = import_name + self.exception = exception + msg = import_name + name = "" + tracked = [] + for part in import_name.replace(":", ".").split("."): + name = f"{name}.{part}" if name else part + imported = import_string(name, silent=True) + if imported: + tracked.append((name, getattr(imported, "__file__", None))) + else: + track = [f"- {n!r} found in {i!r}." for n, i in tracked] + track.append(f"- {name!r} not found.") + track_str = "\n".join(track) + msg = ( + f"import_string() failed for {import_name!r}. Possible reasons" + f" are:\n\n" + "- missing __init__.py in a package;\n" + "- package or module path not included in sys.path;\n" + "- duplicated package or module name taking precedence in" + " sys.path;\n" + "- missing module, class, function or variable;\n\n" + f"Debugged import:\n\n{track_str}\n\n" + f"Original exception:\n\n{type(exception).__name__}: {exception}" + ) + break + + super().__init__(msg) + + def __repr__(self) -> str: + return f"<{type(self).__name__}({self.import_name!r}, {self.exception!r})>" diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py new file mode 100644 index 00000000..b8c45d71 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__init__.py @@ -0,0 +1,3 @@ +from .request import Request as Request +from .response import Response as Response +from .response import ResponseStream diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 00000000..c3212ffc Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/request.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/request.cpython-310.pyc new file mode 100644 index 00000000..dc9ade62 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/request.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/response.cpython-310.pyc b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/response.cpython-310.pyc new file mode 100644 index 00000000..0f55ee11 Binary files /dev/null and b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/__pycache__/response.cpython-310.pyc differ diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/request.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/request.py new file mode 100644 index 00000000..2de77df4 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/request.py @@ -0,0 +1,634 @@ +import functools +import json +import typing +import typing as t +from io import BytesIO + +from .._internal import _wsgi_decoding_dance +from ..datastructures import CombinedMultiDict +from ..datastructures import EnvironHeaders +from ..datastructures import FileStorage +from ..datastructures import ImmutableMultiDict +from ..datastructures import iter_multi_items +from ..datastructures import MultiDict +from ..formparser import default_stream_factory +from ..formparser import FormDataParser +from ..sansio.request import Request as _SansIORequest +from ..utils import cached_property +from ..utils import environ_property +from ..wsgi import _get_server +from ..wsgi import get_input_stream +from werkzeug.exceptions import BadRequest + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +class Request(_SansIORequest): + """Represents an incoming WSGI HTTP request, with headers and body + taken from the WSGI environment. Has properties and methods for + using the functionality defined by various HTTP specs. The data in + requests object is read-only. + + Text data is assumed to use UTF-8 encoding, which should be true for + the vast majority of modern clients. Using an encoding set by the + client is unsafe in Python due to extra encodings it provides, such + as ``zip``. To change the assumed encoding, subclass and replace + :attr:`charset`. + + :param environ: The WSGI environ is generated by the WSGI server and + contains information about the server configuration and client + request. + :param populate_request: Add this request object to the WSGI environ + as ``environ['werkzeug.request']``. Can be useful when + debugging. + :param shallow: Makes reading from :attr:`stream` (and any method + that would read from it) raise a :exc:`RuntimeError`. Useful to + prevent consuming the form data in middleware, which would make + it unavailable to the final application. + + .. versionchanged:: 2.1 + Remove the ``disable_data_descriptor`` attribute. + + .. versionchanged:: 2.0 + Combine ``BaseRequest`` and mixins into a single ``Request`` + class. Using the old classes is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + Read-only mode is enforced with immutable classes for all data. + """ + + #: the maximum content length. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: parsing fails because more than the specified value is transmitted + #: a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :doc:`/request_data` for more details. + #: + #: .. versionadded:: 0.5 + max_content_length: t.Optional[int] = None + + #: the maximum form field size. This is forwarded to the form data + #: parsing function (:func:`parse_form_data`). When set and the + #: :attr:`form` or :attr:`files` attribute is accessed and the + #: data in memory for post data is longer than the specified value a + #: :exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception is raised. + #: + #: Have a look at :doc:`/request_data` for more details. + #: + #: .. versionadded:: 0.5 + max_form_memory_size: t.Optional[int] = None + + #: The maximum number of multipart parts to parse, passed to + #: :attr:`form_data_parser_class`. Parsing form data with more than this + #: many parts will raise :exc:`~.RequestEntityTooLarge`. + #: + #: .. versionadded:: 2.2.3 + max_form_parts = 1000 + + #: The form data parser that should be used. Can be replaced to customize + #: the form date parsing. + form_data_parser_class: t.Type[FormDataParser] = FormDataParser + + #: The WSGI environment containing HTTP headers and information from + #: the WSGI server. + environ: "WSGIEnvironment" + + #: Set when creating the request object. If ``True``, reading from + #: the request body will cause a ``RuntimeException``. Useful to + #: prevent modifying the stream from middleware. + shallow: bool + + def __init__( + self, + environ: "WSGIEnvironment", + populate_request: bool = True, + shallow: bool = False, + ) -> None: + super().__init__( + method=environ.get("REQUEST_METHOD", "GET"), + scheme=environ.get("wsgi.url_scheme", "http"), + server=_get_server(environ), + root_path=_wsgi_decoding_dance( + environ.get("SCRIPT_NAME") or "", self.charset, self.encoding_errors + ), + path=_wsgi_decoding_dance( + environ.get("PATH_INFO") or "", self.charset, self.encoding_errors + ), + query_string=environ.get("QUERY_STRING", "").encode("latin1"), + headers=EnvironHeaders(environ), + remote_addr=environ.get("REMOTE_ADDR"), + ) + self.environ = environ + self.shallow = shallow + + if populate_request and not shallow: + self.environ["werkzeug.request"] = self + + @classmethod + def from_values(cls, *args: t.Any, **kwargs: t.Any) -> "Request": + """Create a new request object based on the values provided. If + environ is given missing values are filled from there. This method is + useful for small scripts when you need to simulate a request from an URL. + Do not use this method for unittesting, there is a full featured client + object (:class:`Client`) that allows to create multipart requests, + support for cookies etc. + + This accepts the same options as the + :class:`~werkzeug.test.EnvironBuilder`. + + .. versionchanged:: 0.5 + This method now accepts the same arguments as + :class:`~werkzeug.test.EnvironBuilder`. Because of this the + `environ` parameter is now called `environ_overrides`. + + :return: request object + """ + from ..test import EnvironBuilder + + charset = kwargs.pop("charset", cls.charset) + kwargs["charset"] = charset + builder = EnvironBuilder(*args, **kwargs) + try: + return builder.get_request(cls) + finally: + builder.close() + + @classmethod + def application( + cls, f: t.Callable[["Request"], "WSGIApplication"] + ) -> "WSGIApplication": + """Decorate a function as responder that accepts the request as + the last argument. This works like the :func:`responder` + decorator but the function is passed the request object as the + last argument and the request object will be closed + automatically:: + + @Request.application + def my_wsgi_app(request): + return Response('Hello World!') + + As of Werkzeug 0.14 HTTP exceptions are automatically caught and + converted to responses instead of failing. + + :param f: the WSGI callable to decorate + :return: a new WSGI callable + """ + #: return a callable that wraps the -2nd argument with the request + #: and calls the function with all the arguments up to that one and + #: the request. The return value is then called with the latest + #: two arguments. This makes it possible to use this decorator for + #: both standalone WSGI functions as well as bound methods and + #: partially applied functions. + from ..exceptions import HTTPException + + @functools.wraps(f) + def application(*args): # type: ignore + request = cls(args[-2]) + with request: + try: + resp = f(*args[:-2] + (request,)) + except HTTPException as e: + resp = e.get_response(args[-2]) + return resp(*args[-2:]) + + return t.cast("WSGIApplication", application) + + def _get_file_stream( + self, + total_content_length: t.Optional[int], + content_type: t.Optional[str], + filename: t.Optional[str] = None, + content_length: t.Optional[int] = None, + ) -> t.IO[bytes]: + """Called to get a stream for the file upload. + + This must provide a file-like class with `read()`, `readline()` + and `seek()` methods that is both writeable and readable. + + The default implementation returns a temporary file if the total + content length is higher than 500KB. Because many browsers do not + provide a content length for the files only the total content + length matters. + + :param total_content_length: the total content length of all the + data in the request combined. This value + is guaranteed to be there. + :param content_type: the mimetype of the uploaded file. + :param filename: the filename of the uploaded file. May be `None`. + :param content_length: the length of this file. This value is usually + not provided because webbrowsers do not provide + this value. + """ + return default_stream_factory( + total_content_length=total_content_length, + filename=filename, + content_type=content_type, + content_length=content_length, + ) + + @property + def want_form_data_parsed(self) -> bool: + """``True`` if the request method carries content. By default + this is true if a ``Content-Type`` is sent. + + .. versionadded:: 0.8 + """ + return bool(self.environ.get("CONTENT_TYPE")) + + def make_form_data_parser(self) -> FormDataParser: + """Creates the form data parser. Instantiates the + :attr:`form_data_parser_class` with some parameters. + + .. versionadded:: 0.8 + """ + return self.form_data_parser_class( + self._get_file_stream, + self.charset, + self.encoding_errors, + self.max_form_memory_size, + self.max_content_length, + self.parameter_storage_class, + max_form_parts=self.max_form_parts, + ) + + def _load_form_data(self) -> None: + """Method used internally to retrieve submitted data. After calling + this sets `form` and `files` on the request object to multi dicts + filled with the incoming form data. As a matter of fact the input + stream will be empty afterwards. You can also call this method to + force the parsing of the form data. + + .. versionadded:: 0.8 + """ + # abort early if we have already consumed the stream + if "form" in self.__dict__: + return + + if self.want_form_data_parsed: + parser = self.make_form_data_parser() + data = parser.parse( + self._get_stream_for_parsing(), + self.mimetype, + self.content_length, + self.mimetype_params, + ) + else: + data = ( + self.stream, + self.parameter_storage_class(), + self.parameter_storage_class(), + ) + + # inject the values into the instance dict so that we bypass + # our cached_property non-data descriptor. + d = self.__dict__ + d["stream"], d["form"], d["files"] = data + + def _get_stream_for_parsing(self) -> t.IO[bytes]: + """This is the same as accessing :attr:`stream` with the difference + that if it finds cached data from calling :meth:`get_data` first it + will create a new stream out of the cached data. + + .. versionadded:: 0.9.3 + """ + cached_data = getattr(self, "_cached_data", None) + if cached_data is not None: + return BytesIO(cached_data) + return self.stream + + def close(self) -> None: + """Closes associated resources of this request object. This + closes all file handles explicitly. You can also use the request + object in a with statement which will automatically close it. + + .. versionadded:: 0.9 + """ + files = self.__dict__.get("files") + for _key, value in iter_multi_items(files or ()): + value.close() + + def __enter__(self) -> "Request": + return self + + def __exit__(self, exc_type, exc_value, tb) -> None: # type: ignore + self.close() + + @cached_property + def stream(self) -> t.IO[bytes]: + """ + If the incoming form data was not encoded with a known mimetype + the data is stored unmodified in this stream for consumption. Most + of the time it is a better idea to use :attr:`data` which will give + you that data as a string. The stream only returns the data once. + + Unlike :attr:`input_stream` this stream is properly guarded that you + can't accidentally read past the length of the input. Werkzeug will + internally always refer to this stream to read data which makes it + possible to wrap this object with a stream that does filtering. + + .. versionchanged:: 0.9 + This stream is now always available but might be consumed by the + form parser later on. Previously the stream was only set if no + parsing happened. + """ + if self.shallow: + raise RuntimeError( + "This request was created with 'shallow=True', reading" + " from the input stream is disabled." + ) + + return get_input_stream(self.environ) + + input_stream = environ_property[t.IO[bytes]]( + "wsgi.input", + doc="""The WSGI input stream. + + In general it's a bad idea to use this one because you can + easily read past the boundary. Use the :attr:`stream` + instead.""", + ) + + @cached_property + def data(self) -> bytes: + """ + Contains the incoming request data as string in case it came with + a mimetype Werkzeug does not handle. + """ + return self.get_data(parse_form_data=True) + + @typing.overload + def get_data( # type: ignore + self, + cache: bool = True, + as_text: "te.Literal[False]" = False, + parse_form_data: bool = False, + ) -> bytes: + ... + + @typing.overload + def get_data( + self, + cache: bool = True, + as_text: "te.Literal[True]" = ..., + parse_form_data: bool = False, + ) -> str: + ... + + def get_data( + self, cache: bool = True, as_text: bool = False, parse_form_data: bool = False + ) -> t.Union[bytes, str]: + """This reads the buffered incoming data from the client into one + bytes object. By default this is cached but that behavior can be + changed by setting `cache` to `False`. + + Usually it's a bad idea to call this method without checking the + content length first as a client could send dozens of megabytes or more + to cause memory problems on the server. + + Note that if the form data was already parsed this method will not + return anything as form data parsing does not cache the data like + this method does. To implicitly invoke form data parsing function + set `parse_form_data` to `True`. When this is done the return value + of this method will be an empty string if the form parser handles + the data. This generally is not necessary as if the whole data is + cached (which is the default) the form parser will used the cached + data to parse the form data. Please be generally aware of checking + the content length first in any case before calling this method + to avoid exhausting server memory. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + rv = getattr(self, "_cached_data", None) + if rv is None: + if parse_form_data: + self._load_form_data() + rv = self.stream.read() + if cache: + self._cached_data = rv + if as_text: + rv = rv.decode(self.charset, self.encoding_errors) + return rv + + @cached_property + def form(self) -> "ImmutableMultiDict[str, str]": + """The form parameters. By default an + :class:`~werkzeug.datastructures.ImmutableMultiDict` + is returned from this function. This can be changed by setting + :attr:`parameter_storage_class` to a different type. This might + be necessary if the order of the form data is important. + + Please keep in mind that file uploads will not end up here, but instead + in the :attr:`files` attribute. + + .. versionchanged:: 0.9 + + Previous to Werkzeug 0.9 this would only contain form data for POST + and PUT requests. + """ + self._load_form_data() + return self.form + + @cached_property + def values(self) -> "CombinedMultiDict[str, str]": + """A :class:`werkzeug.datastructures.CombinedMultiDict` that + combines :attr:`args` and :attr:`form`. + + For GET requests, only ``args`` are present, not ``form``. + + .. versionchanged:: 2.0 + For GET requests, only ``args`` are present, not ``form``. + """ + sources = [self.args] + + if self.method != "GET": + # GET requests can have a body, and some caching proxies + # might not treat that differently than a normal GET + # request, allowing form data to "invisibly" affect the + # cache without indication in the query string / URL. + sources.append(self.form) + + args = [] + + for d in sources: + if not isinstance(d, MultiDict): + d = MultiDict(d) + + args.append(d) + + return CombinedMultiDict(args) + + @cached_property + def files(self) -> "ImmutableMultiDict[str, FileStorage]": + """:class:`~werkzeug.datastructures.MultiDict` object containing + all uploaded files. Each key in :attr:`files` is the name from the + ````. Each value in :attr:`files` is a + Werkzeug :class:`~werkzeug.datastructures.FileStorage` object. + + It basically behaves like a standard file object you know from Python, + with the difference that it also has a + :meth:`~werkzeug.datastructures.FileStorage.save` function that can + store the file on the filesystem. + + Note that :attr:`files` will only contain data if the request method was + POST, PUT or PATCH and the ``

    `` that posted to the request had + ``enctype="multipart/form-data"``. It will be empty otherwise. + + See the :class:`~werkzeug.datastructures.MultiDict` / + :class:`~werkzeug.datastructures.FileStorage` documentation for + more details about the used data structure. + """ + self._load_form_data() + return self.files + + @property + def script_root(self) -> str: + """Alias for :attr:`self.root_path`. ``environ["SCRIPT_ROOT"]`` + without a trailing slash. + """ + return self.root_path + + @cached_property + def url_root(self) -> str: + """Alias for :attr:`root_url`. The URL with scheme, host, and + root path. For example, ``https://example.com/app/``. + """ + return self.root_url + + remote_user = environ_property[str]( + "REMOTE_USER", + doc="""If the server supports user authentication, and the + script is protected, this attribute contains the username the + user has authenticated as.""", + ) + is_multithread = environ_property[bool]( + "wsgi.multithread", + doc="""boolean that is `True` if the application is served by a + multithreaded WSGI server.""", + ) + is_multiprocess = environ_property[bool]( + "wsgi.multiprocess", + doc="""boolean that is `True` if the application is served by a + WSGI server that spawns multiple processes.""", + ) + is_run_once = environ_property[bool]( + "wsgi.run_once", + doc="""boolean that is `True` if the application will be + executed only once in a process lifetime. This is the case for + CGI for example, but it's not guaranteed that the execution only + happens one time.""", + ) + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Optional[t.Any]: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + + If the request content type is not ``application/json``, this + will raise a 400 Bad Request error. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + return self.get_json() + + # Cached values for ``(silent=False, silent=True)``. Initialized + # with sentinel values. + _cached_json: t.Tuple[t.Any, t.Any] = (Ellipsis, Ellipsis) + + @t.overload + def get_json( + self, force: bool = ..., silent: "te.Literal[False]" = ..., cache: bool = ... + ) -> t.Any: + ... + + @t.overload + def get_json( + self, force: bool = ..., silent: bool = ..., cache: bool = ... + ) -> t.Optional[t.Any]: + ... + + def get_json( + self, force: bool = False, silent: bool = False, cache: bool = True + ) -> t.Optional[t.Any]: + """Parse :attr:`data` as JSON. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), or parsing + fails, :meth:`on_json_loading_failed` is called and + its return value is used as the return value. By default this + raises a 400 Bad Request error. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence mimetype and parsing errors, and + return ``None`` instead. + :param cache: Store the parsed JSON to return for subsequent + calls. + + .. versionchanged:: 2.1 + Raise a 400 error if the content type is incorrect. + """ + if cache and self._cached_json[silent] is not Ellipsis: + return self._cached_json[silent] + + if not (force or self.is_json): + if not silent: + return self.on_json_loading_failed(None) + else: + return None + + data = self.get_data(cache=cache) + + try: + rv = self.json_module.loads(data) + except ValueError as e: + if silent: + rv = None + + if cache: + normal_rv, _ = self._cached_json + self._cached_json = (normal_rv, rv) + else: + rv = self.on_json_loading_failed(e) + + if cache: + _, silent_rv = self._cached_json + self._cached_json = (rv, silent_rv) + else: + if cache: + self._cached_json = (rv, rv) + + return rv + + def on_json_loading_failed(self, e: t.Optional[ValueError]) -> t.Any: + """Called if :meth:`get_json` fails and isn't silenced. + + If this method returns a value, it is used as the return value + for :meth:`get_json`. The default implementation raises + :exc:`~werkzeug.exceptions.BadRequest`. + + :param e: If parsing failed, this is the exception. It will be + ``None`` if the content type wasn't ``application/json``. + """ + if e is not None: + raise BadRequest(f"Failed to decode JSON object: {e}") + + raise BadRequest( + "Did not attempt to load JSON data because the request" + " Content-Type was not 'application/json'." + ) diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/response.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/response.py new file mode 100644 index 00000000..454208c7 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wrappers/response.py @@ -0,0 +1,885 @@ +import json +import typing +import typing as t +import warnings +from http import HTTPStatus + +from .._internal import _to_bytes +from ..datastructures import Headers +from ..http import remove_entity_headers +from ..sansio.response import Response as _SansIOResponse +from ..urls import iri_to_uri +from ..urls import url_join +from ..utils import cached_property +from ..wsgi import ClosingIterator +from ..wsgi import get_current_url +from werkzeug._internal import _get_environ +from werkzeug.http import generate_etag +from werkzeug.http import http_date +from werkzeug.http import is_resource_modified +from werkzeug.http import parse_etags +from werkzeug.http import parse_range_header +from werkzeug.wsgi import _RangeWrapper + +if t.TYPE_CHECKING: + import typing_extensions as te + from _typeshed.wsgi import StartResponse + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + from .request import Request + + +def _warn_if_string(iterable: t.Iterable) -> None: + """Helper for the response objects to check if the iterable returned + to the WSGI server is not a string. + """ + if isinstance(iterable, str): + warnings.warn( + "Response iterable was set to a string. This will appear to" + " work but means that the server will send the data to the" + " client one character at a time. This is almost never" + " intended behavior, use 'response.data' to assign strings" + " to the response object.", + stacklevel=2, + ) + + +def _iter_encoded( + iterable: t.Iterable[t.Union[str, bytes]], charset: str +) -> t.Iterator[bytes]: + for item in iterable: + if isinstance(item, str): + yield item.encode(charset) + else: + yield item + + +def _clean_accept_ranges(accept_ranges: t.Union[bool, str]) -> str: + if accept_ranges is True: + return "bytes" + elif accept_ranges is False: + return "none" + elif isinstance(accept_ranges, str): + return accept_ranges + raise ValueError("Invalid accept_ranges value") + + +class Response(_SansIOResponse): + """Represents an outgoing WSGI HTTP response with body, status, and + headers. Has properties and methods for using the functionality + defined by various HTTP specs. + + The response body is flexible to support different use cases. The + simple form is passing bytes, or a string which will be encoded as + UTF-8. Passing an iterable of bytes or strings makes this a + streaming response. A generator is particularly useful for building + a CSV file in memory or using SSE (Server Sent Events). A file-like + object is also iterable, although the + :func:`~werkzeug.utils.send_file` helper should be used in that + case. + + The response object is itself a WSGI application callable. When + called (:meth:`__call__`) with ``environ`` and ``start_response``, + it will pass its status and headers to ``start_response`` then + return its body as an iterable. + + .. code-block:: python + + from werkzeug.wrappers.response import Response + + def index(): + return Response("Hello, World!") + + def application(environ, start_response): + path = environ.get("PATH_INFO") or "/" + + if path == "/": + response = index() + else: + response = Response("Not Found", status=404) + + return response(environ, start_response) + + :param response: The data for the body of the response. A string or + bytes, or tuple or list of strings or bytes, for a fixed-length + response, or any other iterable of strings or bytes for a + streaming response. Defaults to an empty body. + :param status: The status code for the response. Either an int, in + which case the default status message is added, or a string in + the form ``{code} {message}``, like ``404 Not Found``. Defaults + to 200. + :param headers: A :class:`~werkzeug.datastructures.Headers` object, + or a list of ``(key, value)`` tuples that will be converted to a + ``Headers`` object. + :param mimetype: The mime type (content type without charset or + other parameters) of the response. If the value starts with + ``text/`` (or matches some other special cases), the charset + will be added to create the ``content_type``. + :param content_type: The full content type of the response. + Overrides building the value from ``mimetype``. + :param direct_passthrough: Pass the response body directly through + as the WSGI iterable. This can be used when the body is a binary + file or other iterator of bytes, to skip some unnecessary + checks. Use :func:`~werkzeug.utils.send_file` instead of setting + this manually. + + .. versionchanged:: 2.0 + Combine ``BaseResponse`` and mixins into a single ``Response`` + class. Using the old classes is deprecated and will be removed + in Werkzeug 2.1. + + .. versionchanged:: 0.5 + The ``direct_passthrough`` parameter was added. + """ + + #: if set to `False` accessing properties on the response object will + #: not try to consume the response iterator and convert it into a list. + #: + #: .. versionadded:: 0.6.2 + #: + #: That attribute was previously called `implicit_seqence_conversion`. + #: (Notice the typo). If you did use this feature, you have to adapt + #: your code to the name change. + implicit_sequence_conversion = True + + #: If a redirect ``Location`` header is a relative URL, make it an + #: absolute URL, including scheme and domain. + #: + #: .. versionchanged:: 2.1 + #: This is disabled by default, so responses will send relative + #: redirects. + #: + #: .. versionadded:: 0.8 + autocorrect_location_header = False + + #: Should this response object automatically set the content-length + #: header if possible? This is true by default. + #: + #: .. versionadded:: 0.8 + automatically_set_content_length = True + + #: The response body to send as the WSGI iterable. A list of strings + #: or bytes represents a fixed-length response, any other iterable + #: is a streaming response. Strings are encoded to bytes as UTF-8. + #: + #: Do not set to a plain string or bytes, that will cause sending + #: the response to be very inefficient as it will iterate one byte + #: at a time. + response: t.Union[t.Iterable[str], t.Iterable[bytes]] + + def __init__( + self, + response: t.Optional[ + t.Union[t.Iterable[bytes], bytes, t.Iterable[str], str] + ] = None, + status: t.Optional[t.Union[int, str, HTTPStatus]] = None, + headers: t.Optional[ + t.Union[ + t.Mapping[str, t.Union[str, int, t.Iterable[t.Union[str, int]]]], + t.Iterable[t.Tuple[str, t.Union[str, int]]], + ] + ] = None, + mimetype: t.Optional[str] = None, + content_type: t.Optional[str] = None, + direct_passthrough: bool = False, + ) -> None: + super().__init__( + status=status, + headers=headers, + mimetype=mimetype, + content_type=content_type, + ) + + #: Pass the response body directly through as the WSGI iterable. + #: This can be used when the body is a binary file or other + #: iterator of bytes, to skip some unnecessary checks. Use + #: :func:`~werkzeug.utils.send_file` instead of setting this + #: manually. + self.direct_passthrough = direct_passthrough + self._on_close: t.List[t.Callable[[], t.Any]] = [] + + # we set the response after the headers so that if a class changes + # the charset attribute, the data is set in the correct charset. + if response is None: + self.response = [] + elif isinstance(response, (str, bytes, bytearray)): + self.set_data(response) + else: + self.response = response + + def call_on_close(self, func: t.Callable[[], t.Any]) -> t.Callable[[], t.Any]: + """Adds a function to the internal list of functions that should + be called as part of closing down the response. Since 0.7 this + function also returns the function that was passed so that this + can be used as a decorator. + + .. versionadded:: 0.6 + """ + self._on_close.append(func) + return func + + def __repr__(self) -> str: + if self.is_sequence: + body_info = f"{sum(map(len, self.iter_encoded()))} bytes" + else: + body_info = "streamed" if self.is_streamed else "likely-streamed" + return f"<{type(self).__name__} {body_info} [{self.status}]>" + + @classmethod + def force_type( + cls, response: "Response", environ: t.Optional["WSGIEnvironment"] = None + ) -> "Response": + """Enforce that the WSGI response is a response object of the current + type. Werkzeug will use the :class:`Response` internally in many + situations like the exceptions. If you call :meth:`get_response` on an + exception you will get back a regular :class:`Response` object, even + if you are using a custom subclass. + + This method can enforce a given response type, and it will also + convert arbitrary WSGI callables into response objects if an environ + is provided:: + + # convert a Werkzeug response object into an instance of the + # MyResponseClass subclass. + response = MyResponseClass.force_type(response) + + # convert any WSGI application into a response object + response = MyResponseClass.force_type(response, environ) + + This is especially useful if you want to post-process responses in + the main dispatcher and use functionality provided by your subclass. + + Keep in mind that this will modify response objects in place if + possible! + + :param response: a response object or wsgi application. + :param environ: a WSGI environment object. + :return: a response object. + """ + if not isinstance(response, Response): + if environ is None: + raise TypeError( + "cannot convert WSGI application into response" + " objects without an environ" + ) + + from ..test import run_wsgi_app + + response = Response(*run_wsgi_app(response, environ)) + + response.__class__ = cls + return response + + @classmethod + def from_app( + cls, app: "WSGIApplication", environ: "WSGIEnvironment", buffered: bool = False + ) -> "Response": + """Create a new response object from an application output. This + works best if you pass it an application that returns a generator all + the time. Sometimes applications may use the `write()` callable + returned by the `start_response` function. This tries to resolve such + edge cases automatically. But if you don't get the expected output + you should set `buffered` to `True` which enforces buffering. + + :param app: the WSGI application to execute. + :param environ: the WSGI environment to execute against. + :param buffered: set to `True` to enforce buffering. + :return: a response object. + """ + from ..test import run_wsgi_app + + return cls(*run_wsgi_app(app, environ, buffered)) + + @typing.overload + def get_data(self, as_text: "te.Literal[False]" = False) -> bytes: + ... + + @typing.overload + def get_data(self, as_text: "te.Literal[True]") -> str: + ... + + def get_data(self, as_text: bool = False) -> t.Union[bytes, str]: + """The string representation of the response body. Whenever you call + this property the response iterable is encoded and flattened. This + can lead to unwanted behavior if you stream big data. + + This behavior can be disabled by setting + :attr:`implicit_sequence_conversion` to `False`. + + If `as_text` is set to `True` the return value will be a decoded + string. + + .. versionadded:: 0.9 + """ + self._ensure_sequence() + rv = b"".join(self.iter_encoded()) + + if as_text: + return rv.decode(self.charset) + + return rv + + def set_data(self, value: t.Union[bytes, str]) -> None: + """Sets a new string as response. The value must be a string or + bytes. If a string is set it's encoded to the charset of the + response (utf-8 by default). + + .. versionadded:: 0.9 + """ + # if a string is set, it's encoded directly so that we + # can set the content length + if isinstance(value, str): + value = value.encode(self.charset) + else: + value = bytes(value) + self.response = [value] + if self.automatically_set_content_length: + self.headers["Content-Length"] = str(len(value)) + + data = property( + get_data, + set_data, + doc="A descriptor that calls :meth:`get_data` and :meth:`set_data`.", + ) + + def calculate_content_length(self) -> t.Optional[int]: + """Returns the content length if available or `None` otherwise.""" + try: + self._ensure_sequence() + except RuntimeError: + return None + return sum(len(x) for x in self.iter_encoded()) + + def _ensure_sequence(self, mutable: bool = False) -> None: + """This method can be called by methods that need a sequence. If + `mutable` is true, it will also ensure that the response sequence + is a standard Python list. + + .. versionadded:: 0.6 + """ + if self.is_sequence: + # if we need a mutable object, we ensure it's a list. + if mutable and not isinstance(self.response, list): + self.response = list(self.response) # type: ignore + return + if self.direct_passthrough: + raise RuntimeError( + "Attempted implicit sequence conversion but the" + " response object is in direct passthrough mode." + ) + if not self.implicit_sequence_conversion: + raise RuntimeError( + "The response object required the iterable to be a" + " sequence, but the implicit conversion was disabled." + " Call make_sequence() yourself." + ) + self.make_sequence() + + def make_sequence(self) -> None: + """Converts the response iterator in a list. By default this happens + automatically if required. If `implicit_sequence_conversion` is + disabled, this method is not automatically called and some properties + might raise exceptions. This also encodes all the items. + + .. versionadded:: 0.6 + """ + if not self.is_sequence: + # if we consume an iterable we have to ensure that the close + # method of the iterable is called if available when we tear + # down the response + close = getattr(self.response, "close", None) + self.response = list(self.iter_encoded()) + if close is not None: + self.call_on_close(close) + + def iter_encoded(self) -> t.Iterator[bytes]: + """Iter the response encoded with the encoding of the response. + If the response object is invoked as WSGI application the return + value of this method is used as application iterator unless + :attr:`direct_passthrough` was activated. + """ + if __debug__: + _warn_if_string(self.response) + # Encode in a separate function so that self.response is fetched + # early. This allows us to wrap the response with the return + # value from get_app_iter or iter_encoded. + return _iter_encoded(self.response, self.charset) + + @property + def is_streamed(self) -> bool: + """If the response is streamed (the response is not an iterable with + a length information) this property is `True`. In this case streamed + means that there is no information about the number of iterations. + This is usually `True` if a generator is passed to the response object. + + This is useful for checking before applying some sort of post + filtering that should not take place for streamed responses. + """ + try: + len(self.response) # type: ignore + except (TypeError, AttributeError): + return True + return False + + @property + def is_sequence(self) -> bool: + """If the iterator is buffered, this property will be `True`. A + response object will consider an iterator to be buffered if the + response attribute is a list or tuple. + + .. versionadded:: 0.6 + """ + return isinstance(self.response, (tuple, list)) + + def close(self) -> None: + """Close the wrapped response if possible. You can also use the object + in a with statement which will automatically close it. + + .. versionadded:: 0.9 + Can now be used in a with statement. + """ + if hasattr(self.response, "close"): + self.response.close() + for func in self._on_close: + func() + + def __enter__(self) -> "Response": + return self + + def __exit__(self, exc_type, exc_value, tb): # type: ignore + self.close() + + def freeze(self) -> None: + """Make the response object ready to be pickled. Does the + following: + + * Buffer the response into a list, ignoring + :attr:`implicity_sequence_conversion` and + :attr:`direct_passthrough`. + * Set the ``Content-Length`` header. + * Generate an ``ETag`` header if one is not already set. + + .. versionchanged:: 2.1 + Removed the ``no_etag`` parameter. + + .. versionchanged:: 2.0 + An ``ETag`` header is added, the ``no_etag`` parameter is + deprecated and will be removed in Werkzeug 2.1. + + .. versionchanged:: 0.6 + The ``Content-Length`` header is set. + """ + # Always freeze the encoded response body, ignore + # implicit_sequence_conversion and direct_passthrough. + self.response = list(self.iter_encoded()) + self.headers["Content-Length"] = str(sum(map(len, self.response))) + self.add_etag() + + def get_wsgi_headers(self, environ: "WSGIEnvironment") -> Headers: + """This is automatically called right before the response is started + and returns headers modified for the given environment. It returns a + copy of the headers from the response with some modifications applied + if necessary. + + For example the location header (if present) is joined with the root + URL of the environment. Also the content length is automatically set + to zero here for certain status codes. + + .. versionchanged:: 0.6 + Previously that function was called `fix_headers` and modified + the response object in place. Also since 0.6, IRIs in location + and content-location headers are handled properly. + + Also starting with 0.6, Werkzeug will attempt to set the content + length if it is able to figure it out on its own. This is the + case if all the strings in the response iterable are already + encoded and the iterable is buffered. + + :param environ: the WSGI environment of the request. + :return: returns a new :class:`~werkzeug.datastructures.Headers` + object. + """ + headers = Headers(self.headers) + location: t.Optional[str] = None + content_location: t.Optional[str] = None + content_length: t.Optional[t.Union[str, int]] = None + status = self.status_code + + # iterate over the headers to find all values in one go. Because + # get_wsgi_headers is used each response that gives us a tiny + # speedup. + for key, value in headers: + ikey = key.lower() + if ikey == "location": + location = value + elif ikey == "content-location": + content_location = value + elif ikey == "content-length": + content_length = value + + # make sure the location header is an absolute URL + if location is not None: + old_location = location + if isinstance(location, str): + # Safe conversion is necessary here as we might redirect + # to a broken URI scheme (for instance itms-services). + location = iri_to_uri(location, safe_conversion=True) + + if self.autocorrect_location_header: + current_url = get_current_url(environ, strip_querystring=True) + if isinstance(current_url, str): + current_url = iri_to_uri(current_url) + location = url_join(current_url, location) + if location != old_location: + headers["Location"] = location + + # make sure the content location is a URL + if content_location is not None and isinstance(content_location, str): + headers["Content-Location"] = iri_to_uri(content_location) + + if 100 <= status < 200 or status == 204: + # Per section 3.3.2 of RFC 7230, "a server MUST NOT send a + # Content-Length header field in any response with a status + # code of 1xx (Informational) or 204 (No Content)." + headers.remove("Content-Length") + elif status == 304: + remove_entity_headers(headers) + + # if we can determine the content length automatically, we + # should try to do that. But only if this does not involve + # flattening the iterator or encoding of strings in the + # response. We however should not do that if we have a 304 + # response. + if ( + self.automatically_set_content_length + and self.is_sequence + and content_length is None + and status not in (204, 304) + and not (100 <= status < 200) + ): + try: + content_length = sum(len(_to_bytes(x, "ascii")) for x in self.response) + except UnicodeError: + # Something other than bytes, can't safely figure out + # the length of the response. + pass + else: + headers["Content-Length"] = str(content_length) + + return headers + + def get_app_iter(self, environ: "WSGIEnvironment") -> t.Iterable[bytes]: + """Returns the application iterator for the given environ. Depending + on the request method and the current status code the return value + might be an empty response rather than the one from the response. + + If the request method is `HEAD` or the status code is in a range + where the HTTP specification requires an empty response, an empty + iterable is returned. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: a response iterable. + """ + status = self.status_code + if ( + environ["REQUEST_METHOD"] == "HEAD" + or 100 <= status < 200 + or status in (204, 304) + ): + iterable: t.Iterable[bytes] = () + elif self.direct_passthrough: + if __debug__: + _warn_if_string(self.response) + return self.response # type: ignore + else: + iterable = self.iter_encoded() + return ClosingIterator(iterable, self.close) + + def get_wsgi_response( + self, environ: "WSGIEnvironment" + ) -> t.Tuple[t.Iterable[bytes], str, t.List[t.Tuple[str, str]]]: + """Returns the final WSGI response as tuple. The first item in + the tuple is the application iterator, the second the status and + the third the list of headers. The response returned is created + specially for the given environment. For example if the request + method in the WSGI environment is ``'HEAD'`` the response will + be empty and only the headers and status code will be present. + + .. versionadded:: 0.6 + + :param environ: the WSGI environment of the request. + :return: an ``(app_iter, status, headers)`` tuple. + """ + headers = self.get_wsgi_headers(environ) + app_iter = self.get_app_iter(environ) + return app_iter, self.status, headers.to_wsgi_list() + + def __call__( + self, environ: "WSGIEnvironment", start_response: "StartResponse" + ) -> t.Iterable[bytes]: + """Process this response as WSGI application. + + :param environ: the WSGI environment. + :param start_response: the response callable provided by the WSGI + server. + :return: an application iterator + """ + app_iter, status, headers = self.get_wsgi_response(environ) + start_response(status, headers) + return app_iter + + # JSON + + #: A module or other object that has ``dumps`` and ``loads`` + #: functions that match the API of the built-in :mod:`json` module. + json_module = json + + @property + def json(self) -> t.Optional[t.Any]: + """The parsed JSON data if :attr:`mimetype` indicates JSON + (:mimetype:`application/json`, see :attr:`is_json`). + + Calls :meth:`get_json` with default arguments. + """ + return self.get_json() + + @t.overload + def get_json(self, force: bool = ..., silent: "te.Literal[False]" = ...) -> t.Any: + ... + + @t.overload + def get_json(self, force: bool = ..., silent: bool = ...) -> t.Optional[t.Any]: + ... + + def get_json(self, force: bool = False, silent: bool = False) -> t.Optional[t.Any]: + """Parse :attr:`data` as JSON. Useful during testing. + + If the mimetype does not indicate JSON + (:mimetype:`application/json`, see :attr:`is_json`), this + returns ``None``. + + Unlike :meth:`Request.get_json`, the result is not cached. + + :param force: Ignore the mimetype and always try to parse JSON. + :param silent: Silence parsing errors and return ``None`` + instead. + """ + if not (force or self.is_json): + return None + + data = self.get_data() + + try: + return self.json_module.loads(data) + except ValueError: + if not silent: + raise + + return None + + # Stream + + @cached_property + def stream(self) -> "ResponseStream": + """The response iterable as write-only stream.""" + return ResponseStream(self) + + def _wrap_range_response(self, start: int, length: int) -> None: + """Wrap existing Response in case of Range Request context.""" + if self.status_code == 206: + self.response = _RangeWrapper(self.response, start, length) # type: ignore + + def _is_range_request_processable(self, environ: "WSGIEnvironment") -> bool: + """Return ``True`` if `Range` header is present and if underlying + resource is considered unchanged when compared with `If-Range` header. + """ + return ( + "HTTP_IF_RANGE" not in environ + or not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ignore_if_range=False, + ) + ) and "HTTP_RANGE" in environ + + def _process_range_request( + self, + environ: "WSGIEnvironment", + complete_length: t.Optional[int] = None, + accept_ranges: t.Optional[t.Union[bool, str]] = None, + ) -> bool: + """Handle Range Request related headers (RFC7233). If `Accept-Ranges` + header is valid, and Range Request is processable, we set the headers + as described by the RFC, and wrap the underlying response in a + RangeWrapper. + + Returns ``True`` if Range Request can be fulfilled, ``False`` otherwise. + + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Returns ``False`` if the length is 0. + """ + from ..exceptions import RequestedRangeNotSatisfiable + + if ( + accept_ranges is None + or complete_length is None + or complete_length == 0 + or not self._is_range_request_processable(environ) + ): + return False + + parsed_range = parse_range_header(environ.get("HTTP_RANGE")) + + if parsed_range is None: + raise RequestedRangeNotSatisfiable(complete_length) + + range_tuple = parsed_range.range_for_length(complete_length) + content_range_header = parsed_range.to_content_range_header(complete_length) + + if range_tuple is None or content_range_header is None: + raise RequestedRangeNotSatisfiable(complete_length) + + content_length = range_tuple[1] - range_tuple[0] + self.headers["Content-Length"] = content_length + self.headers["Accept-Ranges"] = accept_ranges + self.content_range = content_range_header # type: ignore + self.status_code = 206 + self._wrap_range_response(range_tuple[0], content_length) + return True + + def make_conditional( + self, + request_or_environ: t.Union["WSGIEnvironment", "Request"], + accept_ranges: t.Union[bool, str] = False, + complete_length: t.Optional[int] = None, + ) -> "Response": + """Make the response conditional to the request. This method works + best if an etag was defined for the response already. The `add_etag` + method can be used to do that. If called without etag just the date + header is set. + + This does nothing if the request method in the request or environ is + anything but GET or HEAD. + + For optimal performance when handling range requests, it's recommended + that your response data object implements `seekable`, `seek` and `tell` + methods as described by :py:class:`io.IOBase`. Objects returned by + :meth:`~werkzeug.wsgi.wrap_file` automatically implement those methods. + + It does not remove the body of the response because that's something + the :meth:`__call__` function does for us automatically. + + Returns self so that you can do ``return resp.make_conditional(req)`` + but modifies the object in-place. + + :param request_or_environ: a request object or WSGI environment to be + used to make the response conditional + against. + :param accept_ranges: This parameter dictates the value of + `Accept-Ranges` header. If ``False`` (default), + the header is not set. If ``True``, it will be set + to ``"bytes"``. If ``None``, it will be set to + ``"none"``. If it's a string, it will use this + value. + :param complete_length: Will be used only in valid Range Requests. + It will set `Content-Range` complete length + value and compute `Content-Length` real value. + This parameter is mandatory for successful + Range Requests completion. + :raises: :class:`~werkzeug.exceptions.RequestedRangeNotSatisfiable` + if `Range` header could not be parsed or satisfied. + + .. versionchanged:: 2.0 + Range processing is skipped if length is 0 instead of + raising a 416 Range Not Satisfiable error. + """ + environ = _get_environ(request_or_environ) + if environ["REQUEST_METHOD"] in ("GET", "HEAD"): + # if the date is not in the headers, add it now. We however + # will not override an already existing header. Unfortunately + # this header will be overridden by many WSGI servers including + # wsgiref. + if "date" not in self.headers: + self.headers["Date"] = http_date() + accept_ranges = _clean_accept_ranges(accept_ranges) + is206 = self._process_range_request(environ, complete_length, accept_ranges) + if not is206 and not is_resource_modified( + environ, + self.headers.get("etag"), + None, + self.headers.get("last-modified"), + ): + if parse_etags(environ.get("HTTP_IF_MATCH")): + self.status_code = 412 + else: + self.status_code = 304 + if ( + self.automatically_set_content_length + and "content-length" not in self.headers + ): + length = self.calculate_content_length() + if length is not None: + self.headers["Content-Length"] = length + return self + + def add_etag(self, overwrite: bool = False, weak: bool = False) -> None: + """Add an etag for the current response if there is none yet. + + .. versionchanged:: 2.0 + SHA-1 is used to generate the value. MD5 may not be + available in some environments. + """ + if overwrite or "etag" not in self.headers: + self.set_etag(generate_etag(self.get_data()), weak) + + +class ResponseStream: + """A file descriptor like object used by :meth:`Response.stream` to + represent the body of the stream. It directly pushes into the + response iterable of the response object. + """ + + mode = "wb+" + + def __init__(self, response: Response): + self.response = response + self.closed = False + + def write(self, value: bytes) -> int: + if self.closed: + raise ValueError("I/O operation on closed file") + self.response._ensure_sequence(mutable=True) + self.response.response.append(value) # type: ignore + self.response.headers.pop("Content-Length", None) + return len(value) + + def writelines(self, seq: t.Iterable[bytes]) -> None: + for item in seq: + self.write(item) + + def close(self) -> None: + self.closed = True + + def flush(self) -> None: + if self.closed: + raise ValueError("I/O operation on closed file") + + def isatty(self) -> bool: + if self.closed: + raise ValueError("I/O operation on closed file") + return False + + def tell(self) -> int: + self.response._ensure_sequence() + return sum(map(len, self.response.response)) + + @property + def encoding(self) -> str: + return self.response.charset diff --git a/flask-server/venv/lib/python3.10/site-packages/werkzeug/wsgi.py b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wsgi.py new file mode 100644 index 00000000..d74430d8 --- /dev/null +++ b/flask-server/venv/lib/python3.10/site-packages/werkzeug/wsgi.py @@ -0,0 +1,1058 @@ +import io +import re +import typing as t +import warnings +from functools import partial +from functools import update_wrapper +from itertools import chain + +from ._internal import _make_encode_wrapper +from ._internal import _to_bytes +from ._internal import _to_str +from .sansio import utils as _sansio_utils +from .sansio.utils import host_is_trusted # noqa: F401 # Imported as part of API +from .urls import _URLTuple +from .urls import uri_to_iri +from .urls import url_join +from .urls import url_parse +from .urls import url_quote + +if t.TYPE_CHECKING: + from _typeshed.wsgi import WSGIApplication + from _typeshed.wsgi import WSGIEnvironment + + +def responder(f: t.Callable[..., "WSGIApplication"]) -> "WSGIApplication": + """Marks a function as responder. Decorate a function with it and it + will automatically call the return value as WSGI application. + + Example:: + + @responder + def application(environ, start_response): + return Response('Hello World!') + """ + return update_wrapper(lambda *a: f(*a)(*a[-2:]), f) + + +def get_current_url( + environ: "WSGIEnvironment", + root_only: bool = False, + strip_querystring: bool = False, + host_only: bool = False, + trusted_hosts: t.Optional[t.Iterable[str]] = None, +) -> str: + """Recreate the URL for a request from the parts in a WSGI + environment. + + The URL is an IRI, not a URI, so it may contain Unicode characters. + Use :func:`~werkzeug.urls.iri_to_uri` to convert it to ASCII. + + :param environ: The WSGI environment to get the URL parts from. + :param root_only: Only build the root path, don't include the + remaining path or query string. + :param strip_querystring: Don't include the query string. + :param host_only: Only build the scheme and host. + :param trusted_hosts: A list of trusted host names to validate the + host against. + """ + parts = { + "scheme": environ["wsgi.url_scheme"], + "host": get_host(environ, trusted_hosts), + } + + if not host_only: + parts["root_path"] = environ.get("SCRIPT_NAME", "") + + if not root_only: + parts["path"] = environ.get("PATH_INFO", "") + + if not strip_querystring: + parts["query_string"] = environ.get("QUERY_STRING", "").encode("latin1") + + return _sansio_utils.get_current_url(**parts) + + +def _get_server( + environ: "WSGIEnvironment", +) -> t.Optional[t.Tuple[str, t.Optional[int]]]: + name = environ.get("SERVER_NAME") + + if name is None: + return None + + try: + port: t.Optional[int] = int(environ.get("SERVER_PORT", None)) + except (TypeError, ValueError): + # unix socket + port = None + + return name, port + + +def get_host( + environ: "WSGIEnvironment", trusted_hosts: t.Optional[t.Iterable[str]] = None +) -> str: + """Return the host for the given WSGI environment. + + The ``Host`` header is preferred, then ``SERVER_NAME`` if it's not + set. The returned host will only contain the port if it is different + than the standard port for the protocol. + + Optionally, verify that the host is trusted using + :func:`host_is_trusted` and raise a + :exc:`~werkzeug.exceptions.SecurityError` if it is not. + + :param environ: A WSGI environment dict. + :param trusted_hosts: A list of trusted host names. + + :return: Host, with port if necessary. + :raise ~werkzeug.exceptions.SecurityError: If the host is not + trusted. + """ + return _sansio_utils.get_host( + environ["wsgi.url_scheme"], + environ.get("HTTP_HOST"), + _get_server(environ), + trusted_hosts, + ) + + +def get_content_length(environ: "WSGIEnvironment") -> t.Optional[int]: + """Returns the content length from the WSGI environment as + integer. If it's not available or chunked transfer encoding is used, + ``None`` is returned. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the content length from. + """ + return _sansio_utils.get_content_length( + http_content_length=environ.get("CONTENT_LENGTH"), + http_transfer_encoding=environ.get("HTTP_TRANSFER_ENCODING", ""), + ) + + +def get_input_stream( + environ: "WSGIEnvironment", safe_fallback: bool = True +) -> t.IO[bytes]: + """Returns the input stream from the WSGI environment and wraps it + in the most sensible way possible. The stream returned is not the + raw WSGI stream in most cases but one that is safe to read from + without taking into account the content length. + + If content length is not set, the stream will be empty for safety reasons. + If the WSGI server supports chunked or infinite streams, it should set + the ``wsgi.input_terminated`` value in the WSGI environ to indicate that. + + .. versionadded:: 0.9 + + :param environ: the WSGI environ to fetch the stream from. + :param safe_fallback: use an empty stream as a safe fallback when the + content length is not set. Disabling this allows infinite streams, + which can be a denial-of-service risk. + """ + stream = t.cast(t.IO[bytes], environ["wsgi.input"]) + content_length = get_content_length(environ) + + # A wsgi extension that tells us if the input is terminated. In + # that case we return the stream unchanged as we know we can safely + # read it until the end. + if environ.get("wsgi.input_terminated"): + return stream + + # If the request doesn't specify a content length, returning the stream is + # potentially dangerous because it could be infinite, malicious or not. If + # safe_fallback is true, return an empty stream instead for safety. + if content_length is None: + return io.BytesIO() if safe_fallback else stream + + # Otherwise limit the stream to the content length + return t.cast(t.IO[bytes], LimitedStream(stream, content_length)) + + +def get_query_string(environ: "WSGIEnvironment") -> str: + """Returns the ``QUERY_STRING`` from the WSGI environment. This also + takes care of the WSGI decoding dance. The string returned will be + restricted to ASCII characters. + + :param environ: WSGI environment to get the query string from. + + .. deprecated:: 2.2 + Will be removed in Werkzeug 2.3. + + .. versionadded:: 0.9 + """ + warnings.warn( + "'get_query_string' is deprecated and will be removed in Werkzeug 2.3.", + DeprecationWarning, + stacklevel=2, + ) + qs = environ.get("QUERY_STRING", "").encode("latin1") + # QUERY_STRING really should be ascii safe but some browsers + # will send us some unicode stuff (I am looking at you IE). + # In that case we want to urllib quote it badly. + return url_quote(qs, safe=":&%=+$!*'(),") + + +def get_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> str: + """Return the ``PATH_INFO`` from the WSGI environment and decode it + unless ``charset`` is ``None``. + + :param environ: WSGI environment to get the path from. + :param charset: The charset for the path info, or ``None`` if no + decoding should be performed. + :param errors: The decoding error handling. + + .. versionadded:: 0.9 + """ + path = environ.get("PATH_INFO", "").encode("latin1") + return _to_str(path, charset, errors, allow_none_charset=True) # type: ignore + + +def get_script_name( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> str: + """Return the ``SCRIPT_NAME`` from the WSGI environment and decode + it unless `charset` is set to ``None``. + + :param environ: WSGI environment to get the path from. + :param charset: The charset for the path, or ``None`` if no decoding + should be performed. + :param errors: The decoding error handling. + + .. deprecated:: 2.2 + Will be removed in Werkzeug 2.3. + + .. versionadded:: 0.9 + """ + warnings.warn( + "'get_script_name' is deprecated and will be removed in Werkzeug 2.3.", + DeprecationWarning, + stacklevel=2, + ) + path = environ.get("SCRIPT_NAME", "").encode("latin1") + return _to_str(path, charset, errors, allow_none_charset=True) # type: ignore + + +def pop_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> t.Optional[str]: + """Removes and returns the next segment of `PATH_INFO`, pushing it onto + `SCRIPT_NAME`. Returns `None` if there is nothing left on `PATH_INFO`. + + If the `charset` is set to `None` bytes are returned. + + If there are empty segments (``'/foo//bar``) these are ignored but + properly pushed to the `SCRIPT_NAME`: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> pop_path_info(env) + 'a' + >>> env['SCRIPT_NAME'] + '/foo/a' + >>> pop_path_info(env) + 'b' + >>> env['SCRIPT_NAME'] + '/foo/a/b' + + .. deprecated:: 2.2 + Will be removed in Werkzeug 2.3. + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is modified. + :param charset: The ``encoding`` parameter passed to + :func:`bytes.decode`. + :param errors: The ``errors`` paramater passed to + :func:`bytes.decode`. + """ + warnings.warn( + "'pop_path_info' is deprecated and will be removed in Werkzeug 2.3.", + DeprecationWarning, + stacklevel=2, + ) + + path = environ.get("PATH_INFO") + if not path: + return None + + script_name = environ.get("SCRIPT_NAME", "") + + # shift multiple leading slashes over + old_path = path + path = path.lstrip("/") + if path != old_path: + script_name += "/" * (len(old_path) - len(path)) + + if "/" not in path: + environ["PATH_INFO"] = "" + environ["SCRIPT_NAME"] = script_name + path + rv = path.encode("latin1") + else: + segment, path = path.split("/", 1) + environ["PATH_INFO"] = f"/{path}" + environ["SCRIPT_NAME"] = script_name + segment + rv = segment.encode("latin1") + + return _to_str(rv, charset, errors, allow_none_charset=True) # type: ignore + + +def peek_path_info( + environ: "WSGIEnvironment", charset: str = "utf-8", errors: str = "replace" +) -> t.Optional[str]: + """Returns the next segment on the `PATH_INFO` or `None` if there + is none. Works like :func:`pop_path_info` without modifying the + environment: + + >>> env = {'SCRIPT_NAME': '/foo', 'PATH_INFO': '/a/b'} + >>> peek_path_info(env) + 'a' + >>> peek_path_info(env) + 'a' + + If the `charset` is set to `None` bytes are returned. + + .. deprecated:: 2.2 + Will be removed in Werkzeug 2.3. + + .. versionadded:: 0.5 + + .. versionchanged:: 0.9 + The path is now decoded and a charset and encoding + parameter can be provided. + + :param environ: the WSGI environment that is checked. + """ + warnings.warn( + "'peek_path_info' is deprecated and will be removed in Werkzeug 2.3.", + DeprecationWarning, + stacklevel=2, + ) + + segments = environ.get("PATH_INFO", "").lstrip("/").split("/", 1) + if segments: + return _to_str( # type: ignore + segments[0].encode("latin1"), charset, errors, allow_none_charset=True + ) + return None + + +def extract_path_info( + environ_or_baseurl: t.Union[str, "WSGIEnvironment"], + path_or_url: t.Union[str, _URLTuple], + charset: str = "utf-8", + errors: str = "werkzeug.url_quote", + collapse_http_schemes: bool = True, +) -> t.Optional[str]: + """Extracts the path info from the given URL (or WSGI environment) and + path. The path info returned is a string. The URLs might also be IRIs. + + If the path info could not be determined, `None` is returned. + + Some examples: + + >>> extract_path_info('http://example.com/app', '/app/hello') + '/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello') + '/hello' + >>> extract_path_info('http://example.com/app', + ... 'https://example.com/app/hello', + ... collapse_http_schemes=False) is None + True + + Instead of providing a base URL you can also pass a WSGI environment. + + :param environ_or_baseurl: a WSGI environment dict, a base URL or + base IRI. This is the root of the + application. + :param path_or_url: an absolute path from the server root, a + relative path (in which case it's the path info) + or a full URL. + :param charset: the charset for byte data in URLs + :param errors: the error handling on decode + :param collapse_http_schemes: if set to `False` the algorithm does + not assume that http and https on the + same server point to the same + resource. + + .. deprecated:: 2.2 + Will be removed in Werkzeug 2.3. + + .. versionchanged:: 0.15 + The ``errors`` parameter defaults to leaving invalid bytes + quoted instead of replacing them. + + .. versionadded:: 0.6 + + """ + warnings.warn( + "'extract_path_info' is deprecated and will be removed in Werkzeug 2.3.", + DeprecationWarning, + stacklevel=2, + ) + + def _normalize_netloc(scheme: str, netloc: str) -> str: + parts = netloc.split("@", 1)[-1].split(":", 1) + port: t.Optional[str] + + if len(parts) == 2: + netloc, port = parts + if (scheme == "http" and port == "80") or ( + scheme == "https" and port == "443" + ): + port = None + else: + netloc = parts[0] + port = None + + if port is not None: + netloc += f":{port}" + + return netloc + + # make sure whatever we are working on is a IRI and parse it + path = uri_to_iri(path_or_url, charset, errors) + if isinstance(environ_or_baseurl, dict): + environ_or_baseurl = get_current_url(environ_or_baseurl, root_only=True) + base_iri = uri_to_iri(environ_or_baseurl, charset, errors) + base_scheme, base_netloc, base_path = url_parse(base_iri)[:3] + cur_scheme, cur_netloc, cur_path = url_parse(url_join(base_iri, path))[:3] + + # normalize the network location + base_netloc = _normalize_netloc(base_scheme, base_netloc) + cur_netloc = _normalize_netloc(cur_scheme, cur_netloc) + + # is that IRI even on a known HTTP scheme? + if collapse_http_schemes: + for scheme in base_scheme, cur_scheme: + if scheme not in ("http", "https"): + return None + else: + if not (base_scheme in ("http", "https") and base_scheme == cur_scheme): + return None + + # are the netlocs compatible? + if base_netloc != cur_netloc: + return None + + # are we below the application path? + base_path = base_path.rstrip("/") + if not cur_path.startswith(base_path): + return None + + return f"/{cur_path[len(base_path) :].lstrip('/')}" + + +class ClosingIterator: + """The WSGI specification requires that all middlewares and gateways + respect the `close` callback of the iterable returned by the application. + Because it is useful to add another close action to a returned iterable + and adding a custom iterable is a boring task this class can be used for + that:: + + return ClosingIterator(app(environ, start_response), [cleanup_session, + cleanup_locals]) + + If there is just one close function it can be passed instead of the list. + + A closing iterator is not needed if the application uses response objects + and finishes the processing if the response is started:: + + try: + return response(environ, start_response) + finally: + cleanup_session() + cleanup_locals() + """ + + def __init__( + self, + iterable: t.Iterable[bytes], + callbacks: t.Optional[ + t.Union[t.Callable[[], None], t.Iterable[t.Callable[[], None]]] + ] = None, + ) -> None: + iterator = iter(iterable) + self._next = t.cast(t.Callable[[], bytes], partial(next, iterator)) + if callbacks is None: + callbacks = [] + elif callable(callbacks): + callbacks = [callbacks] + else: + callbacks = list(callbacks) + iterable_close = getattr(iterable, "close", None) + if iterable_close: + callbacks.insert(0, iterable_close) + self._callbacks = callbacks + + def __iter__(self) -> "ClosingIterator": + return self + + def __next__(self) -> bytes: + return self._next() + + def close(self) -> None: + for callback in self._callbacks: + callback() + + +def wrap_file( + environ: "WSGIEnvironment", file: t.IO[bytes], buffer_size: int = 8192 +) -> t.Iterable[bytes]: + """Wraps a file. This uses the WSGI server's file wrapper if available + or otherwise the generic :class:`FileWrapper`. + + .. versionadded:: 0.5 + + If the file wrapper from the WSGI server is used it's important to not + iterate over it from inside the application but to pass it through + unchanged. If you want to pass out a file wrapper inside a response + object you have to set :attr:`Response.direct_passthrough` to `True`. + + More information about file wrappers are available in :pep:`333`. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + return environ.get("wsgi.file_wrapper", FileWrapper)( # type: ignore + file, buffer_size + ) + + +class FileWrapper: + """This class can be used to convert a :class:`file`-like object into + an iterable. It yields `buffer_size` blocks until the file is fully + read. + + You should not use this class directly but rather use the + :func:`wrap_file` function that uses the WSGI server's file wrapper + support if it's available. + + .. versionadded:: 0.5 + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param file: a :class:`file`-like object with a :meth:`~file.read` method. + :param buffer_size: number of bytes for one iteration. + """ + + def __init__(self, file: t.IO[bytes], buffer_size: int = 8192) -> None: + self.file = file + self.buffer_size = buffer_size + + def close(self) -> None: + if hasattr(self.file, "close"): + self.file.close() + + def seekable(self) -> bool: + if hasattr(self.file, "seekable"): + return self.file.seekable() + if hasattr(self.file, "seek"): + return True + return False + + def seek(self, *args: t.Any) -> None: + if hasattr(self.file, "seek"): + self.file.seek(*args) + + def tell(self) -> t.Optional[int]: + if hasattr(self.file, "tell"): + return self.file.tell() + return None + + def __iter__(self) -> "FileWrapper": + return self + + def __next__(self) -> bytes: + data = self.file.read(self.buffer_size) + if data: + return data + raise StopIteration() + + +class _RangeWrapper: + # private for now, but should we make it public in the future ? + + """This class can be used to convert an iterable object into + an iterable that will only yield a piece of the underlying content. + It yields blocks until the underlying stream range is fully read. + The yielded blocks will have a size that can't exceed the original + iterator defined block size, but that can be smaller. + + If you're using this object together with a :class:`Response` you have + to use the `direct_passthrough` mode. + + :param iterable: an iterable object with a :meth:`__next__` method. + :param start_byte: byte from which read will start. + :param byte_range: how many bytes to read. + """ + + def __init__( + self, + iterable: t.Union[t.Iterable[bytes], t.IO[bytes]], + start_byte: int = 0, + byte_range: t.Optional[int] = None, + ): + self.iterable = iter(iterable) + self.byte_range = byte_range + self.start_byte = start_byte + self.end_byte = None + + if byte_range is not None: + self.end_byte = start_byte + byte_range + + self.read_length = 0 + self.seekable = hasattr(iterable, "seekable") and iterable.seekable() + self.end_reached = False + + def __iter__(self) -> "_RangeWrapper": + return self + + def _next_chunk(self) -> bytes: + try: + chunk = next(self.iterable) + self.read_length += len(chunk) + return chunk + except StopIteration: + self.end_reached = True + raise + + def _first_iteration(self) -> t.Tuple[t.Optional[bytes], int]: + chunk = None + if self.seekable: + self.iterable.seek(self.start_byte) # type: ignore + self.read_length = self.iterable.tell() # type: ignore + contextual_read_length = self.read_length + else: + while self.read_length <= self.start_byte: + chunk = self._next_chunk() + if chunk is not None: + chunk = chunk[self.start_byte - self.read_length :] + contextual_read_length = self.start_byte + return chunk, contextual_read_length + + def _next(self) -> bytes: + if self.end_reached: + raise StopIteration() + chunk = None + contextual_read_length = self.read_length + if self.read_length == 0: + chunk, contextual_read_length = self._first_iteration() + if chunk is None: + chunk = self._next_chunk() + if self.end_byte is not None and self.read_length >= self.end_byte: + self.end_reached = True + return chunk[: self.end_byte - contextual_read_length] + return chunk + + def __next__(self) -> bytes: + chunk = self._next() + if chunk: + return chunk + self.end_reached = True + raise StopIteration() + + def close(self) -> None: + if hasattr(self.iterable, "close"): + self.iterable.close() + + +def _make_chunk_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + limit: t.Optional[int], + buffer_size: int, +) -> t.Iterator[bytes]: + """Helper for the line and chunk iter functions.""" + if isinstance(stream, (bytes, bytearray, str)): + raise TypeError( + "Passed a string or byte object instead of true iterator or stream." + ) + if not hasattr(stream, "read"): + for item in stream: + if item: + yield item + return + stream = t.cast(t.IO[bytes], stream) + if not isinstance(stream, LimitedStream) and limit is not None: + stream = t.cast(t.IO[bytes], LimitedStream(stream, limit)) + _read = stream.read + while True: + item = _read(buffer_size) + if not item: + break + yield item + + +def make_line_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + limit: t.Optional[int] = None, + buffer_size: int = 10 * 1024, + cap_at_buffer: bool = False, +) -> t.Iterator[bytes]: + """Safely iterates line-based over an input stream. If the input stream + is not a :class:`LimitedStream` the `limit` parameter is mandatory. + + This uses the stream's :meth:`~file.read` method internally as opposite + to the :meth:`~file.readline` method that is unsafe and can only be used + in violation of the WSGI specification. The same problem applies to the + `__iter__` function of the input stream which calls :meth:`~file.readline` + without arguments. + + If you need line-by-line processing it's strongly recommended to iterate + over the input stream using this helper function. + + .. versionchanged:: 0.8 + This function now ensures that the limit was reached. + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is a :class:`LimitedStream`. + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, "") + if not first_item: + return + + s = _make_encode_wrapper(first_item) + empty = t.cast(bytes, s("")) + cr = t.cast(bytes, s("\r")) + lf = t.cast(bytes, s("\n")) + crlf = t.cast(bytes, s("\r\n")) + + _iter = t.cast(t.Iterator[bytes], chain((first_item,), _iter)) + + def _iter_basic_lines() -> t.Iterator[bytes]: + _join = empty.join + buffer: t.List[bytes] = [] + while True: + new_data = next(_iter, "") + if not new_data: + break + new_buf: t.List[bytes] = [] + buf_size = 0 + for item in t.cast( + t.Iterator[bytes], chain(buffer, new_data.splitlines(True)) + ): + new_buf.append(item) + buf_size += len(item) + if item and item[-1:] in crlf: + yield _join(new_buf) + new_buf = [] + elif cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buffer = new_buf + if buffer: + yield _join(buffer) + + # This hackery is necessary to merge 'foo\r' and '\n' into one item + # of 'foo\r\n' if we were unlucky and we hit a chunk boundary. + previous = empty + for item in _iter_basic_lines(): + if item == lf and previous[-1:] == cr: + previous += item + item = empty + if previous: + yield previous + previous = item + if previous: + yield previous + + +def make_chunk_iter( + stream: t.Union[t.Iterable[bytes], t.IO[bytes]], + separator: bytes, + limit: t.Optional[int] = None, + buffer_size: int = 10 * 1024, + cap_at_buffer: bool = False, +) -> t.Iterator[bytes]: + """Works like :func:`make_line_iter` but accepts a separator + which divides chunks. If you want newline based processing + you should use :func:`make_line_iter` instead as it + supports arbitrary newline markers. + + .. versionadded:: 0.8 + + .. versionadded:: 0.9 + added support for iterators as input stream. + + .. versionadded:: 0.11.10 + added support for the `cap_at_buffer` parameter. + + :param stream: the stream or iterate to iterate over. + :param separator: the separator that divides chunks. + :param limit: the limit in bytes for the stream. (Usually + content length. Not necessary if the `stream` + is otherwise already limited). + :param buffer_size: The optional buffer size. + :param cap_at_buffer: if this is set chunks are split if they are longer + than the buffer size. Internally this is implemented + that the buffer size might be exhausted by a factor + of two however. + """ + _iter = _make_chunk_iter(stream, limit, buffer_size) + + first_item = next(_iter, b"") + if not first_item: + return + + _iter = t.cast(t.Iterator[bytes], chain((first_item,), _iter)) + if isinstance(first_item, str): + separator = _to_str(separator) + _split = re.compile(f"({re.escape(separator)})").split + _join = "".join + else: + separator = _to_bytes(separator) + _split = re.compile(b"(" + re.escape(separator) + b")").split + _join = b"".join + + buffer: t.List[bytes] = [] + while True: + new_data = next(_iter, b"") + if not new_data: + break + chunks = _split(new_data) + new_buf: t.List[bytes] = [] + buf_size = 0 + for item in chain(buffer, chunks): + if item == separator: + yield _join(new_buf) + new_buf = [] + buf_size = 0 + else: + buf_size += len(item) + new_buf.append(item) + + if cap_at_buffer and buf_size >= buffer_size: + rv = _join(new_buf) + while len(rv) >= buffer_size: + yield rv[:buffer_size] + rv = rv[buffer_size:] + new_buf = [rv] + buf_size = len(rv) + + buffer = new_buf + if buffer: + yield _join(buffer) + + +class LimitedStream(io.IOBase): + """Wraps a stream so that it doesn't read more than n bytes. If the + stream is exhausted and the caller tries to get more bytes from it + :func:`on_exhausted` is called which by default returns an empty + string. The return value of that function is forwarded + to the reader function. So if it returns an empty string + :meth:`read` will return an empty string as well. + + The limit however must never be higher than what the stream can + output. Otherwise :meth:`readlines` will try to read past the + limit. + + .. admonition:: Note on WSGI compliance + + calls to :meth:`readline` and :meth:`readlines` are not + WSGI compliant because it passes a size argument to the + readline methods. Unfortunately the WSGI PEP is not safely + implementable without a size argument to :meth:`readline` + because there is no EOF marker in the stream. As a result + of that the use of :meth:`readline` is discouraged. + + For the same reason iterating over the :class:`LimitedStream` + is not portable. It internally calls :meth:`readline`. + + We strongly suggest using :meth:`read` only or using the + :func:`make_line_iter` which safely iterates line-based + over a WSGI input stream. + + :param stream: the stream to wrap. + :param limit: the limit for the stream, must not be longer than + what the string can provide if the stream does not + end with `EOF` (like `wsgi.input`) + """ + + def __init__(self, stream: t.IO[bytes], limit: int) -> None: + self._read = stream.read + self._readline = stream.readline + self._pos = 0 + self.limit = limit + + def __iter__(self) -> "LimitedStream": + return self + + @property + def is_exhausted(self) -> bool: + """If the stream is exhausted this attribute is `True`.""" + return self._pos >= self.limit + + def on_exhausted(self) -> bytes: + """This is called when the stream tries to read past the limit. + The return value of this function is returned from the reading + function. + """ + # Read null bytes from the stream so that we get the + # correct end of stream marker. + return self._read(0) + + def on_disconnect(self) -> bytes: + """What should happen if a disconnect is detected? The return + value of this function is returned from read functions in case + the client went away. By default a + :exc:`~werkzeug.exceptions.ClientDisconnected` exception is raised. + """ + from .exceptions import ClientDisconnected + + raise ClientDisconnected() + + def _exhaust_chunks(self, chunk_size: int = 1024 * 64) -> t.Iterator[bytes]: + """Exhaust the stream by reading until the limit is reached or the client + disconnects, yielding each chunk. + + :param chunk_size: How many bytes to read at a time. + + :meta private: + + .. versionadded:: 2.2.3 + """ + to_read = self.limit - self._pos + + while to_read > 0: + chunk = self.read(min(to_read, chunk_size)) + yield chunk + to_read -= len(chunk) + + def exhaust(self, chunk_size: int = 1024 * 64) -> None: + """Exhaust the stream by reading until the limit is reached or the client + disconnects, discarding the data. + + :param chunk_size: How many bytes to read at a time. + + .. versionchanged:: 2.2.3 + Handle case where wrapped stream returns fewer bytes than requested. + """ + for _ in self._exhaust_chunks(chunk_size): + pass + + def read(self, size: t.Optional[int] = None) -> bytes: + """Read up to ``size`` bytes from the underlying stream. If size is not + provided, read until the limit. + + If the limit is reached, :meth:`on_exhausted` is called, which returns empty + bytes. + + If no bytes are read and the limit is not reached, or if an error occurs during + the read, :meth:`on_disconnect` is called, which raises + :exc:`.ClientDisconnected`. + + :param size: The number of bytes to read. ``None``, default, reads until the + limit is reached. + + .. versionchanged:: 2.2.3 + Handle case where wrapped stream returns fewer bytes than requested. + """ + if self._pos >= self.limit: + return self.on_exhausted() + + if size is None or size == -1: # -1 is for consistency with file + # Keep reading from the wrapped stream until the limit is reached. Can't + # rely on stream.read(size) because it's not guaranteed to return size. + buf = bytearray() + + for chunk in self._exhaust_chunks(): + buf.extend(chunk) + + return bytes(buf) + + to_read = min(self.limit - self._pos, size) + + try: + read = self._read(to_read) + except (OSError, ValueError): + return self.on_disconnect() + + if to_read and not len(read): + # If no data was read, treat it as a disconnect. As long as some data was + # read, a subsequent call can still return more before reaching the limit. + return self.on_disconnect() + + self._pos += len(read) + return read + + def readline(self, size: t.Optional[int] = None) -> bytes: + """Reads one line from the stream.""" + if self._pos >= self.limit: + return self.on_exhausted() + if size is None: + size = self.limit - self._pos + else: + size = min(size, self.limit - self._pos) + try: + line = self._readline(size) + except (ValueError, OSError): + return self.on_disconnect() + if size and not line: + return self.on_disconnect() + self._pos += len(line) + return line + + def readlines(self, size: t.Optional[int] = None) -> t.List[bytes]: + """Reads a file into a list of strings. It calls :meth:`readline` + until the file is read to the end. It does support the optional + `size` argument if the underlying stream supports it for + `readline`. + """ + last_pos = self._pos + result = [] + if size is not None: + end = min(self.limit, last_pos + size) + else: + end = self.limit + while True: + if size is not None: + size -= last_pos - self._pos + if self._pos >= end: + break + result.append(self.readline(size)) + if size is not None: + last_pos = self._pos + return result + + def tell(self) -> int: + """Returns the position of the stream. + + .. versionadded:: 0.9 + """ + return self._pos + + def __next__(self) -> bytes: + line = self.readline() + if not line: + raise StopIteration() + return line + + def readable(self) -> bool: + return True diff --git a/flask-server/venv/pyvenv.cfg b/flask-server/venv/pyvenv.cfg new file mode 100644 index 00000000..c7b9bb81 --- /dev/null +++ b/flask-server/venv/pyvenv.cfg @@ -0,0 +1,3 @@ +home = /Library/Frameworks/Python.framework/Versions/3.10/bin +include-system-site-packages = false +version = 3.10.8 diff --git a/node_modules/.bin/loose-envify b/node_modules/.bin/loose-envify new file mode 120000 index 00000000..ed9009c5 --- /dev/null +++ b/node_modules/.bin/loose-envify @@ -0,0 +1 @@ +../loose-envify/cli.js \ No newline at end of file diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 00000000..29b56fa5 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,97 @@ +{ + "name": "cancer-detection", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/@remix-run/router": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.5.0.tgz", + "integrity": "sha512-bkUDCp8o1MvFO+qxkODcbhSqRa6P2GXgrGZVpt0dCXNW2HCSCqYI0ZoAqEOSAjRWmmlKcYgFvN4B4S+zo/f8kg==", + "engines": { + "node": ">=14" + } + }, + "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==", + "peer": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-router": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.10.0.tgz", + "integrity": "sha512-Nrg0BWpQqrC3ZFFkyewrflCud9dio9ME3ojHCF/WLsprJVzkq3q3UeEhMCAW1dobjeGbWgjNn/PVF6m46ANxXQ==", + "dependencies": { + "@remix-run/router": "1.5.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.10.0.tgz", + "integrity": "sha512-E5dfxRPuXKJqzwSe/qGcqdwa18QiWC6f3H3cWXM24qj4N0/beCIf/CWTipop2xm7mR0RCS99NnaqPNjHtrAzCg==", + "dependencies": { + "@remix-run/router": "1.5.0", + "react-router": "6.10.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + } + } +} diff --git a/node_modules/@remix-run/router/CHANGELOG.md b/node_modules/@remix-run/router/CHANGELOG.md new file mode 100644 index 00000000..a4b4db23 --- /dev/null +++ b/node_modules/@remix-run/router/CHANGELOG.md @@ -0,0 +1,272 @@ +# `@remix-run/router` + +## 1.5.0 + +### Minor Changes + +- Added support for [**Future Flags**](https://reactrouter.com/en/main/guides/api-development-strategy) in React Router. The first flag being introduced is `future.v7_normalizeFormMethod` which will normalize the exposed `useNavigation()/useFetcher()` `formMethod` fields as uppercase HTTP methods to align with the `fetch()` behavior. ([#10207](https://github.com/remix-run/react-router/pull/10207)) + + - When `future.v7_normalizeFormMethod === false` (default v6 behavior), + - `useNavigation().formMethod` is lowercase + - `useFetcher().formMethod` is lowercase + - When `future.v7_normalizeFormMethod === true`: + - `useNavigation().formMethod` is uppercase + - `useFetcher().formMethod` is uppercase + +### Patch Changes + +- Provide fetcher submission to `shouldRevalidate` if the fetcher action redirects ([#10208](https://github.com/remix-run/react-router/pull/10208)) +- Properly handle `lazy()` errors during router initialization ([#10201](https://github.com/remix-run/react-router/pull/10201)) +- Remove `instanceof` check for `DeferredData` to be resilient to ESM/CJS boundaries in SSR bundling scenarios ([#10247](https://github.com/remix-run/react-router/pull/10247)) +- Update to latest `@remix-run/web-fetch@4.3.3` ([#10216](https://github.com/remix-run/react-router/pull/10216)) + +## 1.4.0 + +### Minor Changes + +- **Introducing Lazy Route Modules!** ([#10045](https://github.com/remix-run/react-router/pull/10045)) + + In order to keep your application bundles small and support code-splitting of your routes, we've introduced a new `lazy()` route property. This is an async function that resolves the non-route-matching portions of your route definition (`loader`, `action`, `element`/`Component`, `errorElement`/`ErrorBoundary`, `shouldRevalidate`, `handle`). + + Lazy routes are resolved on initial load and during the `loading` or `submitting` phase of a navigation or fetcher call. You cannot lazily define route-matching properties (`path`, `index`, `children`) since we only execute your lazy route functions after we've matched known routes. + + Your `lazy` functions will typically return the result of a dynamic import. + + ```jsx + // In this example, we assume most folks land on the homepage so we include that + // in our critical-path bundle, but then we lazily load modules for /a and /b so + // they don't load until the user navigates to those routes + let routes = createRoutesFromElements( + }> + } /> + import("./a")} /> + import("./b")} /> + + ); + ``` + + Then in your lazy route modules, export the properties you want defined for the route: + + ```jsx + export async function loader({ request }) { + let data = await fetchData(request); + return json(data); + } + + // Export a `Component` directly instead of needing to create a React Element from it + export function Component() { + let data = useLoaderData(); + + return ( + <> +

    You made it!

    +

    {data}

    + + ); + } + + // Export an `ErrorBoundary` directly instead of needing to create a React Element from it + export function ErrorBoundary() { + let error = useRouteError(); + return isRouteErrorResponse(error) ? ( +

    + {error.status} {error.statusText} +

    + ) : ( +

    {error.message || error}

    + ); + } + ``` + + An example of this in action can be found in the [`examples/lazy-loading-router-provider`](https://github.com/remix-run/react-router/tree/main/examples/lazy-loading-router-provider) directory of the repository. + + 🙌 Huge thanks to @rossipedia for the [Initial Proposal](https://github.com/remix-run/react-router/discussions/9826) and [POC Implementation](https://github.com/remix-run/react-router/pull/9830). + +### Patch Changes + +- Fix `generatePath` incorrectly applying parameters in some cases ([#10078](https://github.com/remix-run/react-router/pull/10078)) + +## 1.3.3 + +### Patch Changes + +- Correctly perform a hard redirect for same-origin absolute URLs outside of the router `basename` ([#10076](https://github.com/remix-run/react-router/pull/10076)) +- Ensure status code and headers are maintained for `defer` loader responses in `createStaticHandler`'s `query()` method ([#10077](https://github.com/remix-run/react-router/pull/10077)) +- Change `invariant` to an `UNSAFE_invariant` export since it's only intended for internal use ([#10066](https://github.com/remix-run/react-router/pull/10066)) +- Add internal API for custom HMR implementations ([#9996](https://github.com/remix-run/react-router/pull/9996)) + +## 1.3.2 + +### Patch Changes + +- Remove inaccurate console warning for POP navigations and update active blocker logic ([#10030](https://github.com/remix-run/react-router/pull/10030)) +- Only check for differing origin on absolute URL redirects ([#10033](https://github.com/remix-run/react-router/pull/10033)) + +## 1.3.1 + +### Patch Changes + +- Fixes 2 separate issues for revalidating fetcher `shouldRevalidate` calls ([#9948](https://github.com/remix-run/react-router/pull/9948)) + - The `shouldRevalidate` function was only being called for _explicit_ revalidation scenarios (after a mutation, manual `useRevalidator` call, or an `X-Remix-Revalidate` header used for cookie setting in Remix). It was not properly being called on _implicit_ revalidation scenarios that also apply to navigation `loader` revalidation, such as a change in search params or clicking a link for the page we're already on. It's now correctly called in those additional scenarios. + - The parameters being passed were incorrect and inconsistent with one another since the `current*`/`next*` parameters reflected the static `fetcher.load` URL (and thus were identical). Instead, they should have reflected the the navigation that triggered the revalidation (as the `form*` parameters did). These parameters now correctly reflect the triggering navigation. +- Respect `preventScrollReset` on `` ([#9963](https://github.com/remix-run/react-router/pull/9963)) +- Do not short circuit on hash change only mutation submissions ([#9944](https://github.com/remix-run/react-router/pull/9944)) +- Remove `instanceof` check from `isRouteErrorResponse` to avoid bundling issues on the server ([#9930](https://github.com/remix-run/react-router/pull/9930)) +- Fix navigation for hash routers on manual URL changes ([#9980](https://github.com/remix-run/react-router/pull/9980)) +- Detect when a `defer` call only contains critical data and remove the `AbortController` ([#9965](https://github.com/remix-run/react-router/pull/9965)) +- Send the name as the value when url-encoding `File` `FormData` entries ([#9867](https://github.com/remix-run/react-router/pull/9867)) + +## 1.3.0 + +### Minor Changes + +- Added support for navigation blocking APIs ([#9709](https://github.com/remix-run/react-router/pull/9709)) +- Expose deferred information from `createStaticHandler` ([#9760](https://github.com/remix-run/react-router/pull/9760)) + +### Patch Changes + +- Improved absolute redirect url detection in actions/loaders ([#9829](https://github.com/remix-run/react-router/pull/9829)) +- Fix URL creation with memory histories ([#9814](https://github.com/remix-run/react-router/pull/9814)) +- Fix `generatePath` when optional params are present ([#9764](https://github.com/remix-run/react-router/pull/9764)) +- Fix scroll reset if a submission redirects ([#9886](https://github.com/remix-run/react-router/pull/9886)) +- Fix 404 bug with same-origin absolute redirects ([#9913](https://github.com/remix-run/react-router/pull/9913)) +- Support `OPTIONS` requests in `staticHandler.queryRoute` ([#9914](https://github.com/remix-run/react-router/pull/9914)) + +## 1.2.1 + +### Patch Changes + +- Include submission info in `shouldRevalidate` on action redirects ([#9777](https://github.com/remix-run/react-router/pull/9777), [#9782](https://github.com/remix-run/react-router/pull/9782)) +- Reset `actionData` on action redirect to current location ([#9772](https://github.com/remix-run/react-router/pull/9772)) + +## 1.2.0 + +### Minor Changes + +- Remove `unstable_` prefix from `createStaticHandler`/`createStaticRouter`/`StaticRouterProvider` ([#9738](https://github.com/remix-run/react-router/pull/9738)) + +### Patch Changes + +- Fix explicit `replace` on submissions and `PUSH` on submission to new paths ([#9734](https://github.com/remix-run/react-router/pull/9734)) +- Fix a few bugs where loader/action data wasn't properly cleared on errors ([#9735](https://github.com/remix-run/react-router/pull/9735)) +- Prevent `useLoaderData` usage in `errorElement` ([#9735](https://github.com/remix-run/react-router/pull/9735)) +- Skip initial scroll restoration for SSR apps with `hydrationData` ([#9664](https://github.com/remix-run/react-router/pull/9664)) + +## 1.1.0 + +This release introduces support for [Optional Route Segments](https://github.com/remix-run/react-router/issues/9546). Now, adding a `?` to the end of any path segment will make that entire segment optional. This works for both static segments and dynamic parameters. + +**Optional Params Examples** + +- Path `lang?/about` will match: + - `/:lang/about` + - `/about` +- Path `/multistep/:widget1?/widget2?/widget3?` will match: + - `/multistep` + - `/multistep/:widget1` + - `/multistep/:widget1/:widget2` + - `/multistep/:widget1/:widget2/:widget3` + +**Optional Static Segment Example** + +- Path `/home?` will match: + - `/` + - `/home` +- Path `/fr?/about` will match: + - `/about` + - `/fr/about` + +### Minor Changes + +- Allows optional routes and optional static segments ([#9650](https://github.com/remix-run/react-router/pull/9650)) + +### Patch Changes + +- Stop incorrectly matching on partial named parameters, i.e. ``, to align with how splat parameters work. If you were previously relying on this behavior then it's recommended to extract the static portion of the path at the `useParams` call site: ([#9506](https://github.com/remix-run/react-router/pull/9506)) + +```jsx +// Old behavior at URL /prefix-123 + }> + +function Comp() { + let params = useParams(); // { id: '123' } + let id = params.id; // "123" + ... +} + +// New behavior at URL /prefix-123 + }> + +function Comp() { + let params = useParams(); // { id: 'prefix-123' } + let id = params.id.replace(/^prefix-/, ''); // "123" + ... +} +``` + +- Persist `headers` on `loader` `request`'s after SSR document `action` request ([#9721](https://github.com/remix-run/react-router/pull/9721)) +- Fix requests sent to revalidating loaders so they reflect a GET request ([#9660](https://github.com/remix-run/react-router/pull/9660)) +- Fix issue with deeply nested optional segments ([#9727](https://github.com/remix-run/react-router/pull/9727)) +- GET forms now expose a submission on the loading navigation ([#9695](https://github.com/remix-run/react-router/pull/9695)) +- Fix error boundary tracking for multiple errors bubbling to the same boundary ([#9702](https://github.com/remix-run/react-router/pull/9702)) + +## 1.0.5 + +### Patch Changes + +- Fix requests sent to revalidating loaders so they reflect a `GET` request ([#9680](https://github.com/remix-run/react-router/pull/9680)) +- Remove `instanceof Response` checks in favor of `isResponse` ([#9690](https://github.com/remix-run/react-router/pull/9690)) +- Fix `URL` creation in Cloudflare Pages or other non-browser-environments ([#9682](https://github.com/remix-run/react-router/pull/9682), [#9689](https://github.com/remix-run/react-router/pull/9689)) +- Add `requestContext` support to static handler `query`/`queryRoute` ([#9696](https://github.com/remix-run/react-router/pull/9696)) + - Note that the unstable API of `queryRoute(path, routeId)` has been changed to `queryRoute(path, { routeId, requestContext })` + +## 1.0.4 + +### Patch Changes + +- Throw an error if an `action`/`loader` function returns `undefined` as revalidations need to know whether the loader has previously been executed. `undefined` also causes issues during SSR stringification for hydration. You should always ensure you `loader`/`action` returns a value, and you may return `null` if you don't wish to return anything. ([#9511](https://github.com/remix-run/react-router/pull/9511)) +- Properly handle redirects to external domains ([#9590](https://github.com/remix-run/react-router/pull/9590), [#9654](https://github.com/remix-run/react-router/pull/9654)) +- Preserve the HTTP method on 307/308 redirects ([#9597](https://github.com/remix-run/react-router/pull/9597)) +- Support `basename` in static data routers ([#9591](https://github.com/remix-run/react-router/pull/9591)) +- Enhanced `ErrorResponse` bodies to contain more descriptive text in internal 403/404/405 scenarios + +## 1.0.3 + +### Patch Changes + +- Fix hrefs generated when using `createHashRouter` ([#9409](https://github.com/remix-run/react-router/pull/9409)) +- fix encoding/matching issues with special chars ([#9477](https://github.com/remix-run/react-router/pull/9477), [#9496](https://github.com/remix-run/react-router/pull/9496)) +- Support `basename` and relative routing in `loader`/`action` redirects ([#9447](https://github.com/remix-run/react-router/pull/9447)) +- Ignore pathless layout routes when looking for proper submission `action` function ([#9455](https://github.com/remix-run/react-router/pull/9455)) +- properly support `index` routes with a `path` in `useResolvedPath` ([#9486](https://github.com/remix-run/react-router/pull/9486)) +- Add UMD build for `@remix-run/router` ([#9446](https://github.com/remix-run/react-router/pull/9446)) +- fix `createURL` in local file execution in Firefox ([#9464](https://github.com/remix-run/react-router/pull/9464)) +- Updates to `unstable_createStaticHandler` for incorporating into Remix ([#9482](https://github.com/remix-run/react-router/pull/9482), [#9465](https://github.com/remix-run/react-router/pull/9465)) + +## 1.0.2 + +### Patch Changes + +- Reset `actionData` after a successful action redirect ([#9334](https://github.com/remix-run/react-router/pull/9334)) +- Update `matchPath` to avoid false positives on dash-separated segments ([#9300](https://github.com/remix-run/react-router/pull/9300)) +- If an index route has children, it will result in a runtime error. We have strengthened our `RouteObject`/`RouteProps` types to surface the error in TypeScript. ([#9366](https://github.com/remix-run/react-router/pull/9366)) + +## 1.0.1 + +### Patch Changes + +- Preserve state from `initialEntries` ([#9288](https://github.com/remix-run/react-router/pull/9288)) +- Preserve `?index` for fetcher get submissions to index routes ([#9312](https://github.com/remix-run/react-router/pull/9312)) + +## 1.0.0 + +This is the first stable release of `@remix-run/router`, which provides all the underlying routing and data loading/mutation logic for `react-router`. You should _not_ be using this package directly unless you are authoring a routing library similar to `react-router`. + +For an overview of the features provided by `react-router`, we recommend you go check out the [docs][rr-docs], especially the [feature overview][rr-feature-overview] and the [tutorial][rr-tutorial]. + +For an overview of the features provided by `@remix-run/router`, please check out the [`README`][remix-router-readme]. + +[rr-docs]: https://reactrouter.com +[rr-feature-overview]: https://reactrouter.com/start/overview +[rr-tutorial]: https://reactrouter.com/start/tutorial +[remix-router-readme]: https://github.com/remix-run/react-router/blob/main/packages/router/README.md diff --git a/node_modules/@remix-run/router/LICENSE.md b/node_modules/@remix-run/router/LICENSE.md new file mode 100644 index 00000000..47c96cbd --- /dev/null +++ b/node_modules/@remix-run/router/LICENSE.md @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) React Training 2015-2019 +Copyright (c) Remix Software 2020-2022 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/@remix-run/router/README.md b/node_modules/@remix-run/router/README.md new file mode 100644 index 00000000..e0589a0d --- /dev/null +++ b/node_modules/@remix-run/router/README.md @@ -0,0 +1,107 @@ +# Remix Router + +The `@remix-run/router` package is a framework-agnostic routing package (sometimes referred to as a browser-emulator) that serves as the heart of [React Router][react-router] and [Remix][remix] and provides all the core functionality for routing coupled with data loading and data mutations. It comes with built-in handling of errors, race-conditions, interruptions, cancellations, lazy-loading data, and much, much more. + +If you're using React Router, you should never `import` anything directly from the `@remix-run/router` or `react-router` packages, but you should have everything you need in either `react-router-dom` or `react-router-native`. Both of those packages re-export everything from `@remix-run/router` and `react-router`. + +> **Warning** +> +> This router is a low-level package intended to be consumed by UI layer routing libraries. You should very likely not be using this package directly unless you are authoring a routing library such as [`react-router-dom`][react-router-repo] or one of it's other [UI ports][remix-routers-repo]. + +## API + +A Router instance can be created using `createRouter`: + +```js +// Create and initialize a router. "initialize" contains all side effects +// including history listeners and kicking off the initial data fetch +let router = createRouter({ + // Routes array + routes: , + // History instance + history, +}).initialize() +``` + +Internally, the Router represents the state in an object of the following format, which is available through `router.state`. You can also register a subscriber of the signature `(state: RouterState) => void` to execute when the state updates via `router.subscribe()`; + +```ts +interface RouterState { + // False during the initial data load, true once we have our initial data + initialized: boolean; + // The `history` action of the most recently completed navigation + historyAction: Action; + // The current location of the router. During a navigation this reflects + // the "old" location and is updated upon completion of the navigation + location: Location; + // The current set of route matches + matches: DataRouteMatch[]; + // The state of the current navigation + navigation: Navigation; + // The state of any in-progress router.revalidate() calls + revalidation: RevalidationState; + // Data from the loaders for the current matches + loaderData: RouteData; + // Data from the action for the current matches + actionData: RouteData | null; + // Errors thrown from loaders/actions for the current matches + errors: RouteData | null; + // Map of all active fetchers + fetchers: Map; + // Scroll position to restore to for the active Location, false if we + // should not restore, or null if we don't have a saved position + // Note: must be enabled via router.enableScrollRestoration() + restoreScrollPosition: number | false | null; + // Proxied `preventScrollReset` value passed to router.navigate() + preventScrollReset: boolean; +} +``` + +### Navigations + +All navigations are done through the `router.navigate` API which is overloaded to support different types of navigations: + +```js +// Link navigation (pushes onto the history stack by default) +router.navigate("/page"); + +// Link navigation (replacing the history stack) +router.navigate("/page", { replace: true }); + +// Pop navigation (moving backward/forward in the history stack) +router.navigate(-1); + +// Form submission navigation +let formData = new FormData(); +formData.append(key, value); +router.navigate("/page", { + formMethod: "post", + formData, +}); +``` + +### Fetchers + +Fetchers are a mechanism to call loaders/actions without triggering a navigation, and are done through the `router.fetch()` API. All fetch calls require a unique key to identify the fetcher. + +```js +// Execute the loader for /page +router.fetch("key", "/page"); + +// Submit to the action for /page +let formData = new FormData(); +formData.append(key, value); +router.fetch("key", "/page", { + formMethod: "post", + formData, +}); +``` + +### Revalidation + +By default, active loaders will revalidate after any navigation or fetcher mutation. If you need to kick off a revalidation for other use-cases, you can use `router.revalidate()` to re-execute all active loaders. + +[react-router]: https://reactrouter.com +[remix]: https://remix.run +[react-router-repo]: https://github.com/remix-run/react-router +[remix-routers-repo]: https://github.com/brophdawg11/remix-routers diff --git a/node_modules/@remix-run/router/dist/history.d.ts b/node_modules/@remix-run/router/dist/history.d.ts new file mode 100644 index 00000000..34526493 --- /dev/null +++ b/node_modules/@remix-run/router/dist/history.d.ts @@ -0,0 +1,250 @@ +/** + * Actions represent the type of change to a location value. + */ +export declare enum Action { + /** + * A POP indicates a change to an arbitrary index in the history stack, such + * as a back or forward navigation. It does not describe the direction of the + * navigation, only that the current index changed. + * + * Note: This is the default action for newly created history objects. + */ + Pop = "POP", + /** + * A PUSH indicates a new entry being added to the history stack, such as when + * a link is clicked and a new page loads. When this happens, all subsequent + * entries in the stack are lost. + */ + Push = "PUSH", + /** + * A REPLACE indicates the entry at the current index in the history stack + * being replaced by a new one. + */ + Replace = "REPLACE" +} +/** + * The pathname, search, and hash values of a URL. + */ +export interface Path { + /** + * A URL pathname, beginning with a /. + */ + pathname: string; + /** + * A URL search string, beginning with a ?. + */ + search: string; + /** + * A URL fragment identifier, beginning with a #. + */ + hash: string; +} +/** + * An entry in a history stack. A location contains information about the + * URL path, as well as possibly some arbitrary state and a key. + */ +export interface Location extends Path { + /** + * A value of arbitrary data associated with this location. + */ + state: any; + /** + * A unique string associated with this location. May be used to safely store + * and retrieve data in some other storage API, like `localStorage`. + * + * Note: This value is always "default" on the initial location. + */ + key: string; +} +/** + * A change to the current location. + */ +export interface Update { + /** + * The action that triggered the change. + */ + action: Action; + /** + * The new location. + */ + location: Location; + /** + * The delta between this location and the former location in the history stack + */ + delta: number | null; +} +/** + * A function that receives notifications about location changes. + */ +export interface Listener { + (update: Update): void; +} +/** + * Describes a location that is the destination of some navigation, either via + * `history.push` or `history.replace`. May be either a URL or the pieces of a + * URL path. + */ +export declare type To = string | Partial; +/** + * A history is an interface to the navigation stack. The history serves as the + * source of truth for the current location, as well as provides a set of + * methods that may be used to change it. + * + * It is similar to the DOM's `window.history` object, but with a smaller, more + * focused API. + */ +export interface History { + /** + * The last action that modified the current location. This will always be + * Action.Pop when a history instance is first created. This value is mutable. + */ + readonly action: Action; + /** + * The current location. This value is mutable. + */ + readonly location: Location; + /** + * Returns a valid href for the given `to` value that may be used as + * the value of an attribute. + * + * @param to - The destination URL + */ + createHref(to: To): string; + /** + * Returns a URL for the given `to` value + * + * @param to - The destination URL + */ + createURL(to: To): URL; + /** + * Encode a location the same way window.history would do (no-op for memory + * history) so we ensure our PUSH/REPLACE navigations for data routers + * behave the same as POP + * + * @param to Unencoded path + */ + encodeLocation(to: To): Path; + /** + * Pushes a new location onto the history stack, increasing its length by one. + * If there were any entries in the stack after the current one, they are + * lost. + * + * @param to - The new URL + * @param state - Data to associate with the new location + */ + push(to: To, state?: any): void; + /** + * Replaces the current location in the history stack with a new one. The + * location that was replaced will no longer be available. + * + * @param to - The new URL + * @param state - Data to associate with the new location + */ + replace(to: To, state?: any): void; + /** + * Navigates `n` entries backward/forward in the history stack relative to the + * current index. For example, a "back" navigation would use go(-1). + * + * @param delta - The delta in the stack index + */ + go(delta: number): void; + /** + * Sets up a listener that will be called whenever the current location + * changes. + * + * @param listener - A function that will be called when the location changes + * @returns unlisten - A function that may be used to stop listening + */ + listen(listener: Listener): () => void; +} +/** + * A user-supplied object that describes a location. Used when providing + * entries to `createMemoryHistory` via its `initialEntries` option. + */ +export declare type InitialEntry = string | Partial; +export declare type MemoryHistoryOptions = { + initialEntries?: InitialEntry[]; + initialIndex?: number; + v5Compat?: boolean; +}; +/** + * A memory history stores locations in memory. This is useful in stateful + * environments where there is no web browser, such as node tests or React + * Native. + */ +export interface MemoryHistory extends History { + /** + * The current index in the history stack. + */ + readonly index: number; +} +/** + * Memory history stores the current location in memory. It is designed for use + * in stateful non-browser environments like tests and React Native. + */ +export declare function createMemoryHistory(options?: MemoryHistoryOptions): MemoryHistory; +/** + * A browser history stores the current location in regular URLs in a web + * browser environment. This is the standard for most web apps and provides the + * cleanest URLs the browser's address bar. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory + */ +export interface BrowserHistory extends UrlHistory { +} +export declare type BrowserHistoryOptions = UrlHistoryOptions; +/** + * Browser history stores the location in regular URLs. This is the standard for + * most web apps, but it requires some configuration on the server to ensure you + * serve the same app at multiple URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory + */ +export declare function createBrowserHistory(options?: BrowserHistoryOptions): BrowserHistory; +/** + * A hash history stores the current location in the fragment identifier portion + * of the URL in a web browser environment. + * + * This is ideal for apps that do not control the server for some reason + * (because the fragment identifier is never sent to the server), including some + * shared hosting environments that do not provide fine-grained controls over + * which pages are served at which URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory + */ +export interface HashHistory extends UrlHistory { +} +export declare type HashHistoryOptions = UrlHistoryOptions; +/** + * Hash history stores the location in window.location.hash. This makes it ideal + * for situations where you don't want to send the location to the server for + * some reason, either because you do cannot configure it or the URL space is + * reserved for something else. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory + */ +export declare function createHashHistory(options?: HashHistoryOptions): HashHistory; +/** + * @private + */ +export declare function invariant(value: boolean, message?: string): asserts value; +export declare function invariant(value: T | null | undefined, message?: string): asserts value is T; +export declare function warning(cond: any, message: string): void; +/** + * Creates a Location object with a unique key from the given Path + */ +export declare function createLocation(current: string | Location, to: To, state?: any, key?: string): Readonly; +/** + * Creates a string URL path from the given pathname, search, and hash components. + */ +export declare function createPath({ pathname, search, hash, }: Partial): string; +/** + * Parses a string URL path into its separate pathname, search, and hash components. + */ +export declare function parsePath(path: string): Partial; +export interface UrlHistory extends History { +} +export declare type UrlHistoryOptions = { + window?: Window; + v5Compat?: boolean; +}; diff --git a/node_modules/@remix-run/router/dist/index.d.ts b/node_modules/@remix-run/router/dist/index.d.ts new file mode 100644 index 00000000..324ac952 --- /dev/null +++ b/node_modules/@remix-run/router/dist/index.d.ts @@ -0,0 +1,9 @@ +export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, LazyRouteFunction, TrackedPromise, FormEncType, FormMethod, HTMLFormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, V7_FormMethod, } from "./utils"; +export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, } from "./utils"; +export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history"; +export { Action, createBrowserHistory, createPath, createHashHistory, createMemoryHistory, parsePath, } from "./history"; +export * from "./router"; +/** @internal */ +export type { RouteManifest as UNSAFE_RouteManifest } from "./utils"; +export { DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, } from "./utils"; +export { invariant as UNSAFE_invariant, warning as UNSAFE_warning, } from "./history"; diff --git a/node_modules/@remix-run/router/dist/router.cjs.js b/node_modules/@remix-run/router/dist/router.cjs.js new file mode 100644 index 00000000..24cec1c3 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.cjs.js @@ -0,0 +1,4267 @@ +/** + * @remix-run/router v1.5.0 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _extends() { + _extends = Object.assign ? Object.assign.bind() : function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + return _extends.apply(this, arguments); +} + +//////////////////////////////////////////////////////////////////////////////// +//#region Types and Constants +//////////////////////////////////////////////////////////////////////////////// + +/** + * Actions represent the type of change to a location value. + */ +exports.Action = void 0; +/** + * The pathname, search, and hash values of a URL. + */ + +(function (Action) { + Action["Pop"] = "POP"; + Action["Push"] = "PUSH"; + Action["Replace"] = "REPLACE"; +})(exports.Action || (exports.Action = {})); + +const PopStateEventType = "popstate"; //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region Memory History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A user-supplied object that describes a location. Used when providing + * entries to `createMemoryHistory` via its `initialEntries` option. + */ + +/** + * Memory history stores the current location in memory. It is designed for use + * in stateful non-browser environments like tests and React Native. + */ +function createMemoryHistory(options) { + if (options === void 0) { + options = {}; + } + + let { + initialEntries = ["/"], + initialIndex, + v5Compat = false + } = options; + let entries; // Declare so we can access from createMemoryLocation + + entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined)); + let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex); + let action = exports.Action.Pop; + let listener = null; + + function clampIndex(n) { + return Math.min(Math.max(n, 0), entries.length - 1); + } + + function getCurrentLocation() { + return entries[index]; + } + + function createMemoryLocation(to, state, key) { + if (state === void 0) { + state = null; + } + + let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key); + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to)); + return location; + } + + function createHref(to) { + return typeof to === "string" ? to : createPath(to); + } + + let history = { + get index() { + return index; + }, + + get action() { + return action; + }, + + get location() { + return getCurrentLocation(); + }, + + createHref, + + createURL(to) { + return new URL(createHref(to), "http://localhost"); + }, + + encodeLocation(to) { + let path = typeof to === "string" ? parsePath(to) : to; + return { + pathname: path.pathname || "", + search: path.search || "", + hash: path.hash || "" + }; + }, + + push(to, state) { + action = exports.Action.Push; + let nextLocation = createMemoryLocation(to, state); + index += 1; + entries.splice(index, entries.length, nextLocation); + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 1 + }); + } + }, + + replace(to, state) { + action = exports.Action.Replace; + let nextLocation = createMemoryLocation(to, state); + entries[index] = nextLocation; + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 0 + }); + } + }, + + go(delta) { + action = exports.Action.Pop; + let nextIndex = clampIndex(index + delta); + let nextLocation = entries[nextIndex]; + index = nextIndex; + + if (listener) { + listener({ + action, + location: nextLocation, + delta + }); + } + }, + + listen(fn) { + listener = fn; + return () => { + listener = null; + }; + } + + }; + return history; +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region Browser History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A browser history stores the current location in regular URLs in a web + * browser environment. This is the standard for most web apps and provides the + * cleanest URLs the browser's address bar. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory + */ + +/** + * Browser history stores the location in regular URLs. This is the standard for + * most web apps, but it requires some configuration on the server to ensure you + * serve the same app at multiple URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory + */ +function createBrowserHistory(options) { + if (options === void 0) { + options = {}; + } + + function createBrowserLocation(window, globalHistory) { + let { + pathname, + search, + hash + } = window.location; + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createBrowserHref(window, to) { + return typeof to === "string" ? to : createPath(to); + } + + return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options); +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region Hash History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A hash history stores the current location in the fragment identifier portion + * of the URL in a web browser environment. + * + * This is ideal for apps that do not control the server for some reason + * (because the fragment identifier is never sent to the server), including some + * shared hosting environments that do not provide fine-grained controls over + * which pages are served at which URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory + */ + +/** + * Hash history stores the location in window.location.hash. This makes it ideal + * for situations where you don't want to send the location to the server for + * some reason, either because you do cannot configure it or the URL space is + * reserved for something else. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory + */ +function createHashHistory(options) { + if (options === void 0) { + options = {}; + } + + function createHashLocation(window, globalHistory) { + let { + pathname = "/", + search = "", + hash = "" + } = parsePath(window.location.hash.substr(1)); + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createHashHref(window, to) { + let base = window.document.querySelector("base"); + let href = ""; + + if (base && base.getAttribute("href")) { + let url = window.location.href; + let hashIndex = url.indexOf("#"); + href = hashIndex === -1 ? url : url.slice(0, hashIndex); + } + + return href + "#" + (typeof to === "string" ? to : createPath(to)); + } + + function validateHashLocation(location, to) { + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")"); + } + + return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options); +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region UTILS +//////////////////////////////////////////////////////////////////////////////// + +/** + * @private + */ + +function invariant(value, message) { + if (value === false || value === null || typeof value === "undefined") { + throw new Error(message); + } +} +function warning(cond, message) { + if (!cond) { + // eslint-disable-next-line no-console + if (typeof console !== "undefined") console.warn(message); + + try { + // Welcome to debugging history! + // + // This error is thrown as a convenience so you can more easily + // find the source for a warning that appears in the console by + // enabling "pause on exceptions" in your JavaScript debugger. + throw new Error(message); // eslint-disable-next-line no-empty + } catch (e) {} + } +} + +function createKey() { + return Math.random().toString(36).substr(2, 8); +} +/** + * For browser-based histories, we combine the state and key into an object + */ + + +function getHistoryState(location, index) { + return { + usr: location.state, + key: location.key, + idx: index + }; +} +/** + * Creates a Location object with a unique key from the given Path + */ + + +function createLocation(current, to, state, key) { + if (state === void 0) { + state = null; + } + + let location = _extends({ + pathname: typeof current === "string" ? current : current.pathname, + search: "", + hash: "" + }, typeof to === "string" ? parsePath(to) : to, { + state, + // TODO: This could be cleaned up. push/replace should probably just take + // full Locations now and avoid the need to run through this flow at all + // But that's a pretty big refactor to the current test suite so going to + // keep as is for the time being and just let any incoming keys take precedence + key: to && to.key || key || createKey() + }); + + return location; +} +/** + * Creates a string URL path from the given pathname, search, and hash components. + */ + +function createPath(_ref) { + let { + pathname = "/", + search = "", + hash = "" + } = _ref; + if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search; + if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash; + return pathname; +} +/** + * Parses a string URL path into its separate pathname, search, and hash components. + */ + +function parsePath(path) { + let parsedPath = {}; + + if (path) { + let hashIndex = path.indexOf("#"); + + if (hashIndex >= 0) { + parsedPath.hash = path.substr(hashIndex); + path = path.substr(0, hashIndex); + } + + let searchIndex = path.indexOf("?"); + + if (searchIndex >= 0) { + parsedPath.search = path.substr(searchIndex); + path = path.substr(0, searchIndex); + } + + if (path) { + parsedPath.pathname = path; + } + } + + return parsedPath; +} + +function getUrlBasedHistory(getLocation, createHref, validateLocation, options) { + if (options === void 0) { + options = {}; + } + + let { + window = document.defaultView, + v5Compat = false + } = options; + let globalHistory = window.history; + let action = exports.Action.Pop; + let listener = null; + let index = getIndex(); // Index should only be null when we initialize. If not, it's because the + // user called history.pushState or history.replaceState directly, in which + // case we should log a warning as it will result in bugs. + + if (index == null) { + index = 0; + globalHistory.replaceState(_extends({}, globalHistory.state, { + idx: index + }), ""); + } + + function getIndex() { + let state = globalHistory.state || { + idx: null + }; + return state.idx; + } + + function handlePop() { + action = exports.Action.Pop; + let nextIndex = getIndex(); + let delta = nextIndex == null ? null : nextIndex - index; + index = nextIndex; + + if (listener) { + listener({ + action, + location: history.location, + delta + }); + } + } + + function push(to, state) { + action = exports.Action.Push; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex() + 1; + let historyState = getHistoryState(location, index); + let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/ + + try { + globalHistory.pushState(historyState, "", url); + } catch (error) { + // They are going to lose state here, but there is no real + // way to warn them about it since the page will refresh... + window.location.assign(url); + } + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 1 + }); + } + } + + function replace(to, state) { + action = exports.Action.Replace; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex(); + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + globalHistory.replaceState(historyState, "", url); + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 0 + }); + } + } + + function createURL(to) { + // window.location.origin is "null" (the literal string value) in Firefox + // under certain conditions, notably when serving from a local HTML file + // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297 + let base = window.location.origin !== "null" ? window.location.origin : window.location.href; + let href = typeof to === "string" ? to : createPath(to); + invariant(base, "No window.location.(origin|href) available to create URL for href: " + href); + return new URL(href, base); + } + + let history = { + get action() { + return action; + }, + + get location() { + return getLocation(window, globalHistory); + }, + + listen(fn) { + if (listener) { + throw new Error("A history only accepts one active listener"); + } + + window.addEventListener(PopStateEventType, handlePop); + listener = fn; + return () => { + window.removeEventListener(PopStateEventType, handlePop); + listener = null; + }; + }, + + createHref(to) { + return createHref(window, to); + }, + + createURL, + + encodeLocation(to) { + // Encode a Location the same way window.location would + let url = createURL(to); + return { + pathname: url.pathname, + search: url.search, + hash: url.hash + }; + }, + + push, + replace, + + go(n) { + return globalHistory.go(n); + } + + }; + return history; +} //#endregion + +/** + * Map of routeId -> data returned from a loader/action/error + */ + +let ResultType; +/** + * Successful result from a loader or action + */ + +(function (ResultType) { + ResultType["data"] = "data"; + ResultType["deferred"] = "deferred"; + ResultType["redirect"] = "redirect"; + ResultType["error"] = "error"; +})(ResultType || (ResultType = {})); + +const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]); +/** + * lazy() function to load a route definition, which can add non-matching + * related properties to a route + */ + +function isIndexRoute(route) { + return route.index === true; +} // Walk the route tree generating unique IDs where necessary so we are working +// solely with AgnosticDataRouteObject's within the Router + + +function convertRoutesToDataRoutes(routes, detectErrorBoundary, parentPath, manifest) { + if (parentPath === void 0) { + parentPath = []; + } + + if (manifest === void 0) { + manifest = {}; + } + + return routes.map((route, index) => { + let treePath = [...parentPath, index]; + let id = typeof route.id === "string" ? route.id : treePath.join("-"); + invariant(route.index !== true || !route.children, "Cannot specify children on an index route"); + invariant(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages"); + + if (isIndexRoute(route)) { + let indexRoute = _extends({}, route, { + hasErrorBoundary: detectErrorBoundary(route), + id + }); + + manifest[id] = indexRoute; + return indexRoute; + } else { + let pathOrLayoutRoute = _extends({}, route, { + id, + hasErrorBoundary: detectErrorBoundary(route), + children: undefined + }); + + manifest[id] = pathOrLayoutRoute; + + if (route.children) { + pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, detectErrorBoundary, treePath, manifest); + } + + return pathOrLayoutRoute; + } + }); +} +/** + * Matches the given routes to a location and returns the match data. + * + * @see https://reactrouter.com/utils/match-routes + */ + +function matchRoutes(routes, locationArg, basename) { + if (basename === void 0) { + basename = "/"; + } + + let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + let pathname = stripBasename(location.pathname || "/", basename); + + if (pathname == null) { + return null; + } + + let branches = flattenRoutes(routes); + rankRouteBranches(branches); + let matches = null; + + for (let i = 0; matches == null && i < branches.length; ++i) { + matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location + // or from router.navigate, but we want to match against the unencoded + // paths in the route definitions. Memory router locations won't be + // encoded here but there also shouldn't be anything to decode so this + // should be a safe operation. This avoids needing matchRoutes to be + // history-aware. + safelyDecodeURI(pathname)); + } + + return matches; +} + +function flattenRoutes(routes, branches, parentsMeta, parentPath) { + if (branches === void 0) { + branches = []; + } + + if (parentsMeta === void 0) { + parentsMeta = []; + } + + if (parentPath === void 0) { + parentPath = ""; + } + + let flattenRoute = (route, index, relativePath) => { + let meta = { + relativePath: relativePath === undefined ? route.path || "" : relativePath, + caseSensitive: route.caseSensitive === true, + childrenIndex: index, + route + }; + + if (meta.relativePath.startsWith("/")) { + invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes."); + meta.relativePath = meta.relativePath.slice(parentPath.length); + } + + let path = joinPaths([parentPath, meta.relativePath]); + let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the + // route tree depth-first and child routes appear before their parents in + // the "flattened" version. + + if (route.children && route.children.length > 0) { + invariant( // Our types know better, but runtime JS may not! + // @ts-expect-error + route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")); + flattenRoutes(route.children, branches, routesMeta, path); + } // Routes without a path shouldn't ever match by themselves unless they are + // index routes, so don't add them to the list of possible branches. + + + if (route.path == null && !route.index) { + return; + } + + branches.push({ + path, + score: computeScore(path, route.index), + routesMeta + }); + }; + + routes.forEach((route, index) => { + var _route$path; + + // coarse-grain check for optional params + if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) { + flattenRoute(route, index); + } else { + for (let exploded of explodeOptionalSegments(route.path)) { + flattenRoute(route, index, exploded); + } + } + }); + return branches; +} +/** + * Computes all combinations of optional path segments for a given path, + * excluding combinations that are ambiguous and of lower priority. + * + * For example, `/one/:two?/three/:four?/:five?` explodes to: + * - `/one/three` + * - `/one/:two/three` + * - `/one/three/:four` + * - `/one/three/:five` + * - `/one/:two/three/:four` + * - `/one/:two/three/:five` + * - `/one/three/:four/:five` + * - `/one/:two/three/:four/:five` + */ + + +function explodeOptionalSegments(path) { + let segments = path.split("/"); + if (segments.length === 0) return []; + let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?` + + let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo` + + let required = first.replace(/\?$/, ""); + + if (rest.length === 0) { + // Intepret empty string as omitting an optional segment + // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three` + return isOptional ? [required, ""] : [required]; + } + + let restExploded = explodeOptionalSegments(rest.join("/")); + let result = []; // All child paths with the prefix. Do this for all children before the + // optional version for all children so we get consistent ordering where the + // parent optional aspect is preferred as required. Otherwise, we can get + // child sections interspersed where deeper optional segments are higher than + // parent optional segments, where for example, /:two would explodes _earlier_ + // then /:one. By always including the parent as required _for all children_ + // first, we avoid this issue + + result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without + + if (isOptional) { + result.push(...restExploded); + } // for absolute paths, ensure `/` instead of empty segment + + + return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded); +} + +function rankRouteBranches(branches) { + branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first + : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex))); +} + +const paramRe = /^:\w+$/; +const dynamicSegmentValue = 3; +const indexRouteValue = 2; +const emptySegmentValue = 1; +const staticSegmentValue = 10; +const splatPenalty = -2; + +const isSplat = s => s === "*"; + +function computeScore(path, index) { + let segments = path.split("/"); + let initialScore = segments.length; + + if (segments.some(isSplat)) { + initialScore += splatPenalty; + } + + if (index) { + initialScore += indexRouteValue; + } + + return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore); +} + +function compareIndexes(a, b) { + let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]); + return siblings ? // If two routes are siblings, we should try to match the earlier sibling + // first. This allows people to have fine-grained control over the matching + // behavior by simply putting routes with identical paths in the order they + // want them tried. + a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index, + // so they sort equally. + 0; +} + +function matchRouteBranch(branch, pathname) { + let { + routesMeta + } = branch; + let matchedParams = {}; + let matchedPathname = "/"; + let matches = []; + + for (let i = 0; i < routesMeta.length; ++i) { + let meta = routesMeta[i]; + let end = i === routesMeta.length - 1; + let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/"; + let match = matchPath({ + path: meta.relativePath, + caseSensitive: meta.caseSensitive, + end + }, remainingPathname); + if (!match) return null; + Object.assign(matchedParams, match.params); + let route = meta.route; + matches.push({ + // TODO: Can this as be avoided? + params: matchedParams, + pathname: joinPaths([matchedPathname, match.pathname]), + pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])), + route + }); + + if (match.pathnameBase !== "/") { + matchedPathname = joinPaths([matchedPathname, match.pathnameBase]); + } + } + + return matches; +} +/** + * Returns a path with params interpolated. + * + * @see https://reactrouter.com/utils/generate-path + */ + + +function generatePath(originalPath, params) { + if (params === void 0) { + params = {}; + } + + let path = originalPath; + + if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) { + warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + path = path.replace(/\*$/, "/*"); + } // ensure `/` is added at the beginning if the path is absolute + + + const prefix = path.startsWith("/") ? "/" : ""; + const segments = path.split(/\/+/).map((segment, index, array) => { + const isLastSegment = index === array.length - 1; // only apply the splat if it's the last segment + + if (isLastSegment && segment === "*") { + const star = "*"; + const starParam = params[star]; // Apply the splat + + return starParam; + } + + const keyMatch = segment.match(/^:(\w+)(\??)$/); + + if (keyMatch) { + const [, key, optional] = keyMatch; + let param = params[key]; + + if (optional === "?") { + return param == null ? "" : param; + } + + if (param == null) { + invariant(false, "Missing \":" + key + "\" param"); + } + + return param; + } // Remove any optional markers from optional static segments + + + return segment.replace(/\?$/g, ""); + }) // Remove empty segments + .filter(segment => !!segment); + return prefix + segments.join("/"); +} +/** + * A PathPattern is used to match on some portion of a URL pathname. + */ + +/** + * Performs pattern matching on a URL pathname and returns information about + * the match. + * + * @see https://reactrouter.com/utils/match-path + */ +function matchPath(pattern, pathname) { + if (typeof pattern === "string") { + pattern = { + path: pattern, + caseSensitive: false, + end: true + }; + } + + let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end); + let match = pathname.match(matcher); + if (!match) return null; + let matchedPathname = match[0]; + let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1"); + let captureGroups = match.slice(1); + let params = paramNames.reduce((memo, paramName, index) => { + // We need to compute the pathnameBase here using the raw splat value + // instead of using params["*"] later because it will be decoded then + if (paramName === "*") { + let splatValue = captureGroups[index] || ""; + pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1"); + } + + memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName); + return memo; + }, {}); + return { + params, + pathname: matchedPathname, + pathnameBase, + pattern + }; +} + +function compilePath(path, caseSensitive, end) { + if (caseSensitive === void 0) { + caseSensitive = false; + } + + if (end === void 0) { + end = true; + } + + warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + let paramNames = []; + let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below + .replace(/^\/*/, "/") // Make sure it has a leading / + .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars + .replace(/\/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName); + return "/([^\\/]+)"; + }); + + if (path.endsWith("*")) { + paramNames.push("*"); + regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest + : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"] + } else if (end) { + // When matching to the end, ignore trailing slashes + regexpSource += "\\/*$"; + } else if (path !== "" && path !== "/") { + // If our path is non-empty and contains anything beyond an initial slash, + // then we have _some_ form of path in our regex so we should expect to + // match only if we find the end of this path segment. Look for an optional + // non-captured trailing slash (to match a portion of the URL) or the end + // of the path (if we've matched to the end). We used to do this with a + // word boundary but that gives false positives on routes like + // /user-preferences since `-` counts as a word boundary. + regexpSource += "(?:(?=\\/|$))"; + } else ; + + let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i"); + return [matcher, paramNames]; +} + +function safelyDecodeURI(value) { + try { + return decodeURI(value); + } catch (error) { + warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ").")); + return value; + } +} + +function safelyDecodeURIComponent(value, paramName) { + try { + return decodeURIComponent(value); + } catch (error) { + warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ").")); + return value; + } +} +/** + * @private + */ + + +function stripBasename(pathname, basename) { + if (basename === "/") return pathname; + + if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) { + return null; + } // We want to leave trailing slash behavior in the user's control, so if they + // specify a basename with a trailing slash, we should support it + + + let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length; + let nextChar = pathname.charAt(startIndex); + + if (nextChar && nextChar !== "/") { + // pathname does not start with basename/ + return null; + } + + return pathname.slice(startIndex) || "/"; +} +/** + * Returns a resolved path object relative to the given pathname. + * + * @see https://reactrouter.com/utils/resolve-path + */ + +function resolvePath(to, fromPathname) { + if (fromPathname === void 0) { + fromPathname = "/"; + } + + let { + pathname: toPathname, + search = "", + hash = "" + } = typeof to === "string" ? parsePath(to) : to; + let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname; + return { + pathname, + search: normalizeSearch(search), + hash: normalizeHash(hash) + }; +} + +function resolvePathname(relativePath, fromPathname) { + let segments = fromPathname.replace(/\/+$/, "").split("/"); + let relativeSegments = relativePath.split("/"); + relativeSegments.forEach(segment => { + if (segment === "..") { + // Keep the root "" segment so the pathname starts at / + if (segments.length > 1) segments.pop(); + } else if (segment !== ".") { + segments.push(segment); + } + }); + return segments.length > 1 ? segments.join("/") : "/"; +} + +function getInvalidPathError(char, field, dest, path) { + return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in and the router will parse it for you."; +} +/** + * @private + * + * When processing relative navigation we want to ignore ancestor routes that + * do not contribute to the path, such that index/pathless layout routes don't + * interfere. + * + * For example, when moving a route element into an index route and/or a + * pathless layout route, relative link behavior contained within should stay + * the same. Both of the following examples should link back to the root: + * + * + * + * + * + * + * + * }> // <-- Does not contribute + * // <-- Does not contribute + * + * + */ + + +function getPathContributingMatches(matches) { + return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0); +} +/** + * @private + */ + +function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) { + if (isPathRelative === void 0) { + isPathRelative = false; + } + + let to; + + if (typeof toArg === "string") { + to = parsePath(toArg); + } else { + to = _extends({}, toArg); + invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to)); + invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to)); + invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to)); + } + + let isEmptyPath = toArg === "" || to.pathname === ""; + let toPathname = isEmptyPath ? "/" : to.pathname; + let from; // Routing is relative to the current pathname if explicitly requested. + // + // If a pathname is explicitly provided in `to`, it should be relative to the + // route context. This is explained in `Note on `` values` in our + // migration guide from v5 as a means of disambiguation between `to` values + // that begin with `/` and those that do not. However, this is problematic for + // `to` values that do not provide a pathname. `to` can simply be a search or + // hash string, in which case we should assume that the navigation is relative + // to the current location's pathname and *not* the route pathname. + + if (isPathRelative || toPathname == null) { + from = locationPathname; + } else { + let routePathnameIndex = routePathnames.length - 1; + + if (toPathname.startsWith("..")) { + let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one + // URL segment". This is a key difference from how works and a + // major reason we call this a "to" value instead of a "href". + + while (toSegments[0] === "..") { + toSegments.shift(); + routePathnameIndex -= 1; + } + + to.pathname = toSegments.join("/"); + } // If there are more ".." segments than parent routes, resolve relative to + // the root / URL. + + + from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/"; + } + + let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one + + let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash + + let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/"); + + if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) { + path.pathname += "/"; + } + + return path; +} +/** + * @private + */ + +function getToPathname(to) { + // Empty strings should be treated the same as / paths + return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname; +} +/** + * @private + */ + +const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/"); +/** + * @private + */ + +const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/"); +/** + * @private + */ + +const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search; +/** + * @private + */ + +const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; + +/** + * This is a shortcut for creating `application/json` responses. Converts `data` + * to JSON and sets the `Content-Type` header. + */ +const json = function json(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + let headers = new Headers(responseInit.headers); + + if (!headers.has("Content-Type")) { + headers.set("Content-Type", "application/json; charset=utf-8"); + } + + return new Response(JSON.stringify(data), _extends({}, responseInit, { + headers + })); +}; +class AbortedDeferredError extends Error {} +class DeferredData { + constructor(data, responseInit) { + this.pendingKeysSet = new Set(); + this.subscribers = new Set(); + this.deferredKeys = []; + invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early + // cancellation + + let reject; + this.abortPromise = new Promise((_, r) => reject = r); + this.controller = new AbortController(); + + let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted")); + + this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort); + + this.controller.signal.addEventListener("abort", onAbort); + this.data = Object.entries(data).reduce((acc, _ref) => { + let [key, value] = _ref; + return Object.assign(acc, { + [key]: this.trackPromise(key, value) + }); + }, {}); + + if (this.done) { + // All incoming values were resolved + this.unlistenAbortSignal(); + } + + this.init = responseInit; + } + + trackPromise(key, value) { + if (!(value instanceof Promise)) { + return value; + } + + this.deferredKeys.push(key); + this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with + // _data/_error props upon resolve/reject + + let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on + // errors or aborted deferred values + + promise.catch(() => {}); + Object.defineProperty(promise, "_tracked", { + get: () => true + }); + return promise; + } + + onSettle(promise, key, error, data) { + if (this.controller.signal.aborted && error instanceof AbortedDeferredError) { + this.unlistenAbortSignal(); + Object.defineProperty(promise, "_error", { + get: () => error + }); + return Promise.reject(error); + } + + this.pendingKeysSet.delete(key); + + if (this.done) { + // Nothing left to abort! + this.unlistenAbortSignal(); + } + + if (error) { + Object.defineProperty(promise, "_error", { + get: () => error + }); + this.emit(false, key); + return Promise.reject(error); + } + + Object.defineProperty(promise, "_data", { + get: () => data + }); + this.emit(false, key); + return data; + } + + emit(aborted, settledKey) { + this.subscribers.forEach(subscriber => subscriber(aborted, settledKey)); + } + + subscribe(fn) { + this.subscribers.add(fn); + return () => this.subscribers.delete(fn); + } + + cancel() { + this.controller.abort(); + this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k)); + this.emit(true); + } + + async resolveData(signal) { + let aborted = false; + + if (!this.done) { + let onAbort = () => this.cancel(); + + signal.addEventListener("abort", onAbort); + aborted = await new Promise(resolve => { + this.subscribe(aborted => { + signal.removeEventListener("abort", onAbort); + + if (aborted || this.done) { + resolve(aborted); + } + }); + }); + } + + return aborted; + } + + get done() { + return this.pendingKeysSet.size === 0; + } + + get unwrappedData() { + invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds"); + return Object.entries(this.data).reduce((acc, _ref2) => { + let [key, value] = _ref2; + return Object.assign(acc, { + [key]: unwrapTrackedPromise(value) + }); + }, {}); + } + + get pendingKeys() { + return Array.from(this.pendingKeysSet); + } + +} + +function isTrackedPromise(value) { + return value instanceof Promise && value._tracked === true; +} + +function unwrapTrackedPromise(value) { + if (!isTrackedPromise(value)) { + return value; + } + + if (value._error) { + throw value._error; + } + + return value._data; +} + +const defer = function defer(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + return new DeferredData(data, responseInit); +}; + +/** + * A redirect response. Sets the status code and the `Location` header. + * Defaults to "302 Found". + */ +const redirect = function redirect(url, init) { + if (init === void 0) { + init = 302; + } + + let responseInit = init; + + if (typeof responseInit === "number") { + responseInit = { + status: responseInit + }; + } else if (typeof responseInit.status === "undefined") { + responseInit.status = 302; + } + + let headers = new Headers(responseInit.headers); + headers.set("Location", url); + return new Response(null, _extends({}, responseInit, { + headers + })); +}; +/** + * @private + * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies + */ + +class ErrorResponse { + constructor(status, statusText, data, internal) { + if (internal === void 0) { + internal = false; + } + + this.status = status; + this.statusText = statusText || ""; + this.internal = internal; + + if (data instanceof Error) { + this.data = data.toString(); + this.error = data; + } else { + this.data = data; + } + } + +} +/** + * Check if the given error is an ErrorResponse generated from a 4xx/5xx + * Response thrown from an action/loader + */ + +function isRouteErrorResponse(error) { + return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error; +} + +//#region Types and Constants +//////////////////////////////////////////////////////////////////////////////// + +/** + * A Router instance manages all navigation and data loading/mutations + */ + +const validMutationMethodsArr = ["post", "put", "patch", "delete"]; +const validMutationMethods = new Set(validMutationMethodsArr); +const validRequestMethodsArr = ["get", ...validMutationMethodsArr]; +const validRequestMethods = new Set(validRequestMethodsArr); +const redirectStatusCodes = new Set([301, 302, 303, 307, 308]); +const redirectPreserveMethodStatusCodes = new Set([307, 308]); +const IDLE_NAVIGATION = { + state: "idle", + location: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined +}; +const IDLE_FETCHER = { + state: "idle", + data: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined +}; +const IDLE_BLOCKER = { + state: "unblocked", + proceed: undefined, + reset: undefined, + location: undefined +}; +const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i; +const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined"; +const isServer = !isBrowser; + +const defaultDetectErrorBoundary = route => Boolean(route.hasErrorBoundary); //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region createRouter +//////////////////////////////////////////////////////////////////////////////// + +/** + * Create a router and listen to history POP navigations + */ + + +function createRouter(init) { + invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter"); + let detectErrorBoundary = init.detectErrorBoundary || defaultDetectErrorBoundary; // Routes keyed by ID + + let manifest = {}; // Routes in tree format for matching + + let dataRoutes = convertRoutesToDataRoutes(init.routes, detectErrorBoundary, undefined, manifest); + let inFlightDataRoutes; // Config driven behavior flags + + let future = _extends({ + v7_normalizeFormMethod: false + }, init.future); // Cleanup function for history + + + let unlistenHistory = null; // Externally-provided functions to call on all state changes + + let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing + + let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys + + let getScrollRestorationKey = null; // Externally-provided function to get current scroll position + + let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration. Because + // we don't get the saved positions from until _after_ + // the initial render, we need to manually trigger a separate updateState to + // send along the restoreScrollPosition + // Set to true if we have `hydrationData` since we assume we were SSR'd and that + // SSR did the initial scroll restoration. + + let initialScrollRestored = init.hydrationData != null; + let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename); + let initialErrors = null; + + if (initialMatches == null) { + // If we do not match a user-provided-route, fall back to the root + // to allow the error boundary to take over + let error = getInternalRouterError(404, { + pathname: init.history.location.pathname + }); + let { + matches, + route + } = getShortCircuitMatches(dataRoutes); + initialMatches = matches; + initialErrors = { + [route.id]: error + }; + } + + let initialized = // All initialMatches need to be loaded before we're ready. If we have lazy + // functions around still then we'll need to run them in initialize() + !initialMatches.some(m => m.route.lazy) && ( // And we have to either have no loaders or have been provided hydrationData + !initialMatches.some(m => m.route.loader) || init.hydrationData != null); + let router; + let state = { + historyAction: init.history.action, + location: init.history.location, + matches: initialMatches, + initialized, + navigation: IDLE_NAVIGATION, + // Don't restore on initial updateState() if we were SSR'd + restoreScrollPosition: init.hydrationData != null ? false : null, + preventScrollReset: false, + revalidation: "idle", + loaderData: init.hydrationData && init.hydrationData.loaderData || {}, + actionData: init.hydrationData && init.hydrationData.actionData || null, + errors: init.hydrationData && init.hydrationData.errors || initialErrors, + fetchers: new Map(), + blockers: new Map() + }; // -- Stateful internal variables to manage navigations -- + // Current navigation in progress (to be committed in completeNavigation) + + let pendingAction = exports.Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot + // be restored? + + let pendingPreventScrollReset = false; // AbortController for the active navigation + + let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a + // revalidation is entirely uninterrupted + + let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders: + // - submissions (completed or interrupted) + // - useRevalidate() + // - X-Remix-Revalidate (from redirect) + + let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due + // to a cancelled deferred on action submission + + let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an + // action navigation and require revalidation + + let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers + + let fetchControllers = new Map(); // Track loads based on the order in which they started + + let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against + // the globally incrementing load when a fetcher load lands after a completed + // navigation + + let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions + + let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions + + let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers + + let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches. When a + // route loader returns defer() we stick one in here. Then, when a nested + // promise resolves we update loaderData. If a new navigation starts we + // cancel active deferreds for eliminated routes. + + let activeDeferreds = new Map(); // Store blocker functions in a separate Map outside of router state since + // we don't need to update UI state if they change + + let blockerFunctions = new Map(); // Flag to ignore the next history update, so we can revert the URL change on + // a POP navigation that was blocked by the user without touching router state + + let ignoreNextHistoryUpdate = false; // Initialize the router, all side effects should be kicked off from here. + // Implemented as a Fluent API for ease of: + // let router = createRouter(init).initialize(); + + function initialize() { + // If history informs us of a POP navigation, start the navigation but do not update + // state. We'll update our own state once the navigation completes + unlistenHistory = init.history.listen(_ref => { + let { + action: historyAction, + location, + delta + } = _ref; + + // Ignore this event if it was just us resetting the URL from a + // blocked POP navigation + if (ignoreNextHistoryUpdate) { + ignoreNextHistoryUpdate = false; + return; + } + + warning(blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + "via `window.history.pushState`/`window.location.hash` instead of using " + "router navigation APIs. This can also happen if you are using " + "createHashRouter and the user manually changes the URL."); + let blockerKey = shouldBlockNavigation({ + currentLocation: state.location, + nextLocation: location, + historyAction + }); + + if (blockerKey && delta != null) { + // Restore the URL to match the current UI, but don't update router state + ignoreNextHistoryUpdate = true; + init.history.go(delta * -1); // Put the blocker into a blocked state + + updateBlocker(blockerKey, { + state: "blocked", + location, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location + }); // Re-do the same POP navigation we just blocked + + init.history.go(delta); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(router.state.blockers) + }); + } + + }); + return; + } + + return startNavigation(historyAction, location); + }); // Kick off initial data load if needed. Use Pop to avoid modifying history + // Note we don't do any handling of lazy here. For SPA's it'll get handled + // in the normal navigation flow. For SSR it's expected that lazy modules are + // resolved prior to router creation since we can't go into a fallbackElement + // UI for SSR'd apps + + if (!state.initialized) { + startNavigation(exports.Action.Pop, state.location); + } + + return router; + } // Clean up a router and it's side effects + + + function dispose() { + if (unlistenHistory) { + unlistenHistory(); + } + + subscribers.clear(); + pendingNavigationController && pendingNavigationController.abort(); + state.fetchers.forEach((_, key) => deleteFetcher(key)); + state.blockers.forEach((_, key) => deleteBlocker(key)); + } // Subscribe to state updates for the router + + + function subscribe(fn) { + subscribers.add(fn); + return () => subscribers.delete(fn); + } // Update our state and notify the calling context of the change + + + function updateState(newState) { + state = _extends({}, state, newState); + subscribers.forEach(subscriber => subscriber(state)); + } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION + // and setting state.[historyAction/location/matches] to the new route. + // - Location is a required param + // - Navigation will always be set to IDLE_NAVIGATION + // - Can pass any other state in newState + + + function completeNavigation(location, newState) { + var _location$state, _location$state2; + + // Deduce if we're in a loading/actionReload state: + // - We have committed actionData in the store + // - The current navigation was a mutation submission + // - We're past the submitting state and into the loading state + // - The location being loaded is not the result of a redirect + let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true; + let actionData; + + if (newState.actionData) { + if (Object.keys(newState.actionData).length > 0) { + actionData = newState.actionData; + } else { + // Empty actionData -> clear prior actionData due to an action error + actionData = null; + } + } else if (isActionReload) { + // Keep the current data if we're wrapping up the action reload + actionData = state.actionData; + } else { + // Clear actionData on any other completed navigations + actionData = null; + } // Always preserve any existing loaderData from re-used routes + + + let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // On a successful navigation we can assume we got through all blockers + // so we can start fresh + + for (let [key] of blockerFunctions) { + deleteBlocker(key); + } // Always respect the user flag. Otherwise don't reset on mutation + // submission navigations unless they redirect + + + let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true; + + if (inFlightDataRoutes) { + dataRoutes = inFlightDataRoutes; + inFlightDataRoutes = undefined; + } + + updateState(_extends({}, newState, { + // matches, errors, fetchers go through as-is + actionData, + loaderData, + historyAction: pendingAction, + location, + initialized: true, + navigation: IDLE_NAVIGATION, + revalidation: "idle", + restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches), + preventScrollReset, + blockers: new Map(state.blockers) + })); + + if (isUninterruptedRevalidation) ; else if (pendingAction === exports.Action.Pop) ; else if (pendingAction === exports.Action.Push) { + init.history.push(location, location.state); + } else if (pendingAction === exports.Action.Replace) { + init.history.replace(location, location.state); + } // Reset stateful navigation vars + + + pendingAction = exports.Action.Pop; + pendingPreventScrollReset = false; + isUninterruptedRevalidation = false; + isRevalidationRequired = false; + cancelledDeferredRoutes = []; + cancelledFetcherLoads = []; + } // Trigger a navigation event, which can either be a numerical POP or a PUSH + // replace with an optional submission + + + async function navigate(to, opts) { + if (typeof to === "number") { + init.history.go(to); + return; + } + + let { + path, + submission, + error + } = normalizeNavigateOptions(to, future, opts); + let currentLocation = state.location; + let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded + // URL from window.location, so we need to encode it here so the behavior + // remains the same as POP and non-data-router usages. new URL() does all + // the same encoding we'd get from a history.pushState/window.location read + // without having to touch history + + nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation)); + let userReplace = opts && opts.replace != null ? opts.replace : undefined; + let historyAction = exports.Action.Push; + + if (userReplace === true) { + historyAction = exports.Action.Replace; + } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) { + // By default on submissions to the current location we REPLACE so that + // users don't have to double-click the back button to get to the prior + // location. If the user redirects to a different location from the + // action/loader this will be ignored and the redirect will be a PUSH + historyAction = exports.Action.Replace; + } + + let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined; + let blockerKey = shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction + }); + + if (blockerKey) { + // Put the blocker into a blocked state + updateBlocker(blockerKey, { + state: "blocked", + location: nextLocation, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location: nextLocation + }); // Send the same navigation through + + navigate(to, opts); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(state.blockers) + }); + } + + }); + return; + } + + return await startNavigation(historyAction, nextLocation, { + submission, + // Send through the formData serialization error if we have one so we can + // render at the right error boundary after we match routes + pendingError: error, + preventScrollReset, + replace: opts && opts.replace + }); + } // Revalidate all current loaders. If a navigation is in progress or if this + // is interrupted by a navigation, allow this to "succeed" by calling all + // loaders during the next loader round + + + function revalidate() { + interruptActiveLoads(); + updateState({ + revalidation: "loading" + }); // If we're currently submitting an action, we don't need to start a new + // navigation, we'll just let the follow up loader execution call all loaders + + if (state.navigation.state === "submitting") { + return; + } // If we're currently in an idle state, start a new navigation for the current + // action/location and mark it as uninterrupted, which will skip the history + // update in completeNavigation + + + if (state.navigation.state === "idle") { + startNavigation(state.historyAction, state.location, { + startUninterruptedRevalidation: true + }); + return; + } // Otherwise, if we're currently in a loading state, just start a new + // navigation to the navigation.location but do not trigger an uninterrupted + // revalidation so that history correctly updates once the navigation completes + + + startNavigation(pendingAction || state.historyAction, state.navigation.location, { + overrideNavigation: state.navigation + }); + } // Start a navigation to the given action/location. Can optionally provide a + // overrideNavigation which will override the normalLoad in the case of a redirect + // navigation + + + async function startNavigation(historyAction, location, opts) { + // Abort any in-progress navigations and start a new one. Unset any ongoing + // uninterrupted revalidations unless told otherwise, since we want this + // new navigation to update history normally + pendingNavigationController && pendingNavigationController.abort(); + pendingNavigationController = null; + pendingAction = historyAction; + isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation, + // and track whether we should reset scroll on completion + + saveScrollPosition(state.location, state.matches); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + let routesToUse = inFlightDataRoutes || dataRoutes; + let loadingNavigation = opts && opts.overrideNavigation; + let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing + + if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes + + cancelActiveDeferreds(); + completeNavigation(location, { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error + } + }); + return; + } // Short circuit if it's only a hash change and not a mutation submission + // For example, on /page#hash and submit a which will + // default to a navigation to /page + + + if (isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) { + completeNavigation(location, { + matches + }); + return; + } // Create a controller/Request for this navigation + + + pendingNavigationController = new AbortController(); + let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission); + let pendingActionData; + let pendingError; + + if (opts && opts.pendingError) { + // If we have a pendingError, it means the user attempted a GET submission + // with binary FormData so assign here and skip to handleLoaders. That + // way we handle calling loaders above the boundary etc. It's not really + // different from an actionError in that sense. + pendingError = { + [findNearestBoundary(matches).route.id]: opts.pendingError + }; + } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) { + // Call action if we received an action submission + let actionOutput = await handleAction(request, location, opts.submission, matches, { + replace: opts.replace + }); + + if (actionOutput.shortCircuited) { + return; + } + + pendingActionData = actionOutput.pendingActionData; + pendingError = actionOutput.pendingActionError; + + let navigation = _extends({ + state: "loading", + location + }, opts.submission); + + loadingNavigation = navigation; // Create a GET request for the loaders + + request = new Request(request.url, { + signal: request.signal + }); + } // Call loaders + + + let { + shortCircuited, + loaderData, + errors + } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError); + + if (shortCircuited) { + return; + } // Clean up now that the action/loaders have completed. Don't clean up if + // we short circuited because pendingNavigationController will have already + // been assigned to a new controller for the next navigation + + + pendingNavigationController = null; + completeNavigation(location, _extends({ + matches + }, pendingActionData ? { + actionData: pendingActionData + } : {}, { + loaderData, + errors + })); + } // Call the action matched by the leaf route for this navigation and handle + // redirects/errors + + + async function handleAction(request, location, submission, matches, opts) { + interruptActiveLoads(); // Put us in a submitting state + + let navigation = _extends({ + state: "submitting", + location + }, submission); + + updateState({ + navigation + }); // Call our action and get the result + + let result; + let actionMatch = getTargetMatch(matches, location); + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + result = { + type: ResultType.error, + error: getInternalRouterError(405, { + method: request.method, + pathname: location.pathname, + routeId: actionMatch.route.id + }) + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, router.basename); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } + } + + if (isRedirectResult(result)) { + let replace; + + if (opts && opts.replace != null) { + replace = opts.replace; + } else { + // If the user didn't explicity indicate replace behavior, replace if + // we redirected to the exact same location we're currently at to avoid + // double back-buttons + replace = result.location === state.location.pathname + state.location.search; + } + + await startRedirectNavigation(state, result, { + submission, + replace + }); + return { + shortCircuited: true + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the + // action threw an error that'll be rendered in an errorElement, we fall + // back to PUSH so that the user can use the back button to get back to + // the pre-submission form location to try again + + if ((opts && opts.replace) !== true) { + pendingAction = exports.Action.Push; + } + + return { + // Send back an empty object we can use to clear out any prior actionData + pendingActionData: {}, + pendingActionError: { + [boundaryMatch.route.id]: result.error + } + }; + } + + if (isDeferredResult(result)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } + + return { + pendingActionData: { + [actionMatch.route.id]: result.data + } + }; + } // Call all applicable loaders for the given matches, handling redirects, + // errors, etc. + + + async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) { + // Figure out the right navigation we want to use for data loading + let loadingNavigation = overrideNavigation; + + if (!loadingNavigation) { + let navigation = _extends({ + state: "loading", + location, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission); + + loadingNavigation = navigation; + } // If this was a redirect from an action we don't have a "submission" but + // we have it on the loading navigation so use that if available + + + let activeSubmission = submission || fetcherSubmission ? submission || fetcherSubmission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? { + formMethod: loadingNavigation.formMethod, + formAction: loadingNavigation.formAction, + formData: loadingNavigation.formData, + formEncType: loadingNavigation.formEncType + } : undefined; + let routesToUse = inFlightDataRoutes || dataRoutes; + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're + // about to reload. Note that if this is an action reload we would have + // already cancelled all pending deferreds so this would be a no-op + + cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run + + if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) { + completeNavigation(location, _extends({ + matches, + loaderData: {}, + // Commit pending error if we're short circuiting + errors: pendingError || null + }, pendingActionData ? { + actionData: pendingActionData + } : {})); + return { + shortCircuited: true + }; + } // If this is an uninterrupted revalidation, we remain in our current idle + // state. If not, we need to switch to our loading state and load data, + // preserving any new action data or existing action data (in the case of + // a revalidation interrupting an actionReload) + + + if (!isUninterruptedRevalidation) { + revalidatingFetchers.forEach(rf => { + let fetcher = state.fetchers.get(rf.key); + let revalidatingFetcher = { + state: "loading", + data: fetcher && fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(rf.key, revalidatingFetcher); + }); + let actionData = pendingActionData || state.actionData; + updateState(_extends({ + navigation: loadingNavigation + }, actionData ? Object.keys(actionData).length === 0 ? { + actionData: null + } : { + actionData + } : {}, revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {})); + } + + pendingNavigationLoadId = ++incrementingLoadId; + revalidatingFetchers.forEach(rf => fetchControllers.set(rf.key, pendingNavigationController)); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } // Clean up _after_ loaders have completed. Don't clean up if we short + // circuited because fetchControllers would have been aborted and + // reassigned to new controllers for the next navigation + + + revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key)); // If any loaders returned a redirect Response, start a new REPLACE navigation + + let redirect = findRedirect(results); + + if (redirect) { + await startRedirectNavigation(state, redirect, { + replace + }); + return { + shortCircuited: true + }; + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle + + activeDeferreds.forEach((deferredData, routeId) => { + deferredData.subscribe(aborted => { + // Note: No need to updateState here since the TrackedPromise on + // loaderData is stable across resolve/reject + // Remove this instance if we were aborted or if promises have settled + if (aborted || deferredData.done) { + activeDeferreds.delete(routeId); + } + }); + }); + markFetchRedirectsDone(); + let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId); + return _extends({ + loaderData, + errors + }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {}); + } + + function getFetcher(key) { + return state.fetchers.get(key) || IDLE_FETCHER; + } // Trigger a fetcher load/submit for the given fetcher key + + + function fetch(key, routeId, href, opts) { + if (isServer) { + throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback."); + } + + if (fetchControllers.has(key)) abortFetcher(key); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = matchRoutes(routesToUse, href, init.basename); + + if (!matches) { + setFetcherError(key, routeId, getInternalRouterError(404, { + pathname: href + })); + return; + } + + let { + path, + submission + } = normalizeNavigateOptions(href, future, opts, true); + let match = getTargetMatch(matches, path); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + + if (submission && isMutationMethod(submission.formMethod)) { + handleFetcherAction(key, routeId, path, match, matches, submission); + return; + } // Store off the match so we can call it's shouldRevalidate on subsequent + // revalidations + + + fetchLoadMatches.set(key, { + routeId, + path + }); + handleFetcherLoader(key, routeId, path, match, matches, submission); + } // Call the action for the matched fetcher.submit(), and then handle redirects, + // errors, and revalidation + + + async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) { + interruptActiveLoads(); + fetchLoadMatches.delete(key); + + if (!match.route.action && !match.route.lazy) { + let error = getInternalRouterError(405, { + method: submission.formMethod, + pathname: path, + routeId: routeId + }); + setFetcherError(key, routeId, error); + return; + } // Put this fetcher into it's submitting state + + + let existingFetcher = state.fetchers.get(key); + + let fetcher = _extends({ + state: "submitting" + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, fetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the action for the fetcher + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission); + fetchControllers.set(key, abortController); + let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, detectErrorBoundary, router.basename); + + if (fetchRequest.signal.aborted) { + // We can delete this so long as we weren't aborted by ou our own fetcher + // re-submit which would have put _new_ controller is in fetchControllers + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + return; + } + + if (isRedirectResult(actionResult)) { + fetchControllers.delete(key); + fetchRedirectIds.add(key); + + let loadingFetcher = _extends({ + state: "loading" + }, submission, { + data: undefined, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + return startRedirectNavigation(state, actionResult, { + submission, + isFetchActionRedirect: true + }); + } // Process any non-redirect errors thrown + + + if (isErrorResult(actionResult)) { + setFetcherError(key, routeId, actionResult.error); + return; + } + + if (isDeferredResult(actionResult)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } // Start the data load for current matches, or the next location if we're + // in the middle of a navigation + + + let nextLocation = state.navigation.location || state.location; + let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches; + invariant(matches, "Didn't find any matches after fetcher action"); + let loadId = ++incrementingLoadId; + fetchReloadIds.set(key, loadId); + + let loadFetcher = _extends({ + state: "loading", + data: actionResult.data + }, submission, { + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadFetcher); + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, { + [match.route.id]: actionResult.data + }, undefined // No need to send through errors since we short circuit above + ); // Put all revalidating fetchers into the loading state, except for the + // current fetcher which we want to keep in it's current loading state which + // contains it's action submission info + action data + + revalidatingFetchers.filter(rf => rf.key !== key).forEach(rf => { + let staleKey = rf.key; + let existingFetcher = state.fetchers.get(staleKey); + let revalidatingFetcher = { + state: "loading", + data: existingFetcher && existingFetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(staleKey, revalidatingFetcher); + fetchControllers.set(staleKey, abortController); + }); + updateState({ + fetchers: new Map(state.fetchers) + }); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest); + + if (abortController.signal.aborted) { + return; + } + + fetchReloadIds.delete(key); + fetchControllers.delete(key); + revalidatingFetchers.forEach(r => fetchControllers.delete(r.key)); + let redirect = findRedirect(results); + + if (redirect) { + return startRedirectNavigation(state, redirect); + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds); + let doneFetcher = { + state: "idle", + data: actionResult.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is + // more recent than the navigation, we want the newer data so abort the + // navigation and complete it with the fetcher data + + if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) { + invariant(pendingAction, "Expected pending action"); + pendingNavigationController && pendingNavigationController.abort(); + completeNavigation(state.navigation.location, { + matches, + loaderData, + errors, + fetchers: new Map(state.fetchers) + }); + } else { + // otherwise just update with the fetcher data, preserving any existing + // loaderData for loaders that did not need to reload. We have to + // manually merge here since we aren't going through completeNavigation + updateState(_extends({ + errors, + loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors) + }, didAbortFetchLoads ? { + fetchers: new Map(state.fetchers) + } : {})); + isRevalidationRequired = false; + } + } // Call the matched loader for fetcher.load(), handling redirects, errors, etc. + + + async function handleFetcherLoader(key, routeId, path, match, matches, submission) { + let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state + + let loadingFetcher = _extends({ + state: "loading", + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the loader for this fetcher route match + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal); + fetchControllers.set(key, abortController); + let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, detectErrorBoundary, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it + // as a normal load. resolveDeferredData will return undefined if this + // fetcher gets aborted, so we just leave result untouched and short circuit + // below if that happens + + if (isDeferredResult(result)) { + result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result; + } // We can delete this so long as we weren't aborted by ou our own fetcher + // re-load which would have put _new_ controller is in fetchControllers + + + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + if (fetchRequest.signal.aborted) { + return; + } // If the loader threw a redirect Response, start a new REPLACE navigation + + + if (isRedirectResult(result)) { + await startRedirectNavigation(state, result); + return; + } // Process any non-redirect errors thrown + + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch - + // do we need to behave any differently with our non-redirect errors? + // What if it was a non-redirect Response? + + updateState({ + fetchers: new Map(state.fetchers), + errors: { + [boundaryMatch.route.id]: result.error + } + }); + return; + } + + invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state + + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + } + /** + * Utility function to handle redirects returned from an action or loader. + * Normally, a redirect "replaces" the navigation that triggered it. So, for + * example: + * + * - user is on /a + * - user clicks a link to /b + * - loader for /b redirects to /c + * + * In a non-JS app the browser would track the in-flight navigation to /b and + * then replace it with /c when it encountered the redirect response. In + * the end it would only ever update the URL bar with /c. + * + * In client-side routing using pushState/replaceState, we aim to emulate + * this behavior and we also do not update history until the end of the + * navigation (including processed redirects). This means that we never + * actually touch history until we've processed redirects, so we just use + * the history action from the original navigation (PUSH or REPLACE). + */ + + + async function startRedirectNavigation(state, redirect, _temp) { + var _window; + + let { + submission, + replace, + isFetchActionRedirect + } = _temp === void 0 ? {} : _temp; + + if (redirect.revalidate) { + isRevalidationRequired = true; + } + + let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2 + _extends({ + _isRedirect: true + }, isFetchActionRedirect ? { + _isFetchActionRedirect: true + } : {})); + invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an absolute external redirect that goes to a new origin + + if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser && typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") { + let url = init.history.createURL(redirect.location); + let isDifferentBasename = stripBasename(url.pathname, init.basename || "/") == null; + + if (window.location.origin !== url.origin || isDifferentBasename) { + if (replace) { + window.location.replace(redirect.location); + } else { + window.location.assign(redirect.location); + } + + return; + } + } // There's no need to abort on redirects, since we don't detect the + // redirect until the action/loaders have settled + + + pendingNavigationController = null; + let redirectHistoryAction = replace === true ? exports.Action.Replace : exports.Action.Push; // Use the incoming submission if provided, fallback on the active one in + // state.navigation + + let { + formMethod, + formAction, + formEncType, + formData + } = state.navigation; + + if (!submission && formMethod && formAction && formData && formEncType) { + submission = { + formMethod, + formAction, + formEncType, + formData + }; + } // If this was a 307/308 submission we want to preserve the HTTP method and + // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the + // redirected location + + + if (redirectPreserveMethodStatusCodes.has(redirect.status) && submission && isMutationMethod(submission.formMethod)) { + await startNavigation(redirectHistoryAction, redirectLocation, { + submission: _extends({}, submission, { + formAction: redirect.location + }), + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else if (isFetchActionRedirect) { + // For a fetch action redirect, we kick off a new loading navigation + // without the fetcher submission, but we send it along for shouldRevalidate + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, + fetcherSubmission: submission, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else { + // Otherwise, we kick off a new loading navigation, preserving the + // submission info for the duration of this navigation + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: submission ? submission.formMethod : undefined, + formAction: submission ? submission.formAction : undefined, + formEncType: submission ? submission.formEncType : undefined, + formData: submission ? submission.formData : undefined + }, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } + } + + async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) { + // Call all navigation loaders and revalidating fetcher loaders in parallel, + // then slice off the results into separate arrays so we can handle them + // accordingly + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, router.basename)), ...fetchersToLoad.map(f => { + if (f.matches && f.match) { + return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, manifest, detectErrorBoundary, router.basename); + } else { + let error = { + type: ResultType.error, + error: getInternalRouterError(404, { + pathname: f.path + }) + }; + return error; + } + })]); + let loaderResults = results.slice(0, matchesToLoad.length); + let fetcherResults = results.slice(matchesToLoad.length); + await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]); + return { + results, + loaderResults, + fetcherResults + }; + } + + function interruptActiveLoads() { + // Every interruption triggers a revalidation + isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for + // revalidation + + cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads + + fetchLoadMatches.forEach((_, key) => { + if (fetchControllers.has(key)) { + cancelledFetcherLoads.push(key); + abortFetcher(key); + } + }); + } + + function setFetcherError(key, routeId, error) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + deleteFetcher(key); + updateState({ + errors: { + [boundaryMatch.route.id]: error + }, + fetchers: new Map(state.fetchers) + }); + } + + function deleteFetcher(key) { + if (fetchControllers.has(key)) abortFetcher(key); + fetchLoadMatches.delete(key); + fetchReloadIds.delete(key); + fetchRedirectIds.delete(key); + state.fetchers.delete(key); + } + + function abortFetcher(key) { + let controller = fetchControllers.get(key); + invariant(controller, "Expected fetch controller: " + key); + controller.abort(); + fetchControllers.delete(key); + } + + function markFetchersDone(keys) { + for (let key of keys) { + let fetcher = getFetcher(key); + let doneFetcher = { + state: "idle", + data: fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + function markFetchRedirectsDone() { + let doneKeys = []; + + for (let key of fetchRedirectIds) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + fetchRedirectIds.delete(key); + doneKeys.push(key); + } + } + + markFetchersDone(doneKeys); + } + + function abortStaleFetchLoads(landedId) { + let yeetedKeys = []; + + for (let [key, id] of fetchReloadIds) { + if (id < landedId) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + abortFetcher(key); + fetchReloadIds.delete(key); + yeetedKeys.push(key); + } + } + } + + markFetchersDone(yeetedKeys); + return yeetedKeys.length > 0; + } + + function getBlocker(key, fn) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + + if (blockerFunctions.get(key) !== fn) { + blockerFunctions.set(key, fn); + } + + return blocker; + } + + function deleteBlocker(key) { + state.blockers.delete(key); + blockerFunctions.delete(key); + } // Utility function to update blockers, ensuring valid state transitions + + + function updateBlocker(key, newBlocker) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; // Poor mans state machine :) + // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM + + invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state); + state.blockers.set(key, newBlocker); + updateState({ + blockers: new Map(state.blockers) + }); + } + + function shouldBlockNavigation(_ref2) { + let { + currentLocation, + nextLocation, + historyAction + } = _ref2; + + if (blockerFunctions.size === 0) { + return; + } // We ony support a single active blocker at the moment since we don't have + // any compelling use cases for multi-blocker yet + + + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); + + if (blocker && blocker.state === "proceeding") { + // If the blocker is currently proceeding, we don't need to re-check + // it and can let this navigation continue + return; + } // At this point, we know we're unblocked/blocked so we need to check the + // user-provided blocker function + + + if (blockerFunction({ + currentLocation, + nextLocation, + historyAction + })) { + return blockerKey; + } + } + + function cancelActiveDeferreds(predicate) { + let cancelledRouteIds = []; + activeDeferreds.forEach((dfd, routeId) => { + if (!predicate || predicate(routeId)) { + // Cancel the deferred - but do not remove from activeDeferreds here - + // we rely on the subscribers to do that so our tests can assert proper + // cleanup via _internalActiveDeferreds + dfd.cancel(); + cancelledRouteIds.push(routeId); + activeDeferreds.delete(routeId); + } + }); + return cancelledRouteIds; + } // Opt in to capturing and reporting scroll positions during navigations, + // used by the component + + + function enableScrollRestoration(positions, getPosition, getKey) { + savedScrollPositions = positions; + getScrollPosition = getPosition; + + getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on + // the initial updateState() because we've not yet rendered + // and therefore have no savedScrollPositions available + + + if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) { + initialScrollRestored = true; + let y = getSavedScrollPosition(state.location, state.matches); + + if (y != null) { + updateState({ + restoreScrollPosition: y + }); + } + } + + return () => { + savedScrollPositions = null; + getScrollPosition = null; + getScrollRestorationKey = null; + }; + } + + function saveScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + savedScrollPositions[key] = getScrollPosition(); + } + } + + function getSavedScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + let y = savedScrollPositions[key]; + + if (typeof y === "number") { + return y; + } + } + + return null; + } + + function _internalSetRoutes(newRoutes) { + inFlightDataRoutes = newRoutes; + } + + router = { + get basename() { + return init.basename; + }, + + get state() { + return state; + }, + + get routes() { + return dataRoutes; + }, + + initialize, + subscribe, + enableScrollRestoration, + navigate, + fetch, + revalidate, + // Passthrough to history-aware createHref used by useHref so we get proper + // hash-aware URLs in DOM paths + createHref: to => init.history.createHref(to), + encodeLocation: to => init.history.encodeLocation(to), + getFetcher, + deleteFetcher, + dispose, + getBlocker, + deleteBlocker, + _internalFetchControllers: fetchControllers, + _internalActiveDeferreds: activeDeferreds, + // TODO: Remove setRoutes, it's temporary to avoid dealing with + // updating the tree while validating the update algorithm. + _internalSetRoutes + }; + return router; +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region createStaticHandler +//////////////////////////////////////////////////////////////////////////////// + +const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred"); +function createStaticHandler(routes, opts) { + invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler"); + let manifest = {}; + let detectErrorBoundary = (opts == null ? void 0 : opts.detectErrorBoundary) || defaultDetectErrorBoundary; + let dataRoutes = convertRoutesToDataRoutes(routes, detectErrorBoundary, undefined, manifest); + let basename = (opts ? opts.basename : null) || "/"; + /** + * The query() method is intended for document requests, in which we want to + * call an optional action and potentially multiple loaders for all nested + * routes. It returns a StaticHandlerContext object, which is very similar + * to the router state (location, loaderData, actionData, errors, etc.) and + * also adds SSR-specific information such as the statusCode and headers + * from action/loaders Responses. + * + * It _should_ never throw and should report all errors through the + * returned context.errors object, properly associating errors to their error + * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be + * used to emulate React error boundaries during SSr by performing a second + * pass only down to the boundaryId. + * + * The one exception where we do not return a StaticHandlerContext is when a + * redirect response is returned or thrown from any action/loader. We + * propagate that out and return the raw Response so the HTTP server can + * return it directly. + */ + + async function query(request, _temp2) { + let { + requestContext + } = _temp2 === void 0 ? {} : _temp2; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD") { + let error = getInternalRouterError(405, { + method + }); + let { + matches: methodNotAllowedMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: methodNotAllowedMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } else if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: notFoundMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + let result = await queryImpl(request, location, matches, requestContext); + + if (isResponse(result)) { + return result; + } // When returning StaticHandlerContext, we patch back in the location here + // since we need it for React Context. But this helps keep our submit and + // loadRouteData operating on a Request instead of a Location + + + return _extends({ + location, + basename + }, result); + } + /** + * The queryRoute() method is intended for targeted route requests, either + * for fetch ?_data requests or resource route requests. In this case, we + * are only ever calling a single action or loader, and we are returning the + * returned value directly. In most cases, this will be a Response returned + * from the action/loader, but it may be a primitive or other value as well - + * and in such cases the calling context should handle that accordingly. + * + * We do respect the throw/return differentiation, so if an action/loader + * throws, then this method will throw the value. This is important so we + * can do proper boundary identification in Remix where a thrown Response + * must go to the Catch Boundary but a returned Response is happy-path. + * + * One thing to note is that any Router-initiated Errors that make sense + * to associate with a status code will be thrown as an ErrorResponse + * instance which include the raw Error, such that the calling context can + * serialize the error as they see fit while including the proper response + * code. Examples here are 404 and 405 errors that occur prior to reaching + * any user-defined loaders. + */ + + + async function queryRoute(request, _temp3) { + let { + routeId, + requestContext + } = _temp3 === void 0 ? {} : _temp3; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") { + throw getInternalRouterError(405, { + method + }); + } else if (!matches) { + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location); + + if (routeId && !match) { + throw getInternalRouterError(403, { + pathname: location.pathname, + routeId + }); + } else if (!match) { + // This should never hit I don't think? + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let result = await queryImpl(request, location, matches, requestContext, match); + + if (isResponse(result)) { + return result; + } + + let error = result.errors ? Object.values(result.errors)[0] : undefined; + + if (error !== undefined) { + // If we got back result.errors, that means the loader/action threw + // _something_ that wasn't a Response, but it's not guaranteed/required + // to be an `instanceof Error` either, so we have to use throw here to + // preserve the "error" state outside of queryImpl. + throw error; + } // Pick off the right state value to return + + + if (result.actionData) { + return Object.values(result.actionData)[0]; + } + + if (result.loaderData) { + var _result$activeDeferre; + + let data = Object.values(result.loaderData)[0]; + + if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) { + data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id]; + } + + return data; + } + + return undefined; + } + + async function queryImpl(request, location, matches, requestContext, routeMatch) { + invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal"); + + try { + if (isMutationMethod(request.method.toLowerCase())) { + let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null); + return result; + } + + let result = await loadRouteData(request, matches, requestContext, routeMatch); + return isResponse(result) ? result : _extends({}, result, { + actionData: null, + actionHeaders: {} + }); + } catch (e) { + // If the user threw/returned a Response in callLoaderOrAction, we throw + // it to bail out and then return or throw here based on whether the user + // returned or threw + if (isQueryRouteResponse(e)) { + if (e.type === ResultType.error && !isRedirectResponse(e.response)) { + throw e.response; + } + + return e.response; + } // Redirects are always returned since they don't propagate to catch + // boundaries + + + if (isRedirectResponse(e)) { + return e; + } + + throw e; + } + } + + async function submit(request, matches, actionMatch, requestContext, isRouteRequest) { + let result; + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + let error = getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: actionMatch.route.id + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } + } + + if (isRedirectResult(result)) { + // Uhhhh - this should never happen, we should always throw these from + // callLoaderOrAction, but the type narrowing here keeps TS happy and we + // can get back on the "throw all redirect responses" train here should + // this ever happen :/ + throw new Response(null, { + status: result.status, + headers: { + Location: result.location + } + }); + } + + if (isDeferredResult(result)) { + let error = getInternalRouterError(400, { + type: "defer-action" + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } + + if (isRouteRequest) { + // Note: This should only be non-Response values if we get here, since + // isRouteRequest should throw any Response received in callLoaderOrAction + if (isErrorResult(result)) { + throw result.error; + } + + return { + matches: [actionMatch], + loaderData: {}, + actionData: { + [actionMatch.route.id]: result.data + }, + errors: null, + // Note: statusCode + headers are unused here since queryRoute will + // return the raw Response or value + statusCode: 200, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + let context = await loadRouteData(request, matches, requestContext, undefined, { + [boundaryMatch.route.id]: result.error + }); // action status codes take precedence over loader status codes + + return _extends({}, context, { + statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500, + actionData: null, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } // Create a GET request for the loaders + + + let loaderRequest = new Request(request.url, { + headers: request.headers, + redirect: request.redirect, + signal: request.signal + }); + let context = await loadRouteData(loaderRequest, matches, requestContext); + return _extends({}, context, result.statusCode ? { + statusCode: result.statusCode + } : {}, { + actionData: { + [actionMatch.route.id]: result.data + }, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } + + async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) { + let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute()) + + if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader) && !(routeMatch != null && routeMatch.route.lazy)) { + throw getInternalRouterError(400, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: routeMatch == null ? void 0 : routeMatch.route.id + }); + } + + let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]); + let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy); // Short circuit if we have no loaders to run (query()) + + if (matchesToLoad.length === 0) { + return { + matches, + // Add a null for all matched routes for proper revalidation on the client + loaderData: matches.reduce((acc, m) => Object.assign(acc, { + [m.route.id]: null + }), {}), + errors: pendingActionError || null, + statusCode: 200, + loaderHeaders: {}, + activeDeferreds: null + }; + } + + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext))]); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } // Process and commit output from loaders + + + let activeDeferreds = new Map(); + let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client + + let executedLoaders = new Set(matchesToLoad.map(match => match.route.id)); + matches.forEach(match => { + if (!executedLoaders.has(match.route.id)) { + context.loaderData[match.route.id] = null; + } + }); + return _extends({}, context, { + matches, + activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null + }); + } + + return { + dataRoutes, + query, + queryRoute + }; +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region Helpers +//////////////////////////////////////////////////////////////////////////////// + +/** + * Given an existing StaticHandlerContext and an error thrown at render time, + * provide an updated StaticHandlerContext suitable for a second SSR render + */ + +function getStaticContextFromError(routes, context, error) { + let newContext = _extends({}, context, { + statusCode: 500, + errors: { + [context._deepestRenderedBoundaryId || routes[0].id]: error + } + }); + + return newContext; +} + +function isSubmissionNavigation(opts) { + return opts != null && "formData" in opts; +} // Normalize navigation options by converting formMethod=GET formData objects to +// URLSearchParams so they behave identically to links with query params + + +function normalizeNavigateOptions(to, future, opts, isFetcher) { + if (isFetcher === void 0) { + isFetcher = false; + } + + let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations + + if (!opts || !isSubmissionNavigation(opts)) { + return { + path + }; + } + + if (opts.formMethod && !isValidMethod(opts.formMethod)) { + return { + path, + error: getInternalRouterError(405, { + method: opts.formMethod + }) + }; + } // Create a Submission on non-GET navigations + + + let submission; + + if (opts.formData) { + let formMethod = opts.formMethod || "get"; + submission = { + formMethod: future.v7_normalizeFormMethod ? formMethod.toUpperCase() : formMethod.toLowerCase(), + formAction: stripHashFromPath(path), + formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded", + formData: opts.formData + }; + + if (isMutationMethod(submission.formMethod)) { + return { + path, + submission + }; + } + } // Flatten submission onto URLSearchParams for GET submissions + + + let parsedPath = parsePath(path); + let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to + // navigation GET submissions which run all loaders), we need to preserve + // any incoming ?index params + + if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { + searchParams.append("index", ""); + } + + parsedPath.search = "?" + searchParams; + return { + path: createPath(parsedPath), + submission + }; +} // Filter out all routes below any caught error as they aren't going to +// render so we don't need to load them + + +function getLoaderMatchesUntilBoundary(matches, boundaryId) { + let boundaryMatches = matches; + + if (boundaryId) { + let index = matches.findIndex(m => m.route.id === boundaryId); + + if (index >= 0) { + boundaryMatches = matches.slice(0, index); + } + } + + return boundaryMatches; +} + +function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) { + let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; + let currentUrl = history.createURL(state.location); + let nextUrl = history.createURL(location); + let defaultShouldRevalidate = // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate + isRevalidationRequired || // Clicked the same link, resubmitted a GET form + currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders + currentUrl.search !== nextUrl.search; // Pick navigation matches that are net-new or qualify for revalidation + + let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined; + let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId); + let navigationMatches = boundaryMatches.filter((match, index) => { + if (match.route.lazy) { + // We haven't loaded this route yet so we don't know if it's got a loader! + return true; + } + + if (match.route.loader == null) { + return false; + } // Always call the loader on new route instances and pending defer cancellations + + + if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) { + return true; + } // This is the default implementation for when we revalidate. If the route + // provides it's own implementation, then we give them full control but + // provide this value so they can leverage it if needed after they check + // their own specific use cases + + + let currentRouteMatch = state.matches[index]; + let nextRouteMatch = match; + return shouldRevalidateLoader(match, _extends({ + currentUrl, + currentParams: currentRouteMatch.params, + nextUrl, + nextParams: nextRouteMatch.params + }, submission, { + actionResult, + defaultShouldRevalidate: defaultShouldRevalidate || isNewRouteInstance(currentRouteMatch, nextRouteMatch) + })); + }); // Pick fetcher.loads that need to be revalidated + + let revalidatingFetchers = []; + fetchLoadMatches.forEach((f, key) => { + // Don't revalidate if fetcher won't be present in the subsequent render + if (!matches.some(m => m.route.id === f.routeId)) { + return; + } + + let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so + // we can trigger a 404 in callLoadersAndMaybeResolveData + + if (!fetcherMatches) { + revalidatingFetchers.push(_extends({ + key + }, f, { + matches: null, + match: null + })); + return; + } + + let fetcherMatch = getTargetMatch(fetcherMatches, f.path); + + if (cancelledFetcherLoads.includes(key)) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + return; + } // Revalidating fetchers are decoupled from the route matches since they + // hit a static href, so they _always_ check shouldRevalidate and the + // default is strictly if a revalidation is explicitly required (action + // submissions, useRevalidator, X-Remix-Revalidate). + + + let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({ + currentUrl, + currentParams: state.matches[state.matches.length - 1].params, + nextUrl, + nextParams: matches[matches.length - 1].params + }, submission, { + actionResult, + defaultShouldRevalidate + })); + + if (shouldRevalidate) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + } + }); + return [navigationMatches, revalidatingFetchers]; +} + +function isNewLoader(currentLoaderData, currentMatch, match) { + let isNew = // [a] -> [a, b] + !currentMatch || // [a, b] -> [a, c] + match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially + // from a prior error or from a cancelled pending deferred + + let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data + + return isNew || isMissingData; +} + +function isNewRouteInstance(currentMatch, match) { + let currentPath = currentMatch.route.path; + return (// param change for this match, /users/123 -> /users/456 + currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path + // e.g. /files/images/avatar.jpg -> files/finances.xls + currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"] + ); +} + +function shouldRevalidateLoader(loaderMatch, arg) { + if (loaderMatch.route.shouldRevalidate) { + let routeChoice = loaderMatch.route.shouldRevalidate(arg); + + if (typeof routeChoice === "boolean") { + return routeChoice; + } + } + + return arg.defaultShouldRevalidate; +} +/** + * Execute route.lazy() methods to lazily load route modules (loader, action, + * shouldRevalidate) and update the routeManifest in place which shares objects + * with dataRoutes so those get updated as well. + */ + + +async function loadLazyRouteModule(route, detectErrorBoundary, manifest) { + if (!route.lazy) { + return; + } + + let lazyRoute = await route.lazy(); // If the lazy route function was executed and removed by another parallel + // call then we can return - first lazy() to finish wins because the return + // value of lazy is expected to be static + + if (!route.lazy) { + return; + } + + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); // Update the route in place. This should be safe because there's no way + // we could yet be sitting on this route as we can't get there without + // resolving lazy() first. + // + // This is different than the HMR "update" use-case where we may actively be + // on the route being updated. The main concern boils down to "does this + // mutation affect any ongoing navigations or any current state.matches + // values?". If not, it should be safe to update in place. + + let routeUpdates = {}; + + for (let lazyRouteProperty in lazyRoute) { + let staticRouteValue = routeToUpdate[lazyRouteProperty]; + let isPropertyStaticallyDefined = staticRouteValue !== undefined && // This property isn't static since it should always be updated based + // on the route updates + lazyRouteProperty !== "hasErrorBoundary"; + warning(!isPropertyStaticallyDefined, "Route \"" + routeToUpdate.id + "\" has a static property \"" + lazyRouteProperty + "\" " + "defined but its lazy function is also returning a value for this property. " + ("The lazy route property \"" + lazyRouteProperty + "\" will be ignored.")); + + if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) { + routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty]; + } + } // Mutate the route with the provided updates. Do this first so we pass + // the updated version to detectErrorBoundary + + + Object.assign(routeToUpdate, routeUpdates); // Mutate the `hasErrorBoundary` property on the route based on the route + // updates and remove the `lazy` function so we don't resolve the lazy + // route again. + + Object.assign(routeToUpdate, { + // To keep things framework agnostic, we use the provided + // `detectErrorBoundary` function to set the `hasErrorBoundary` route + // property since the logic will differ between frameworks. + hasErrorBoundary: detectErrorBoundary(_extends({}, routeToUpdate)), + lazy: undefined + }); +} + +async function callLoaderOrAction(type, request, match, matches, manifest, detectErrorBoundary, basename, isStaticRequest, isRouteRequest, requestContext) { + if (basename === void 0) { + basename = "/"; + } + + if (isStaticRequest === void 0) { + isStaticRequest = false; + } + + if (isRouteRequest === void 0) { + isRouteRequest = false; + } + + let resultType; + let result; + let onReject; + + let runHandler = handler => { + // Setup a promise we can race against so that abort signals short circuit + let reject; + let abortPromise = new Promise((_, r) => reject = r); + + onReject = () => reject(); + + request.signal.addEventListener("abort", onReject); + return Promise.race([handler({ + request, + params: match.params, + context: requestContext + }), abortPromise]); + }; + + try { + let handler = match.route[type]; + + if (match.route.lazy) { + if (handler) { + // Run statically defined handler in parallel with lazy() + let values = await Promise.all([runHandler(handler), loadLazyRouteModule(match.route, detectErrorBoundary, manifest)]); + result = values[0]; + } else { + // Load lazy route module, then run any returned handler + await loadLazyRouteModule(match.route, detectErrorBoundary, manifest); + handler = match.route[type]; + + if (handler) { + // Handler still run even if we got interrupted to maintain consistency + // with un-abortable behavior of handler execution on non-lazy or + // previously-lazy-loaded routes + result = await runHandler(handler); + } else if (type === "action") { + throw getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: match.route.id + }); + } else { + // lazy() route has no loader to run. Short circuit here so we don't + // hit the invariant below that errors on returning undefined. + return { + type: ResultType.data, + data: undefined + }; + } + } + } else { + invariant(handler, "Could not find the " + type + " to run on the \"" + match.route.id + "\" route"); + result = await runHandler(handler); + } + + invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`."); + } catch (e) { + resultType = ResultType.error; + result = e; + } finally { + if (onReject) { + request.signal.removeEventListener("abort", onReject); + } + } + + if (isResponse(result)) { + let status = result.status; // Process redirects + + if (redirectStatusCodes.has(status)) { + let location = result.headers.get("Location"); + invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header"); // Support relative routing in internal redirects + + if (!ABSOLUTE_URL_REGEX.test(location)) { + let activeMatches = matches.slice(0, matches.indexOf(match) + 1); + let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase); + let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname); + invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + location); // Prepend the basename to the redirect location if we have one + + if (basename) { + let path = resolvedLocation.pathname; + resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]); + } + + location = createPath(resolvedLocation); + } else if (!isStaticRequest) { + // Strip off the protocol+origin for same-origin + same-basename absolute + // redirects. If this is a static request, we can let it go back to the + // browser as-is + let currentUrl = new URL(request.url); + let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location); + let isSameBasename = stripBasename(url.pathname, basename) != null; + + if (url.origin === currentUrl.origin && isSameBasename) { + location = url.pathname + url.search + url.hash; + } + } // Don't process redirects in the router during static requests requests. + // Instead, throw the Response and let the server handle it with an HTTP + // redirect. We also update the Location header in place in this flow so + // basename and relative routing is taken into account + + + if (isStaticRequest) { + result.headers.set("Location", location); + throw result; + } + + return { + type: ResultType.redirect, + status, + location, + revalidate: result.headers.get("X-Remix-Revalidate") !== null + }; + } // For SSR single-route requests, we want to hand Responses back directly + // without unwrapping. We do this with the QueryRouteResponse wrapper + // interface so we can know whether it was returned or thrown + + + if (isRouteRequest) { + // eslint-disable-next-line no-throw-literal + throw { + type: resultType || ResultType.data, + response: result + }; + } + + let data; + let contentType = result.headers.get("Content-Type"); // Check between word boundaries instead of startsWith() due to the last + // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type + + if (contentType && /\bapplication\/json\b/.test(contentType)) { + data = await result.json(); + } else { + data = await result.text(); + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: new ErrorResponse(status, result.statusText, data), + headers: result.headers + }; + } + + return { + type: ResultType.data, + data, + statusCode: result.status, + headers: result.headers + }; + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: result + }; + } + + if (isDeferredData(result)) { + var _result$init, _result$init2; + + return { + type: ResultType.deferred, + deferredData: result, + statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status, + headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers) + }; + } + + return { + type: ResultType.data, + data: result + }; +} // Utility method for creating the Request instances for loaders/actions during +// client-side navigations and fetches. During SSR we will always have a +// Request instance from the static handler (query/queryRoute) + + +function createClientSideRequest(history, location, signal, submission) { + let url = history.createURL(stripHashFromPath(location)).toString(); + let init = { + signal + }; + + if (submission && isMutationMethod(submission.formMethod)) { + let { + formMethod, + formEncType, + formData + } = submission; // Didn't think we needed this but it turns out unlike other methods, patch + // won't be properly normalized to uppercase and results in a 405 error. + // See: https://fetch.spec.whatwg.org/#concept-method + + init.method = formMethod.toUpperCase(); + init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData; + } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request) + + + return new Request(url, init); +} + +function convertFormDataToSearchParams(formData) { + let searchParams = new URLSearchParams(); + + for (let [key, value] of formData.entries()) { + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs + searchParams.append(key, value instanceof File ? value.name : value); + } + + return searchParams; +} + +function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) { + // Fill in loaderData/errors from our loaders + let loaderData = {}; + let errors = null; + let statusCode; + let foundError = false; + let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors + + results.forEach((result, index) => { + let id = matchesToLoad[index].route.id; + invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData"); + + if (isErrorResult(result)) { + // Look upwards from the matched route for the closest ancestor + // error boundary, defaulting to the root match + let boundaryMatch = findNearestBoundary(matches, id); + let error = result.error; // If we have a pending action error, we report it at the highest-route + // that throws a loader error, and then clear it out to indicate that + // it was consumed + + if (pendingError) { + error = Object.values(pendingError)[0]; + pendingError = undefined; + } + + errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary + + if (errors[boundaryMatch.route.id] == null) { + errors[boundaryMatch.route.id] = error; + } // Clear our any prior loaderData for the throwing route + + + loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and + // prevent deeper status codes from overriding + + if (!foundError) { + foundError = true; + statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } else { + if (isDeferredResult(result)) { + activeDeferreds.set(id, result.deferredData); + loaderData[id] = result.deferredData.data; + } else { + loaderData[id] = result.data; + } // Error status codes always override success status codes, but if all + // loaders are successful we take the deepest status code. + + + if (result.statusCode != null && result.statusCode !== 200 && !foundError) { + statusCode = result.statusCode; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } + }); // If we didn't consume the pending action error (i.e., all loaders + // resolved), then consume it here. Also clear out any loaderData for the + // throwing route + + if (pendingError) { + errors = pendingError; + loaderData[Object.keys(pendingError)[0]] = undefined; + } + + return { + loaderData, + errors, + statusCode: statusCode || 200, + loaderHeaders + }; +} + +function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) { + let { + loaderData, + errors + } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers + + for (let index = 0; index < revalidatingFetchers.length; index++) { + let { + key, + match + } = revalidatingFetchers[index]; + invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result"); + let result = fetcherResults[index]; // Process fetcher non-redirect errors + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id); + + if (!(errors && errors[boundaryMatch.route.id])) { + errors = _extends({}, errors, { + [boundaryMatch.route.id]: result.error + }); + } + + state.fetchers.delete(key); + } else if (isRedirectResult(result)) { + // Should never get here, redirects should get processed above, but we + // keep this to type narrow to a success result in the else + invariant(false, "Unhandled fetcher revalidation redirect"); + } else if (isDeferredResult(result)) { + // Should never get here, deferred data should be awaited for fetchers + // in resolveDeferredResults + invariant(false, "Unhandled fetcher deferred data"); + } else { + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + return { + loaderData, + errors + }; +} + +function mergeLoaderData(loaderData, newLoaderData, matches, errors) { + let mergedLoaderData = _extends({}, newLoaderData); + + for (let match of matches) { + let id = match.route.id; + + if (newLoaderData.hasOwnProperty(id)) { + if (newLoaderData[id] !== undefined) { + mergedLoaderData[id] = newLoaderData[id]; + } + } else if (loaderData[id] !== undefined && match.route.loader) { + // Preserve existing keys not included in newLoaderData and where a loader + // wasn't removed by HMR + mergedLoaderData[id] = loaderData[id]; + } + + if (errors && errors.hasOwnProperty(id)) { + // Don't keep any loader data below the boundary + break; + } + } + + return mergedLoaderData; +} // Find the nearest error boundary, looking upwards from the leaf route (or the +// route specified by routeId) for the closest ancestor error boundary, +// defaulting to the root match + + +function findNearestBoundary(matches, routeId) { + let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches]; + return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0]; +} + +function getShortCircuitMatches(routes) { + // Prefer a root layout route if present, otherwise shim in a route object + let route = routes.find(r => r.index || !r.path || r.path === "/") || { + id: "__shim-error-route__" + }; + return { + matches: [{ + params: {}, + pathname: "", + pathnameBase: "", + route + }], + route + }; +} + +function getInternalRouterError(status, _temp4) { + let { + pathname, + routeId, + method, + type + } = _temp4 === void 0 ? {} : _temp4; + let statusText = "Unknown Server Error"; + let errorMessage = "Unknown @remix-run/router error"; + + if (status === 400) { + statusText = "Bad Request"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (type === "defer-action") { + errorMessage = "defer() is not supported in actions"; + } + } else if (status === 403) { + statusText = "Forbidden"; + errorMessage = "Route \"" + routeId + "\" does not match URL \"" + pathname + "\""; + } else if (status === 404) { + statusText = "Not Found"; + errorMessage = "No route matches URL \"" + pathname + "\""; + } else if (status === 405) { + statusText = "Method Not Allowed"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (method) { + errorMessage = "Invalid request method \"" + method.toUpperCase() + "\""; + } + } + + return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true); +} // Find any returned redirect errors, starting from the lowest match + + +function findRedirect(results) { + for (let i = results.length - 1; i >= 0; i--) { + let result = results[i]; + + if (isRedirectResult(result)) { + return result; + } + } +} + +function stripHashFromPath(path) { + let parsedPath = typeof path === "string" ? parsePath(path) : path; + return createPath(_extends({}, parsedPath, { + hash: "" + })); +} + +function isHashChangeOnly(a, b) { + return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash; +} + +function isDeferredResult(result) { + return result.type === ResultType.deferred; +} + +function isErrorResult(result) { + return result.type === ResultType.error; +} + +function isRedirectResult(result) { + return (result && result.type) === ResultType.redirect; +} + +function isDeferredData(value) { + let deferred = value; + return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function"; +} + +function isResponse(value) { + return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; +} + +function isRedirectResponse(result) { + if (!isResponse(result)) { + return false; + } + + let status = result.status; + let location = result.headers.get("Location"); + return status >= 300 && status <= 399 && location != null; +} + +function isQueryRouteResponse(obj) { + return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error); +} + +function isValidMethod(method) { + return validRequestMethods.has(method.toLowerCase()); +} + +function isMutationMethod(method) { + return validMutationMethods.has(method.toLowerCase()); +} + +async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) { + for (let index = 0; index < results.length; index++) { + let result = results[index]; + let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do + // anything with. This is for revalidating fetchers where the route was + // removed during HMR + + if (!match) { + continue; + } + + let currentMatch = currentMatches.find(m => m.route.id === match.route.id); + let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined; + + if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) { + // Note: we do not have to touch activeDeferreds here since we race them + // against the signal in resolveDeferredData and they'll get aborted + // there if needed + await resolveDeferredData(result, signal, isFetcher).then(result => { + if (result) { + results[index] = result || results[index]; + } + }); + } + } +} + +async function resolveDeferredData(result, signal, unwrap) { + if (unwrap === void 0) { + unwrap = false; + } + + let aborted = await result.deferredData.resolveData(signal); + + if (aborted) { + return; + } + + if (unwrap) { + try { + return { + type: ResultType.data, + data: result.deferredData.unwrappedData + }; + } catch (e) { + // Handle any TrackedPromise._error values encountered while unwrapping + return { + type: ResultType.error, + error: e + }; + } + } + + return { + type: ResultType.data, + data: result.deferredData.data + }; +} + +function hasNakedIndexQuery(search) { + return new URLSearchParams(search).getAll("index").some(v => v === ""); +} // Note: This should match the format exported by useMatches, so if you change +// this please also change that :) Eventually we'll DRY this up + + +function createUseMatchesMatch(match, loaderData) { + let { + route, + pathname, + params + } = match; + return { + id: route.id, + pathname, + params, + data: loaderData[route.id], + handle: route.handle + }; +} + +function getTargetMatch(matches, location) { + let search = typeof location === "string" ? parsePath(location).search : location.search; + + if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) { + // Return the leaf index route when index is present + return matches[matches.length - 1]; + } // Otherwise grab the deepest "path contributing" match (ignoring index and + // pathless layout routes) + + + let pathMatches = getPathContributingMatches(matches); + return pathMatches[pathMatches.length - 1]; +} //#endregion + +exports.AbortedDeferredError = AbortedDeferredError; +exports.ErrorResponse = ErrorResponse; +exports.IDLE_BLOCKER = IDLE_BLOCKER; +exports.IDLE_FETCHER = IDLE_FETCHER; +exports.IDLE_NAVIGATION = IDLE_NAVIGATION; +exports.UNSAFE_DEFERRED_SYMBOL = UNSAFE_DEFERRED_SYMBOL; +exports.UNSAFE_DeferredData = DeferredData; +exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes; +exports.UNSAFE_getPathContributingMatches = getPathContributingMatches; +exports.UNSAFE_invariant = invariant; +exports.UNSAFE_warning = warning; +exports.createBrowserHistory = createBrowserHistory; +exports.createHashHistory = createHashHistory; +exports.createMemoryHistory = createMemoryHistory; +exports.createPath = createPath; +exports.createRouter = createRouter; +exports.createStaticHandler = createStaticHandler; +exports.defer = defer; +exports.generatePath = generatePath; +exports.getStaticContextFromError = getStaticContextFromError; +exports.getToPathname = getToPathname; +exports.isDeferredData = isDeferredData; +exports.isRouteErrorResponse = isRouteErrorResponse; +exports.joinPaths = joinPaths; +exports.json = json; +exports.matchPath = matchPath; +exports.matchRoutes = matchRoutes; +exports.normalizePathname = normalizePathname; +exports.parsePath = parsePath; +exports.redirect = redirect; +exports.resolvePath = resolvePath; +exports.resolveTo = resolveTo; +exports.stripBasename = stripBasename; +//# sourceMappingURL=router.cjs.js.map diff --git a/node_modules/@remix-run/router/dist/router.cjs.js.map b/node_modules/@remix-run/router/dist/router.cjs.js.map new file mode 100644 index 00000000..22283003 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.cjs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"router.cjs.js","sources":["../history.ts","../utils.ts","../router.ts"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nexport enum Action {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Pop = \"POP\",\n\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Push = \"PUSH\",\n\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Replace = \"REPLACE\",\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\nexport interface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * An entry in a history stack. A location contains information about the\n * URL path, as well as possibly some arbitrary state and a key.\n */\nexport interface Location extends Path {\n /**\n * A value of arbitrary data associated with this location.\n */\n state: any;\n\n /**\n * A unique string associated with this location. May be used to safely store\n * and retrieve data in some other storage API, like `localStorage`.\n *\n * Note: This value is always \"default\" on the initial location.\n */\n key: string;\n}\n\n/**\n * A change to the current location.\n */\nexport interface Update {\n /**\n * The action that triggered the change.\n */\n action: Action;\n\n /**\n * The new location.\n */\n location: Location;\n\n /**\n * The delta between this location and the former location in the history stack\n */\n delta: number | null;\n}\n\n/**\n * A function that receives notifications about location changes.\n */\nexport interface Listener {\n (update: Update): void;\n}\n\n/**\n * Describes a location that is the destination of some navigation, either via\n * `history.push` or `history.replace`. May be either a URL or the pieces of a\n * URL path.\n */\nexport type To = string | Partial;\n\n/**\n * A history is an interface to the navigation stack. The history serves as the\n * source of truth for the current location, as well as provides a set of\n * methods that may be used to change it.\n *\n * It is similar to the DOM's `window.history` object, but with a smaller, more\n * focused API.\n */\nexport interface History {\n /**\n * The last action that modified the current location. This will always be\n * Action.Pop when a history instance is first created. This value is mutable.\n */\n readonly action: Action;\n\n /**\n * The current location. This value is mutable.\n */\n readonly location: Location;\n\n /**\n * Returns a valid href for the given `to` value that may be used as\n * the value of an attribute.\n *\n * @param to - The destination URL\n */\n createHref(to: To): string;\n\n /**\n * Returns a URL for the given `to` value\n *\n * @param to - The destination URL\n */\n createURL(to: To): URL;\n\n /**\n * Encode a location the same way window.history would do (no-op for memory\n * history) so we ensure our PUSH/REPLACE navigations for data routers\n * behave the same as POP\n *\n * @param to Unencoded path\n */\n encodeLocation(to: To): Path;\n\n /**\n * Pushes a new location onto the history stack, increasing its length by one.\n * If there were any entries in the stack after the current one, they are\n * lost.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n push(to: To, state?: any): void;\n\n /**\n * Replaces the current location in the history stack with a new one. The\n * location that was replaced will no longer be available.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n replace(to: To, state?: any): void;\n\n /**\n * Navigates `n` entries backward/forward in the history stack relative to the\n * current index. For example, a \"back\" navigation would use go(-1).\n *\n * @param delta - The delta in the stack index\n */\n go(delta: number): void;\n\n /**\n * Sets up a listener that will be called whenever the current location\n * changes.\n *\n * @param listener - A function that will be called when the location changes\n * @returns unlisten - A function that may be used to stop listening\n */\n listen(listener: Listener): () => void;\n}\n\ntype HistoryState = {\n usr: any;\n key?: string;\n idx: number;\n};\n\nconst PopStateEventType = \"popstate\";\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Memory History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A user-supplied object that describes a location. Used when providing\n * entries to `createMemoryHistory` via its `initialEntries` option.\n */\nexport type InitialEntry = string | Partial;\n\nexport type MemoryHistoryOptions = {\n initialEntries?: InitialEntry[];\n initialIndex?: number;\n v5Compat?: boolean;\n};\n\n/**\n * A memory history stores locations in memory. This is useful in stateful\n * environments where there is no web browser, such as node tests or React\n * Native.\n */\nexport interface MemoryHistory extends History {\n /**\n * The current index in the history stack.\n */\n readonly index: number;\n}\n\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nexport function createMemoryHistory(\n options: MemoryHistoryOptions = {}\n): MemoryHistory {\n let { initialEntries = [\"/\"], initialIndex, v5Compat = false } = options;\n let entries: Location[]; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) =>\n createMemoryLocation(\n entry,\n typeof entry === \"string\" ? null : entry.state,\n index === 0 ? \"default\" : undefined\n )\n );\n let index = clampIndex(\n initialIndex == null ? entries.length - 1 : initialIndex\n );\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n function clampIndex(n: number): number {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation(): Location {\n return entries[index];\n }\n function createMemoryLocation(\n to: To,\n state: any = null,\n key?: string\n ): Location {\n let location = createLocation(\n entries ? getCurrentLocation().pathname : \"/\",\n to,\n state,\n key\n );\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in memory history: ${JSON.stringify(\n to\n )}`\n );\n return location;\n }\n\n function createHref(to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n let history: MemoryHistory = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to: To) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\",\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 1 });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 0 });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({ action, location: nextLocation, delta });\n }\n },\n listen(fn: Listener) {\n listener = fn;\n return () => {\n listener = null;\n };\n },\n };\n\n return history;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Browser History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A browser history stores the current location in regular URLs in a web\n * browser environment. This is the standard for most web apps and provides the\n * cleanest URLs the browser's address bar.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory\n */\nexport interface BrowserHistory extends UrlHistory {}\n\nexport type BrowserHistoryOptions = UrlHistoryOptions;\n\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nexport function createBrowserHistory(\n options: BrowserHistoryOptions = {}\n): BrowserHistory {\n function createBrowserLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let { pathname, search, hash } = window.location;\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createBrowserHref(window: Window, to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(\n createBrowserLocation,\n createBrowserHref,\n null,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Hash History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A hash history stores the current location in the fragment identifier portion\n * of the URL in a web browser environment.\n *\n * This is ideal for apps that do not control the server for some reason\n * (because the fragment identifier is never sent to the server), including some\n * shared hosting environments that do not provide fine-grained controls over\n * which pages are served at which URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory\n */\nexport interface HashHistory extends UrlHistory {}\n\nexport type HashHistoryOptions = UrlHistoryOptions;\n\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nexport function createHashHistory(\n options: HashHistoryOptions = {}\n): HashHistory {\n function createHashLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createHashHref(window: Window, to: To) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location: Location, to: To) {\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in hash history.push(${JSON.stringify(\n to\n )})`\n );\n }\n\n return getUrlBasedHistory(\n createHashLocation,\n createHashHref,\n validateHashLocation,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region UTILS\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * @private\n */\nexport function invariant(value: boolean, message?: string): asserts value;\nexport function invariant(\n value: T | null | undefined,\n message?: string\n): asserts value is T;\nexport function invariant(value: any, message?: string) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nexport function warning(cond: any, message: string) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location: Location, index: number): HistoryState {\n return {\n usr: location.state,\n key: location.key,\n idx: index,\n };\n}\n\n/**\n * Creates a Location object with a unique key from the given Path\n */\nexport function createLocation(\n current: string | Location,\n to: To,\n state: any = null,\n key?: string\n): Readonly {\n let location: Readonly = {\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\",\n ...(typeof to === \"string\" ? parsePath(to) : to),\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: (to && (to as Location).key) || key || createKey(),\n };\n return location;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial {\n let parsedPath: Partial = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\nexport interface UrlHistory extends History {}\n\nexport type UrlHistoryOptions = {\n window?: Window;\n v5Compat?: boolean;\n};\n\nfunction getUrlBasedHistory(\n getLocation: (window: Window, globalHistory: Window[\"history\"]) => Location,\n createHref: (window: Window, to: To) => string,\n validateLocation: ((location: Location, to: To) => void) | null,\n options: UrlHistoryOptions = {}\n): UrlHistory {\n let { window = document.defaultView!, v5Compat = false } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n let index = getIndex()!;\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState({ ...globalHistory.state, idx: index }, \"\");\n }\n\n function getIndex(): number {\n let state = globalHistory.state || { idx: null };\n return state.idx;\n }\n\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({ action, location: history.location, delta });\n }\n }\n\n function push(to: To, state?: any) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 1 });\n }\n }\n\n function replace(to: To, state?: any) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 0 });\n }\n }\n\n function createURL(to: To): URL {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base =\n window.location.origin !== \"null\"\n ? window.location.origin\n : window.location.href;\n\n let href = typeof to === \"string\" ? to : createPath(to);\n invariant(\n base,\n `No window.location.(origin|href) available to create URL for href: ${href}`\n );\n return new URL(href, base);\n }\n\n let history: History = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn: Listener) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n },\n };\n\n return history;\n}\n\n//#endregion\n","import type { Location, Path, To } from \"./history\";\nimport { warning, invariant, parsePath } from \"./history\";\n\n/**\n * Map of routeId -> data returned from a loader/action/error\n */\nexport interface RouteData {\n [routeId: string]: any;\n}\n\nexport enum ResultType {\n data = \"data\",\n deferred = \"deferred\",\n redirect = \"redirect\",\n error = \"error\",\n}\n\n/**\n * Successful result from a loader or action\n */\nexport interface SuccessResult {\n type: ResultType.data;\n data: any;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Successful defer() result from a loader or action\n */\nexport interface DeferredResult {\n type: ResultType.deferred;\n deferredData: DeferredData;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Redirect result from a loader or action\n */\nexport interface RedirectResult {\n type: ResultType.redirect;\n status: number;\n location: string;\n revalidate: boolean;\n}\n\n/**\n * Unsuccessful result from a loader or action\n */\nexport interface ErrorResult {\n type: ResultType.error;\n error: any;\n headers?: Headers;\n}\n\n/**\n * Result from a loader or action - potentially successful or unsuccessful\n */\nexport type DataResult =\n | SuccessResult\n | DeferredResult\n | RedirectResult\n | ErrorResult;\n\ntype LowerCaseFormMethod = \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\ntype UpperCaseFormMethod = Uppercase;\n\n/**\n * Users can specify either lowercase or uppercase form methods on ,\n * useSubmit(), , etc.\n */\nexport type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;\n\n/**\n * Active navigation/fetcher form methods are exposed in lowercase on the\n * RouterState\n */\nexport type FormMethod = LowerCaseFormMethod;\nexport type MutationFormMethod = Exclude;\n\n/**\n * In v7, active navigation/fetcher form methods are exposed in uppercase on the\n * RouterState. This is to align with the normalization done via fetch().\n */\nexport type V7_FormMethod = UpperCaseFormMethod;\nexport type V7_MutationFormMethod = Exclude;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\";\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n}\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: any;\n}\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Route loader function signature\n */\nexport interface LoaderFunction {\n (args: LoaderFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n formData?: Submission[\"formData\"];\n actionResult?: DataResult;\n defaultShouldRevalidate: boolean;\n }): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set `hasErrorBoundary`\n * from the framework-aware `errorElement` prop\n */\nexport interface DetectErrorBoundaryFunction {\n (route: AgnosticRouteObject): boolean;\n}\n\n/**\n * Keys we cannot change from within a lazy() function. We spread all other keys\n * onto the route. Either they're meaningful to the router, or they'll get\n * ignored.\n */\nexport type ImmutableRouteKey =\n | \"lazy\"\n | \"caseSensitive\"\n | \"path\"\n | \"id\"\n | \"index\"\n | \"children\";\n\nexport const immutableRouteKeys = new Set([\n \"lazy\",\n \"caseSensitive\",\n \"path\",\n \"id\",\n \"index\",\n \"children\",\n]);\n\n/**\n * lazy() function to load a route definition, which can add non-matching\n * related properties to a route\n */\nexport interface LazyRouteFunction {\n (): Promise>;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n lazy?: LazyRouteFunction;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\nexport type RouteManifest = Record;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\ntype PathParam =\n // check if path is just a wildcard\n Path extends \"*\" | \"/*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n detectErrorBoundary: DetectErrorBoundaryFunction,\n parentPath: number[] = [],\n manifest: RouteManifest = {}\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !manifest[id],\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = {\n ...route,\n hasErrorBoundary: detectErrorBoundary(route),\n id,\n };\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n id,\n hasErrorBoundary: detectErrorBoundary(route),\n children: undefined,\n };\n manifest[id] = pathOrLayoutRoute;\n\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(\n route.children,\n detectErrorBoundary,\n treePath,\n manifest\n );\n }\n\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path: string = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n\n const segments = path\n .split(/\\/+/)\n .map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\" as PathParam;\n const starParam = params[star];\n\n // Apply the splat\n return starParam;\n }\n\n const keyMatch = segment.match(/^:(\\w+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key as PathParam];\n\n if (optional === \"?\") {\n return param == null ? \"\" : param;\n }\n\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n\n return param;\n }\n\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter((segment) => !!segment);\n\n return prefix + segments.join(\"/\");\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, paramNames] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = paramNames.reduce>(\n (memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(\n captureGroups[index] || \"\",\n paramName\n );\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, string[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let paramNames: string[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_: string, paramName: string) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, null, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n if (error) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\nexport class ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n error?: Error;\n internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n warning,\n} from \"./history\";\nimport type {\n DataResult,\n DeferredData,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n DeferredResult,\n ErrorResult,\n FormEncType,\n FormMethod,\n DetectErrorBoundaryFunction,\n RedirectResult,\n RouteData,\n AgnosticRouteObject,\n Submission,\n SuccessResult,\n AgnosticRouteMatch,\n ShouldRevalidateFunction,\n RouteManifest,\n ImmutableRouteKey,\n ActionFunction,\n LoaderFunction,\n V7_MutationFormMethod,\n V7_FormMethod,\n HTMLFormMethod,\n MutationFormMethod,\n} from \"./utils\";\nimport {\n ErrorResponse,\n ResultType,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n immutableRouteKeys,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n stripBasename,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterNavigateOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key?: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key?: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * HMR needs to pass in-flight route updates to React Router\n * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)\n */\n _internalSetRoutes(routes: AgnosticRouteObject[]): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface FutureConfig {\n v7_normalizeFormMethod: boolean;\n}\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n routes: AgnosticRouteObject[];\n history: History;\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n future?: FutureConfig;\n hydrationData?: HydrationState;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (state: RouterState): void;\n}\n\ninterface UseMatchesMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: unknown;\n handle: unknown;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UseMatchesMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\n/**\n * Options for a navigate() call for a Link navigation\n */\ntype LinkNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n};\n\n/**\n * Options for a navigate() call for a Form navigation\n */\ntype SubmissionNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n formMethod?: HTMLFormMethod;\n formEncType?: FormEncType;\n formData: FormData;\n};\n\n/**\n * Options to pass to navigate() for either a Link or Form navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions =\n | Omit\n | Omit;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Loading: {\n state: \"loading\";\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n match: AgnosticDataRouteMatch | null;\n matches: AgnosticDataRouteMatch[] | null;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst isBrowser =\n typeof window !== \"undefined\" &&\n typeof window.document !== \"undefined\" &&\n typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser;\n\nconst defaultDetectErrorBoundary = (route: AgnosticRouteObject) =>\n Boolean(route.hasErrorBoundary);\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let detectErrorBoundary =\n init.detectErrorBoundary || defaultDetectErrorBoundary;\n\n // Routes keyed by ID\n let manifest: RouteManifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(\n init.routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined;\n // Config driven behavior flags\n let future: FutureConfig = {\n v7_normalizeFormMethod: false,\n ...init.future,\n };\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(\n dataRoutes,\n init.history.location,\n init.basename\n );\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized =\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n !initialMatches.some((m) => m.route.lazy) &&\n // And we have to either have no loaders or have been provided hydrationData\n (!initialMatches.some((m) => m.route.loader) || init.hydrationData != null);\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations from their actions\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(router.state.blockers) });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location);\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(newState: Partial): void {\n state = {\n ...state,\n ...newState,\n };\n subscribers.forEach((subscriber) => subscriber(state));\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n for (let [key] of blockerFunctions) {\n deleteBlocker(key);\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n\n updateState({\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers: new Map(state.blockers),\n });\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(\n to,\n future,\n opts\n );\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(state.blockers) });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n submission?: Submission;\n fetcherSubmission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponse;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, init.basename);\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n });\n return;\n }\n\n // Short circuit if it's only a hash change and not a mutation submission\n // For example, on /page#hash and submit a which will\n // default to a navigation to /page\n if (\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n ...opts.submission,\n };\n loadingNavigation = navigation;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.fetcherSubmission,\n opts && opts.replace,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts?: { replace?: boolean }\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n ...submission,\n };\n updateState({ navigation });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n fetcherSubmission?: Submission,\n replace?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n if (!loadingNavigation) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n };\n loadingNavigation = navigation;\n }\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission =\n submission || fetcherSubmission\n ? submission || fetcherSubmission\n : loadingNavigation.formMethod &&\n loadingNavigation.formAction &&\n loadingNavigation.formData &&\n loadingNavigation.formEncType\n ? {\n formMethod: loadingNavigation.formMethod,\n formAction: loadingNavigation.formAction,\n formData: loadingNavigation.formData,\n formEncType: loadingNavigation.formEncType,\n }\n : undefined;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n pendingActionData,\n pendingError\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n });\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState({\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n });\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach((rf) =>\n fetchControllers.set(rf.key, pendingNavigationController!)\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n await startRedirectNavigation(state, redirect, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n\n return {\n loaderData,\n errors,\n ...(didAbortFetchLoads || revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n };\n }\n\n function getFetcher(key: string): Fetcher {\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches = matchRoutes(routesToUse, href, init.basename);\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: href })\n );\n return;\n }\n\n let { path, submission } = normalizeNavigateOptions(\n href,\n future,\n opts,\n true\n );\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path });\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action && !match.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error);\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, fetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n ...submission,\n data: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n return startRedirectNavigation(state, actionResult, {\n submission,\n isFetchActionRedirect: true,\n });\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n\n nextLocation,\n abortController.signal\n );\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(routesToUse, state.navigation.location, init.basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: actionResult.data,\n ...submission,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n { [match.route.id]: actionResult.data },\n undefined // No need to send through errors since we short circuit above\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n\n let didAbortFetchLoads = abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n // Put this fetcher into it's loading state\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key);\n // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error,\n },\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n replace,\n isFetchActionRedirect,\n }: {\n submission?: Submission;\n replace?: boolean;\n isFetchActionRedirect?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(\n state.location,\n redirect.location,\n // TODO: This can be removed once we get rid of useTransition in Remix v2\n {\n _isRedirect: true,\n ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}),\n }\n );\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n // Check if this an absolute external redirect that goes to a new origin\n if (\n ABSOLUTE_URL_REGEX.test(redirect.location) &&\n isBrowser &&\n typeof window?.location !== \"undefined\"\n ) {\n let url = init.history.createURL(redirect.location);\n let isDifferentBasename =\n stripBasename(url.pathname, init.basename || \"/\") == null;\n\n if (window.location.origin !== url.origin || isDifferentBasename) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType, formData } = state.navigation;\n if (!submission && formMethod && formAction && formData && formEncType) {\n submission = {\n formMethod,\n formAction,\n formEncType,\n formData,\n };\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n submission &&\n isMutationMethod(submission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...submission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else if (isFetchActionRedirect) {\n // For a fetch action redirect, we kick off a new loading navigation\n // without the fetcher submission, but we send it along for shouldRevalidate\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n },\n fetcherSubmission: submission,\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: submission ? submission.formMethod : undefined,\n formAction: submission ? submission.formAction : undefined,\n formEncType: submission ? submission.formEncType : undefined,\n formData: submission ? submission.formData : undefined,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n )\n ),\n ...fetchersToLoad.map((f) => {\n if (f.matches && f.match) {\n return callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, request.signal),\n f.match,\n f.matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n } else {\n let error: ErrorResult = {\n type: ResultType.error,\n error: getInternalRouterError(404, { pathname: f.path }),\n };\n return error;\n }\n }),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n request.signal,\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n request.signal,\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key: string, routeId: string, error: any) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n });\n }\n\n function deleteFetcher(key: string): void {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): void {\n let doneKeys = [];\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n state.blockers.set(key, newBlocker);\n updateState({ blockers: new Map(state.blockers) });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || ((location) => location.key);\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) {\n inFlightDataRoutes = newRoutes;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\nexport interface CreateStaticHandlerOptions {\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n}\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: CreateStaticHandlerOptions\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let manifest: RouteManifest = {};\n let detectErrorBoundary =\n opts?.detectErrorBoundary || defaultDetectErrorBoundary;\n let dataRoutes = convertRoutesToDataRoutes(\n routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let basename = (opts ? opts.basename : null) || \"/\";\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (\n isRouteRequest &&\n !routeMatch?.route.loader &&\n !routeMatch?.route.lazy\n ) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter(\n (m) => m.route.loader || m.route.lazy\n );\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: RouterNavigateOptions\n): opts is SubmissionNavigateOptions {\n return opts != null && \"formData\" in opts;\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n to: To,\n future: FutureConfig,\n opts?: RouterNavigateOptions,\n isFetcher = false\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponse;\n} {\n let path = typeof to === \"string\" ? to : createPath(to);\n\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n // Create a Submission on non-GET navigations\n let submission: Submission | undefined;\n if (opts.formData) {\n let formMethod = opts.formMethod || \"get\";\n submission = {\n formMethod: future.v7_normalizeFormMethod\n ? (formMethod.toUpperCase() as V7_FormMethod)\n : (formMethod.toLowerCase() as FormMethod),\n formAction: stripHashFromPath(path),\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData: opts.formData,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n let searchParams = convertFormDataToSearchParams(opts.formData);\n // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n fetchLoadMatches: Map,\n routesToUse: AgnosticDataRouteObject[],\n basename: string | undefined,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n let defaultShouldRevalidate =\n // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search;\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n if (match.route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n if (match.route.loader == null) {\n return false;\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n defaultShouldRevalidate ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate if fetcher won't be present in the subsequent render\n if (!matches.some((m) => m.route.id === f.routeId)) {\n return;\n }\n\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData\n if (!fetcherMatches) {\n revalidatingFetchers.push({ key, ...f, matches: null, match: null });\n return;\n }\n\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n\n if (cancelledFetcherLoads.includes(key)) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n return;\n }\n\n // Revalidating fetchers are decoupled from the route matches since they\n // hit a static href, so they _always_ check shouldRevalidate and the\n // default is strictly if a revalidation is explicitly required (action\n // submissions, useRevalidator, X-Remix-Revalidate).\n let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate,\n });\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: Parameters[0]\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(\n route: AgnosticDataRouteObject,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n manifest: RouteManifest\n) {\n if (!route.lazy) {\n return;\n }\n\n let lazyRoute = await route.lazy();\n\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates: Record = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue =\n routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];\n\n let isPropertyStaticallyDefined =\n staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n\n warning(\n !isPropertyStaticallyDefined,\n `Route \"${routeToUpdate.id}\" has a static property \"${lazyRouteProperty}\" ` +\n `defined but its lazy function is also returning a value for this property. ` +\n `The lazy route property \"${lazyRouteProperty}\" will be ignored.`\n );\n\n if (\n !isPropertyStaticallyDefined &&\n !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey)\n ) {\n routeUpdates[lazyRouteProperty] =\n lazyRoute[lazyRouteProperty as keyof typeof lazyRoute];\n }\n }\n\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to detectErrorBoundary\n Object.assign(routeToUpdate, routeUpdates);\n\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, {\n // To keep things framework agnostic, we use the provided\n // `detectErrorBoundary` function to set the `hasErrorBoundary` route\n // property since the logic will differ between frameworks.\n hasErrorBoundary: detectErrorBoundary({ ...routeToUpdate }),\n lazy: undefined,\n });\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n manifest: RouteManifest,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n basename = \"/\",\n isStaticRequest: boolean = false,\n isRouteRequest: boolean = false,\n requestContext?: unknown\n): Promise {\n let resultType;\n let result;\n let onReject: (() => void) | undefined;\n\n let runHandler = (handler: ActionFunction | LoaderFunction) => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n return Promise.race([\n handler({ request, params: match.params, context: requestContext }),\n abortPromise,\n ]);\n };\n\n try {\n let handler = match.route[type];\n\n if (match.route.lazy) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let values = await Promise.all([\n runHandler(handler),\n loadLazyRouteModule(match.route, detectErrorBoundary, manifest),\n ]);\n result = values[0];\n } else {\n // Load lazy route module, then run any returned handler\n await loadLazyRouteModule(match.route, detectErrorBoundary, manifest);\n\n handler = match.route[type];\n if (handler) {\n // Handler still run even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n throw getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: match.route.id,\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return { type: ResultType.data, data: undefined };\n }\n }\n } else {\n invariant(\n handler,\n `Could not find the ${type} to run on the \"${match.route.id}\" route`\n );\n\n result = await runHandler(handler);\n }\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(\n (match) => match.pathnameBase\n );\n let resolvedLocation = resolveTo(\n location,\n routePathnames,\n new URL(request.url).pathname\n );\n invariant(\n createPath(resolvedLocation),\n `Unable to resolve redirect location: ${location}`\n );\n\n // Prepend the basename to the redirect location if we have one\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname =\n path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } else if (!isStaticRequest) {\n // Strip off the protocol+origin for same-origin + same-basename absolute\n // redirects. If this is a static request, we can let it go back to the\n // browser as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result,\n };\n }\n\n let data: any;\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (isDeferredData(result)) {\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: result.init?.status,\n headers: result.init?.headers && new Headers(result.init.headers),\n };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType, formData } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n init.body =\n formEncType === \"application/x-www-form-urlencoded\"\n ? convertFormDataToSearchParams(formData)\n : formData;\n }\n\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, value instanceof File ? value.name : value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponse(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results: DataResult[]): RedirectResult | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n return (\n a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash\n );\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nexport function isDeferredData(value: any): value is DeferredData {\n let deferred: DeferredData = value;\n return (\n deferred &&\n typeof deferred === \"object\" &&\n typeof deferred.data === \"object\" &&\n typeof deferred.subscribe === \"function\" &&\n typeof deferred.cancel === \"function\" &&\n typeof deferred.resolveData === \"function\"\n );\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod | V7_FormMethod {\n return validRequestMethods.has(method.toLowerCase() as FormMethod);\n}\n\nfunction isMutationMethod(\n method: string\n): method is MutationFormMethod | V7_MutationFormMethod {\n return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: (AgnosticDataRouteMatch | null)[],\n results: DataResult[],\n signal: AbortSignal,\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match!.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\n// Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\nfunction createUseMatchesMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UseMatchesMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id] as unknown,\n handle: route.handle as unknown,\n };\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n//#endregion\n"],"names":["Action","PopStateEventType","createMemoryHistory","options","initialEntries","initialIndex","v5Compat","entries","map","entry","index","createMemoryLocation","state","undefined","clampIndex","length","action","Pop","listener","n","Math","min","max","getCurrentLocation","to","key","location","createLocation","pathname","warning","charAt","JSON","stringify","createHref","createPath","history","createURL","URL","encodeLocation","path","parsePath","search","hash","push","Push","nextLocation","splice","delta","replace","Replace","go","nextIndex","listen","fn","createBrowserHistory","createBrowserLocation","window","globalHistory","usr","createBrowserHref","getUrlBasedHistory","createHashHistory","createHashLocation","substr","createHashHref","base","document","querySelector","href","getAttribute","url","hashIndex","indexOf","slice","validateHashLocation","invariant","value","message","Error","cond","console","warn","e","createKey","random","toString","getHistoryState","idx","current","parsedPath","searchIndex","getLocation","validateLocation","defaultView","getIndex","replaceState","handlePop","historyState","pushState","error","assign","origin","addEventListener","removeEventListener","ResultType","immutableRouteKeys","Set","isIndexRoute","route","convertRoutesToDataRoutes","routes","detectErrorBoundary","parentPath","manifest","treePath","id","join","children","indexRoute","hasErrorBoundary","pathOrLayoutRoute","matchRoutes","locationArg","basename","stripBasename","branches","flattenRoutes","rankRouteBranches","matches","i","matchRouteBranch","safelyDecodeURI","parentsMeta","flattenRoute","relativePath","meta","caseSensitive","childrenIndex","startsWith","joinPaths","routesMeta","concat","score","computeScore","forEach","includes","exploded","explodeOptionalSegments","segments","split","first","rest","isOptional","endsWith","required","restExploded","result","subpath","sort","a","b","compareIndexes","paramRe","dynamicSegmentValue","indexRouteValue","emptySegmentValue","staticSegmentValue","splatPenalty","isSplat","s","initialScore","some","filter","reduce","segment","test","siblings","every","branch","matchedParams","matchedPathname","end","remainingPathname","match","matchPath","Object","params","pathnameBase","normalizePathname","generatePath","originalPath","prefix","array","isLastSegment","star","starParam","keyMatch","optional","param","pattern","matcher","paramNames","compilePath","captureGroups","memo","paramName","splatValue","safelyDecodeURIComponent","regexpSource","_","RegExp","decodeURI","decodeURIComponent","toLowerCase","startIndex","nextChar","resolvePath","fromPathname","toPathname","resolvePathname","normalizeSearch","normalizeHash","relativeSegments","pop","getInvalidPathError","char","field","dest","getPathContributingMatches","resolveTo","toArg","routePathnames","locationPathname","isPathRelative","isEmptyPath","from","routePathnameIndex","toSegments","shift","hasExplicitTrailingSlash","hasCurrentTrailingSlash","getToPathname","paths","json","data","init","responseInit","status","headers","Headers","has","set","Response","AbortedDeferredError","DeferredData","constructor","pendingKeysSet","subscribers","deferredKeys","Array","isArray","reject","abortPromise","Promise","r","controller","AbortController","onAbort","unlistenAbortSignal","signal","acc","trackPromise","done","add","promise","race","then","onSettle","catch","defineProperty","get","aborted","delete","emit","settledKey","subscriber","subscribe","cancel","abort","v","k","resolveData","resolve","size","unwrappedData","unwrapTrackedPromise","pendingKeys","isTrackedPromise","_tracked","_error","_data","defer","redirect","ErrorResponse","statusText","internal","isRouteErrorResponse","validMutationMethodsArr","validMutationMethods","validRequestMethodsArr","validRequestMethods","redirectStatusCodes","redirectPreserveMethodStatusCodes","IDLE_NAVIGATION","formMethod","formAction","formEncType","formData","IDLE_FETCHER","IDLE_BLOCKER","proceed","reset","ABSOLUTE_URL_REGEX","isBrowser","createElement","isServer","defaultDetectErrorBoundary","Boolean","createRouter","dataRoutes","inFlightDataRoutes","future","v7_normalizeFormMethod","unlistenHistory","savedScrollPositions","getScrollRestorationKey","getScrollPosition","initialScrollRestored","hydrationData","initialMatches","initialErrors","getInternalRouterError","getShortCircuitMatches","initialized","m","lazy","loader","router","historyAction","navigation","restoreScrollPosition","preventScrollReset","revalidation","loaderData","actionData","errors","fetchers","Map","blockers","pendingAction","HistoryAction","pendingPreventScrollReset","pendingNavigationController","isUninterruptedRevalidation","isRevalidationRequired","cancelledDeferredRoutes","cancelledFetcherLoads","fetchControllers","incrementingLoadId","pendingNavigationLoadId","fetchReloadIds","fetchRedirectIds","fetchLoadMatches","activeDeferreds","blockerFunctions","ignoreNextHistoryUpdate","initialize","blockerKey","shouldBlockNavigation","currentLocation","updateBlocker","deleteBlocker","updateState","startNavigation","dispose","clear","deleteFetcher","newState","completeNavigation","isActionReload","isMutationMethod","_isRedirect","keys","mergeLoaderData","getSavedScrollPosition","navigate","opts","submission","normalizeNavigateOptions","userReplace","pendingError","revalidate","interruptActiveLoads","startUninterruptedRevalidation","overrideNavigation","saveScrollPosition","routesToUse","loadingNavigation","notFoundMatches","cancelActiveDeferreds","isHashChangeOnly","request","createClientSideRequest","pendingActionData","findNearestBoundary","actionOutput","handleAction","shortCircuited","pendingActionError","Request","handleLoaders","fetcherSubmission","actionMatch","getTargetMatch","type","method","routeId","callLoaderOrAction","isRedirectResult","startRedirectNavigation","isErrorResult","boundaryMatch","isDeferredResult","activeSubmission","matchesToLoad","revalidatingFetchers","getMatchesToLoad","rf","fetcher","revalidatingFetcher","results","loaderResults","fetcherResults","callLoadersAndMaybeResolveData","findRedirect","processLoaderData","deferredData","markFetchRedirectsDone","didAbortFetchLoads","abortStaleFetchLoads","getFetcher","fetch","abortFetcher","setFetcherError","handleFetcherAction","handleFetcherLoader","requestMatches","existingFetcher","abortController","fetchRequest","actionResult","loadingFetcher","isFetchActionRedirect","revalidationRequest","loadId","loadFetcher","staleKey","doneFetcher","resolveDeferredData","redirectLocation","_isFetchActionRedirect","isDifferentBasename","redirectHistoryAction","currentMatches","fetchersToLoad","all","f","resolveDeferredResults","markFetchersDone","doneKeys","landedId","yeetedKeys","getBlocker","blocker","newBlocker","blockerFunction","predicate","cancelledRouteIds","dfd","enableScrollRestoration","positions","getPosition","getKey","y","userMatches","createUseMatchesMatch","_internalSetRoutes","newRoutes","_internalFetchControllers","_internalActiveDeferreds","UNSAFE_DEFERRED_SYMBOL","Symbol","createStaticHandler","query","requestContext","isValidMethod","methodNotAllowedMatches","statusCode","loaderHeaders","actionHeaders","queryImpl","isResponse","queryRoute","find","values","routeMatch","submit","loadRouteData","isQueryRouteResponse","isRedirectResponse","response","isRouteRequest","Location","context","loaderRequest","getLoaderMatchesUntilBoundary","processRouteLoaderData","executedLoaders","fromEntries","getStaticContextFromError","newContext","_deepestRenderedBoundaryId","isSubmissionNavigation","isFetcher","toUpperCase","stripHashFromPath","searchParams","convertFormDataToSearchParams","hasNakedIndexQuery","append","boundaryId","boundaryMatches","findIndex","currentUrl","nextUrl","defaultShouldRevalidate","navigationMatches","isNewLoader","currentRouteMatch","nextRouteMatch","shouldRevalidateLoader","currentParams","nextParams","isNewRouteInstance","fetcherMatches","fetcherMatch","shouldRevalidate","currentLoaderData","currentMatch","isNew","isMissingData","currentPath","loaderMatch","arg","routeChoice","loadLazyRouteModule","lazyRoute","routeToUpdate","routeUpdates","lazyRouteProperty","staticRouteValue","isPropertyStaticallyDefined","isStaticRequest","resultType","onReject","runHandler","handler","activeMatches","resolvedLocation","protocol","isSameBasename","contentType","text","isDeferredData","deferred","body","URLSearchParams","File","name","foundError","newLoaderData","mergedLoaderData","hasOwnProperty","eligibleMatches","reverse","errorMessage","obj","isRevalidatingLoader","unwrap","getAll","handle","pathMatches"],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@remix-run/router/dist/router.d.ts b/node_modules/@remix-run/router/dist/router.d.ts new file mode 100644 index 00000000..8c3ea363 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.d.ts @@ -0,0 +1,444 @@ +import type { History, Location, Path, To } from "./history"; +import { Action as HistoryAction } from "./history"; +import type { DeferredData, AgnosticDataRouteMatch, AgnosticDataRouteObject, FormEncType, FormMethod, DetectErrorBoundaryFunction, RouteData, AgnosticRouteObject, AgnosticRouteMatch, V7_FormMethod, HTMLFormMethod } from "./utils"; +/** + * A Router instance manages all navigation and data loading/mutations + */ +export interface Router { + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the basename for the router + */ + get basename(): RouterInit["basename"]; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the current state of the router + */ + get state(): RouterState; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the routes for this router instance + */ + get routes(): AgnosticDataRouteObject[]; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Initialize the router, including adding history listeners and kicking off + * initial data fetches. Returns a function to cleanup listeners and abort + * any in-progress loads + */ + initialize(): Router; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Subscribe to router.state updates + * + * @param fn function to call with the new state + */ + subscribe(fn: RouterSubscriber): () => void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Enable scroll restoration behavior in the router + * + * @param savedScrollPositions Object that will manage positions, in case + * it's being restored from sessionStorage + * @param getScrollPosition Function to get the active Y scroll position + * @param getKey Function to get the key to use for restoration + */ + enableScrollRestoration(savedScrollPositions: Record, getScrollPosition: GetScrollPositionFunction, getKey?: GetScrollRestorationKeyFunction): () => void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Navigate forward/backward in the history stack + * @param to Delta to move in the history stack + */ + navigate(to: number): Promise; + /** + * Navigate to the given path + * @param to Path to navigate to + * @param opts Navigation options (method, submission, etc.) + */ + navigate(to: To, opts?: RouterNavigateOptions): Promise; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Trigger a fetcher load/submission + * + * @param key Fetcher key + * @param routeId Route that owns the fetcher + * @param href href to fetch + * @param opts Fetcher options, (method, submission, etc.) + */ + fetch(key: string, routeId: string, href: string, opts?: RouterNavigateOptions): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Trigger a revalidation of all current route loaders and fetcher loads + */ + revalidate(): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Utility function to create an href for the given location + * @param location + */ + createHref(location: Location | URL): string; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Utility function to URL encode a destination path according to the internal + * history implementation + * @param to + */ + encodeLocation(to: To): Path; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Get/create a fetcher for the given key + * @param key + */ + getFetcher(key?: string): Fetcher; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Delete the fetcher for a given key + * @param key + */ + deleteFetcher(key?: string): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Cleanup listeners and abort any in-progress loads + */ + dispose(): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Get a navigation blocker + * @param key The identifier for the blocker + * @param fn The blocker function implementation + */ + getBlocker(key: string, fn: BlockerFunction): Blocker; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Delete a navigation blocker + * @param key The identifier for the blocker + */ + deleteBlocker(key: string): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * HMR needs to pass in-flight route updates to React Router + * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute) + */ + _internalSetRoutes(routes: AgnosticRouteObject[]): void; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Internal fetch AbortControllers accessed by unit tests + */ + _internalFetchControllers: Map; + /** + * @internal + * PRIVATE - DO NOT USE + * + * Internal pending DeferredData instances accessed by unit tests + */ + _internalActiveDeferreds: Map; +} +/** + * State maintained internally by the router. During a navigation, all states + * reflect the the "old" location unless otherwise noted. + */ +export interface RouterState { + /** + * The action of the most recent navigation + */ + historyAction: HistoryAction; + /** + * The current location reflected by the router + */ + location: Location; + /** + * The current set of route matches + */ + matches: AgnosticDataRouteMatch[]; + /** + * Tracks whether we've completed our initial data load + */ + initialized: boolean; + /** + * Current scroll position we should start at for a new view + * - number -> scroll position to restore to + * - false -> do not restore scroll at all (used during submissions) + * - null -> don't have a saved position, scroll to hash or top of page + */ + restoreScrollPosition: number | false | null; + /** + * Indicate whether this navigation should skip resetting the scroll position + * if we are unable to restore the scroll position + */ + preventScrollReset: boolean; + /** + * Tracks the state of the current navigation + */ + navigation: Navigation; + /** + * Tracks any in-progress revalidations + */ + revalidation: RevalidationState; + /** + * Data from the loaders for the current matches + */ + loaderData: RouteData; + /** + * Data from the action for the current matches + */ + actionData: RouteData | null; + /** + * Errors caught from loaders for the current matches + */ + errors: RouteData | null; + /** + * Map of current fetchers + */ + fetchers: Map; + /** + * Map of current blockers + */ + blockers: Map; +} +/** + * Data that can be passed into hydrate a Router from SSR + */ +export declare type HydrationState = Partial>; +/** + * Future flags to toggle new feature behavior + */ +export interface FutureConfig { + v7_normalizeFormMethod: boolean; +} +/** + * Initialization options for createRouter + */ +export interface RouterInit { + routes: AgnosticRouteObject[]; + history: History; + basename?: string; + detectErrorBoundary?: DetectErrorBoundaryFunction; + future?: FutureConfig; + hydrationData?: HydrationState; +} +/** + * State returned from a server-side query() call + */ +export interface StaticHandlerContext { + basename: Router["basename"]; + location: RouterState["location"]; + matches: RouterState["matches"]; + loaderData: RouterState["loaderData"]; + actionData: RouterState["actionData"]; + errors: RouterState["errors"]; + statusCode: number; + loaderHeaders: Record; + actionHeaders: Record; + activeDeferreds: Record | null; + _deepestRenderedBoundaryId?: string | null; +} +/** + * A StaticHandler instance manages a singular SSR navigation/fetch event + */ +export interface StaticHandler { + dataRoutes: AgnosticDataRouteObject[]; + query(request: Request, opts?: { + requestContext?: unknown; + }): Promise; + queryRoute(request: Request, opts?: { + routeId?: string; + requestContext?: unknown; + }): Promise; +} +/** + * Subscriber function signature for changes to router state + */ +export interface RouterSubscriber { + (state: RouterState): void; +} +interface UseMatchesMatch { + id: string; + pathname: string; + params: AgnosticRouteMatch["params"]; + data: unknown; + handle: unknown; +} +/** + * Function signature for determining the key to be used in scroll restoration + * for a given location + */ +export interface GetScrollRestorationKeyFunction { + (location: Location, matches: UseMatchesMatch[]): string | null; +} +/** + * Function signature for determining the current scroll position + */ +export interface GetScrollPositionFunction { + (): number; +} +/** + * Options for a navigate() call for a Link navigation + */ +declare type LinkNavigateOptions = { + replace?: boolean; + state?: any; + preventScrollReset?: boolean; +}; +/** + * Options for a navigate() call for a Form navigation + */ +declare type SubmissionNavigateOptions = { + replace?: boolean; + state?: any; + preventScrollReset?: boolean; + formMethod?: HTMLFormMethod; + formEncType?: FormEncType; + formData: FormData; +}; +/** + * Options to pass to navigate() for either a Link or Form navigation + */ +export declare type RouterNavigateOptions = LinkNavigateOptions | SubmissionNavigateOptions; +/** + * Options to pass to fetch() + */ +export declare type RouterFetchOptions = Omit | Omit; +/** + * Potential states for state.navigation + */ +export declare type NavigationStates = { + Idle: { + state: "idle"; + location: undefined; + formMethod: undefined; + formAction: undefined; + formEncType: undefined; + formData: undefined; + }; + Loading: { + state: "loading"; + location: Location; + formMethod: FormMethod | V7_FormMethod | undefined; + formAction: string | undefined; + formEncType: FormEncType | undefined; + formData: FormData | undefined; + }; + Submitting: { + state: "submitting"; + location: Location; + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; + }; +}; +export declare type Navigation = NavigationStates[keyof NavigationStates]; +export declare type RevalidationState = "idle" | "loading"; +/** + * Potential states for fetchers + */ +declare type FetcherStates = { + Idle: { + state: "idle"; + formMethod: undefined; + formAction: undefined; + formEncType: undefined; + formData: undefined; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; + Loading: { + state: "loading"; + formMethod: FormMethod | V7_FormMethod | undefined; + formAction: string | undefined; + formEncType: FormEncType | undefined; + formData: FormData | undefined; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; + Submitting: { + state: "submitting"; + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; +}; +export declare type Fetcher = FetcherStates[keyof FetcherStates]; +interface BlockerBlocked { + state: "blocked"; + reset(): void; + proceed(): void; + location: Location; +} +interface BlockerUnblocked { + state: "unblocked"; + reset: undefined; + proceed: undefined; + location: undefined; +} +interface BlockerProceeding { + state: "proceeding"; + reset: undefined; + proceed: undefined; + location: Location; +} +export declare type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding; +export declare type BlockerFunction = (args: { + currentLocation: Location; + nextLocation: Location; + historyAction: HistoryAction; +}) => boolean; +export declare const IDLE_NAVIGATION: NavigationStates["Idle"]; +export declare const IDLE_FETCHER: FetcherStates["Idle"]; +export declare const IDLE_BLOCKER: BlockerUnblocked; +/** + * Create a router and listen to history POP navigations + */ +export declare function createRouter(init: RouterInit): Router; +export declare const UNSAFE_DEFERRED_SYMBOL: unique symbol; +export interface CreateStaticHandlerOptions { + basename?: string; + detectErrorBoundary?: DetectErrorBoundaryFunction; +} +export declare function createStaticHandler(routes: AgnosticRouteObject[], opts?: CreateStaticHandlerOptions): StaticHandler; +/** + * Given an existing StaticHandlerContext and an error thrown at render time, + * provide an updated StaticHandlerContext suitable for a second SSR render + */ +export declare function getStaticContextFromError(routes: AgnosticDataRouteObject[], context: StaticHandlerContext, error: any): StaticHandlerContext; +export declare function isDeferredData(value: any): value is DeferredData; +export {}; diff --git a/node_modules/@remix-run/router/dist/router.js b/node_modules/@remix-run/router/dist/router.js new file mode 100644 index 00000000..e5ae6cd4 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.js @@ -0,0 +1,4182 @@ +/** + * @remix-run/router v1.5.0 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ +function _extends() { + _extends = Object.assign ? Object.assign.bind() : function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + return _extends.apply(this, arguments); +} + +//////////////////////////////////////////////////////////////////////////////// +//#region Types and Constants +//////////////////////////////////////////////////////////////////////////////// + +/** + * Actions represent the type of change to a location value. + */ +var Action; + +(function (Action) { + /** + * A POP indicates a change to an arbitrary index in the history stack, such + * as a back or forward navigation. It does not describe the direction of the + * navigation, only that the current index changed. + * + * Note: This is the default action for newly created history objects. + */ + Action["Pop"] = "POP"; + /** + * A PUSH indicates a new entry being added to the history stack, such as when + * a link is clicked and a new page loads. When this happens, all subsequent + * entries in the stack are lost. + */ + + Action["Push"] = "PUSH"; + /** + * A REPLACE indicates the entry at the current index in the history stack + * being replaced by a new one. + */ + + Action["Replace"] = "REPLACE"; +})(Action || (Action = {})); + +const PopStateEventType = "popstate"; +/** + * Memory history stores the current location in memory. It is designed for use + * in stateful non-browser environments like tests and React Native. + */ + +function createMemoryHistory(options) { + if (options === void 0) { + options = {}; + } + + let { + initialEntries = ["/"], + initialIndex, + v5Compat = false + } = options; + let entries; // Declare so we can access from createMemoryLocation + + entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined)); + let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex); + let action = Action.Pop; + let listener = null; + + function clampIndex(n) { + return Math.min(Math.max(n, 0), entries.length - 1); + } + + function getCurrentLocation() { + return entries[index]; + } + + function createMemoryLocation(to, state, key) { + if (state === void 0) { + state = null; + } + + let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key); + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to)); + return location; + } + + function createHref(to) { + return typeof to === "string" ? to : createPath(to); + } + + let history = { + get index() { + return index; + }, + + get action() { + return action; + }, + + get location() { + return getCurrentLocation(); + }, + + createHref, + + createURL(to) { + return new URL(createHref(to), "http://localhost"); + }, + + encodeLocation(to) { + let path = typeof to === "string" ? parsePath(to) : to; + return { + pathname: path.pathname || "", + search: path.search || "", + hash: path.hash || "" + }; + }, + + push(to, state) { + action = Action.Push; + let nextLocation = createMemoryLocation(to, state); + index += 1; + entries.splice(index, entries.length, nextLocation); + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 1 + }); + } + }, + + replace(to, state) { + action = Action.Replace; + let nextLocation = createMemoryLocation(to, state); + entries[index] = nextLocation; + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 0 + }); + } + }, + + go(delta) { + action = Action.Pop; + let nextIndex = clampIndex(index + delta); + let nextLocation = entries[nextIndex]; + index = nextIndex; + + if (listener) { + listener({ + action, + location: nextLocation, + delta + }); + } + }, + + listen(fn) { + listener = fn; + return () => { + listener = null; + }; + } + + }; + return history; +} +/** + * Browser history stores the location in regular URLs. This is the standard for + * most web apps, but it requires some configuration on the server to ensure you + * serve the same app at multiple URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory + */ + +function createBrowserHistory(options) { + if (options === void 0) { + options = {}; + } + + function createBrowserLocation(window, globalHistory) { + let { + pathname, + search, + hash + } = window.location; + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createBrowserHref(window, to) { + return typeof to === "string" ? to : createPath(to); + } + + return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options); +} +/** + * Hash history stores the location in window.location.hash. This makes it ideal + * for situations where you don't want to send the location to the server for + * some reason, either because you do cannot configure it or the URL space is + * reserved for something else. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory + */ + +function createHashHistory(options) { + if (options === void 0) { + options = {}; + } + + function createHashLocation(window, globalHistory) { + let { + pathname = "/", + search = "", + hash = "" + } = parsePath(window.location.hash.substr(1)); + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createHashHref(window, to) { + let base = window.document.querySelector("base"); + let href = ""; + + if (base && base.getAttribute("href")) { + let url = window.location.href; + let hashIndex = url.indexOf("#"); + href = hashIndex === -1 ? url : url.slice(0, hashIndex); + } + + return href + "#" + (typeof to === "string" ? to : createPath(to)); + } + + function validateHashLocation(location, to) { + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")"); + } + + return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options); +} +function invariant(value, message) { + if (value === false || value === null || typeof value === "undefined") { + throw new Error(message); + } +} +function warning(cond, message) { + if (!cond) { + // eslint-disable-next-line no-console + if (typeof console !== "undefined") console.warn(message); + + try { + // Welcome to debugging history! + // + // This error is thrown as a convenience so you can more easily + // find the source for a warning that appears in the console by + // enabling "pause on exceptions" in your JavaScript debugger. + throw new Error(message); // eslint-disable-next-line no-empty + } catch (e) {} + } +} + +function createKey() { + return Math.random().toString(36).substr(2, 8); +} +/** + * For browser-based histories, we combine the state and key into an object + */ + + +function getHistoryState(location, index) { + return { + usr: location.state, + key: location.key, + idx: index + }; +} +/** + * Creates a Location object with a unique key from the given Path + */ + + +function createLocation(current, to, state, key) { + if (state === void 0) { + state = null; + } + + let location = _extends({ + pathname: typeof current === "string" ? current : current.pathname, + search: "", + hash: "" + }, typeof to === "string" ? parsePath(to) : to, { + state, + // TODO: This could be cleaned up. push/replace should probably just take + // full Locations now and avoid the need to run through this flow at all + // But that's a pretty big refactor to the current test suite so going to + // keep as is for the time being and just let any incoming keys take precedence + key: to && to.key || key || createKey() + }); + + return location; +} +/** + * Creates a string URL path from the given pathname, search, and hash components. + */ + +function createPath(_ref) { + let { + pathname = "/", + search = "", + hash = "" + } = _ref; + if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search; + if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash; + return pathname; +} +/** + * Parses a string URL path into its separate pathname, search, and hash components. + */ + +function parsePath(path) { + let parsedPath = {}; + + if (path) { + let hashIndex = path.indexOf("#"); + + if (hashIndex >= 0) { + parsedPath.hash = path.substr(hashIndex); + path = path.substr(0, hashIndex); + } + + let searchIndex = path.indexOf("?"); + + if (searchIndex >= 0) { + parsedPath.search = path.substr(searchIndex); + path = path.substr(0, searchIndex); + } + + if (path) { + parsedPath.pathname = path; + } + } + + return parsedPath; +} + +function getUrlBasedHistory(getLocation, createHref, validateLocation, options) { + if (options === void 0) { + options = {}; + } + + let { + window = document.defaultView, + v5Compat = false + } = options; + let globalHistory = window.history; + let action = Action.Pop; + let listener = null; + let index = getIndex(); // Index should only be null when we initialize. If not, it's because the + // user called history.pushState or history.replaceState directly, in which + // case we should log a warning as it will result in bugs. + + if (index == null) { + index = 0; + globalHistory.replaceState(_extends({}, globalHistory.state, { + idx: index + }), ""); + } + + function getIndex() { + let state = globalHistory.state || { + idx: null + }; + return state.idx; + } + + function handlePop() { + action = Action.Pop; + let nextIndex = getIndex(); + let delta = nextIndex == null ? null : nextIndex - index; + index = nextIndex; + + if (listener) { + listener({ + action, + location: history.location, + delta + }); + } + } + + function push(to, state) { + action = Action.Push; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex() + 1; + let historyState = getHistoryState(location, index); + let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/ + + try { + globalHistory.pushState(historyState, "", url); + } catch (error) { + // They are going to lose state here, but there is no real + // way to warn them about it since the page will refresh... + window.location.assign(url); + } + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 1 + }); + } + } + + function replace(to, state) { + action = Action.Replace; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex(); + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + globalHistory.replaceState(historyState, "", url); + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 0 + }); + } + } + + function createURL(to) { + // window.location.origin is "null" (the literal string value) in Firefox + // under certain conditions, notably when serving from a local HTML file + // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297 + let base = window.location.origin !== "null" ? window.location.origin : window.location.href; + let href = typeof to === "string" ? to : createPath(to); + invariant(base, "No window.location.(origin|href) available to create URL for href: " + href); + return new URL(href, base); + } + + let history = { + get action() { + return action; + }, + + get location() { + return getLocation(window, globalHistory); + }, + + listen(fn) { + if (listener) { + throw new Error("A history only accepts one active listener"); + } + + window.addEventListener(PopStateEventType, handlePop); + listener = fn; + return () => { + window.removeEventListener(PopStateEventType, handlePop); + listener = null; + }; + }, + + createHref(to) { + return createHref(window, to); + }, + + createURL, + + encodeLocation(to) { + // Encode a Location the same way window.location would + let url = createURL(to); + return { + pathname: url.pathname, + search: url.search, + hash: url.hash + }; + }, + + push, + replace, + + go(n) { + return globalHistory.go(n); + } + + }; + return history; +} //#endregion + +var ResultType; + +(function (ResultType) { + ResultType["data"] = "data"; + ResultType["deferred"] = "deferred"; + ResultType["redirect"] = "redirect"; + ResultType["error"] = "error"; +})(ResultType || (ResultType = {})); + +const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]); + +function isIndexRoute(route) { + return route.index === true; +} // Walk the route tree generating unique IDs where necessary so we are working +// solely with AgnosticDataRouteObject's within the Router + + +function convertRoutesToDataRoutes(routes, detectErrorBoundary, parentPath, manifest) { + if (parentPath === void 0) { + parentPath = []; + } + + if (manifest === void 0) { + manifest = {}; + } + + return routes.map((route, index) => { + let treePath = [...parentPath, index]; + let id = typeof route.id === "string" ? route.id : treePath.join("-"); + invariant(route.index !== true || !route.children, "Cannot specify children on an index route"); + invariant(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages"); + + if (isIndexRoute(route)) { + let indexRoute = _extends({}, route, { + hasErrorBoundary: detectErrorBoundary(route), + id + }); + + manifest[id] = indexRoute; + return indexRoute; + } else { + let pathOrLayoutRoute = _extends({}, route, { + id, + hasErrorBoundary: detectErrorBoundary(route), + children: undefined + }); + + manifest[id] = pathOrLayoutRoute; + + if (route.children) { + pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, detectErrorBoundary, treePath, manifest); + } + + return pathOrLayoutRoute; + } + }); +} +/** + * Matches the given routes to a location and returns the match data. + * + * @see https://reactrouter.com/utils/match-routes + */ + +function matchRoutes(routes, locationArg, basename) { + if (basename === void 0) { + basename = "/"; + } + + let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + let pathname = stripBasename(location.pathname || "/", basename); + + if (pathname == null) { + return null; + } + + let branches = flattenRoutes(routes); + rankRouteBranches(branches); + let matches = null; + + for (let i = 0; matches == null && i < branches.length; ++i) { + matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location + // or from router.navigate, but we want to match against the unencoded + // paths in the route definitions. Memory router locations won't be + // encoded here but there also shouldn't be anything to decode so this + // should be a safe operation. This avoids needing matchRoutes to be + // history-aware. + safelyDecodeURI(pathname)); + } + + return matches; +} + +function flattenRoutes(routes, branches, parentsMeta, parentPath) { + if (branches === void 0) { + branches = []; + } + + if (parentsMeta === void 0) { + parentsMeta = []; + } + + if (parentPath === void 0) { + parentPath = ""; + } + + let flattenRoute = (route, index, relativePath) => { + let meta = { + relativePath: relativePath === undefined ? route.path || "" : relativePath, + caseSensitive: route.caseSensitive === true, + childrenIndex: index, + route + }; + + if (meta.relativePath.startsWith("/")) { + invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes."); + meta.relativePath = meta.relativePath.slice(parentPath.length); + } + + let path = joinPaths([parentPath, meta.relativePath]); + let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the + // route tree depth-first and child routes appear before their parents in + // the "flattened" version. + + if (route.children && route.children.length > 0) { + invariant( // Our types know better, but runtime JS may not! + // @ts-expect-error + route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")); + flattenRoutes(route.children, branches, routesMeta, path); + } // Routes without a path shouldn't ever match by themselves unless they are + // index routes, so don't add them to the list of possible branches. + + + if (route.path == null && !route.index) { + return; + } + + branches.push({ + path, + score: computeScore(path, route.index), + routesMeta + }); + }; + + routes.forEach((route, index) => { + var _route$path; + + // coarse-grain check for optional params + if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) { + flattenRoute(route, index); + } else { + for (let exploded of explodeOptionalSegments(route.path)) { + flattenRoute(route, index, exploded); + } + } + }); + return branches; +} +/** + * Computes all combinations of optional path segments for a given path, + * excluding combinations that are ambiguous and of lower priority. + * + * For example, `/one/:two?/three/:four?/:five?` explodes to: + * - `/one/three` + * - `/one/:two/three` + * - `/one/three/:four` + * - `/one/three/:five` + * - `/one/:two/three/:four` + * - `/one/:two/three/:five` + * - `/one/three/:four/:five` + * - `/one/:two/three/:four/:five` + */ + + +function explodeOptionalSegments(path) { + let segments = path.split("/"); + if (segments.length === 0) return []; + let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?` + + let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo` + + let required = first.replace(/\?$/, ""); + + if (rest.length === 0) { + // Intepret empty string as omitting an optional segment + // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three` + return isOptional ? [required, ""] : [required]; + } + + let restExploded = explodeOptionalSegments(rest.join("/")); + let result = []; // All child paths with the prefix. Do this for all children before the + // optional version for all children so we get consistent ordering where the + // parent optional aspect is preferred as required. Otherwise, we can get + // child sections interspersed where deeper optional segments are higher than + // parent optional segments, where for example, /:two would explodes _earlier_ + // then /:one. By always including the parent as required _for all children_ + // first, we avoid this issue + + result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without + + if (isOptional) { + result.push(...restExploded); + } // for absolute paths, ensure `/` instead of empty segment + + + return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded); +} + +function rankRouteBranches(branches) { + branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first + : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex))); +} + +const paramRe = /^:\w+$/; +const dynamicSegmentValue = 3; +const indexRouteValue = 2; +const emptySegmentValue = 1; +const staticSegmentValue = 10; +const splatPenalty = -2; + +const isSplat = s => s === "*"; + +function computeScore(path, index) { + let segments = path.split("/"); + let initialScore = segments.length; + + if (segments.some(isSplat)) { + initialScore += splatPenalty; + } + + if (index) { + initialScore += indexRouteValue; + } + + return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore); +} + +function compareIndexes(a, b) { + let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]); + return siblings ? // If two routes are siblings, we should try to match the earlier sibling + // first. This allows people to have fine-grained control over the matching + // behavior by simply putting routes with identical paths in the order they + // want them tried. + a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index, + // so they sort equally. + 0; +} + +function matchRouteBranch(branch, pathname) { + let { + routesMeta + } = branch; + let matchedParams = {}; + let matchedPathname = "/"; + let matches = []; + + for (let i = 0; i < routesMeta.length; ++i) { + let meta = routesMeta[i]; + let end = i === routesMeta.length - 1; + let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/"; + let match = matchPath({ + path: meta.relativePath, + caseSensitive: meta.caseSensitive, + end + }, remainingPathname); + if (!match) return null; + Object.assign(matchedParams, match.params); + let route = meta.route; + matches.push({ + // TODO: Can this as be avoided? + params: matchedParams, + pathname: joinPaths([matchedPathname, match.pathname]), + pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])), + route + }); + + if (match.pathnameBase !== "/") { + matchedPathname = joinPaths([matchedPathname, match.pathnameBase]); + } + } + + return matches; +} +/** + * Returns a path with params interpolated. + * + * @see https://reactrouter.com/utils/generate-path + */ + + +function generatePath(originalPath, params) { + if (params === void 0) { + params = {}; + } + + let path = originalPath; + + if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) { + warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + path = path.replace(/\*$/, "/*"); + } // ensure `/` is added at the beginning if the path is absolute + + + const prefix = path.startsWith("/") ? "/" : ""; + const segments = path.split(/\/+/).map((segment, index, array) => { + const isLastSegment = index === array.length - 1; // only apply the splat if it's the last segment + + if (isLastSegment && segment === "*") { + const star = "*"; + const starParam = params[star]; // Apply the splat + + return starParam; + } + + const keyMatch = segment.match(/^:(\w+)(\??)$/); + + if (keyMatch) { + const [, key, optional] = keyMatch; + let param = params[key]; + + if (optional === "?") { + return param == null ? "" : param; + } + + if (param == null) { + invariant(false, "Missing \":" + key + "\" param"); + } + + return param; + } // Remove any optional markers from optional static segments + + + return segment.replace(/\?$/g, ""); + }) // Remove empty segments + .filter(segment => !!segment); + return prefix + segments.join("/"); +} +/** + * Performs pattern matching on a URL pathname and returns information about + * the match. + * + * @see https://reactrouter.com/utils/match-path + */ + +function matchPath(pattern, pathname) { + if (typeof pattern === "string") { + pattern = { + path: pattern, + caseSensitive: false, + end: true + }; + } + + let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end); + let match = pathname.match(matcher); + if (!match) return null; + let matchedPathname = match[0]; + let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1"); + let captureGroups = match.slice(1); + let params = paramNames.reduce((memo, paramName, index) => { + // We need to compute the pathnameBase here using the raw splat value + // instead of using params["*"] later because it will be decoded then + if (paramName === "*") { + let splatValue = captureGroups[index] || ""; + pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1"); + } + + memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName); + return memo; + }, {}); + return { + params, + pathname: matchedPathname, + pathnameBase, + pattern + }; +} + +function compilePath(path, caseSensitive, end) { + if (caseSensitive === void 0) { + caseSensitive = false; + } + + if (end === void 0) { + end = true; + } + + warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + let paramNames = []; + let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below + .replace(/^\/*/, "/") // Make sure it has a leading / + .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars + .replace(/\/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName); + return "/([^\\/]+)"; + }); + + if (path.endsWith("*")) { + paramNames.push("*"); + regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest + : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"] + } else if (end) { + // When matching to the end, ignore trailing slashes + regexpSource += "\\/*$"; + } else if (path !== "" && path !== "/") { + // If our path is non-empty and contains anything beyond an initial slash, + // then we have _some_ form of path in our regex so we should expect to + // match only if we find the end of this path segment. Look for an optional + // non-captured trailing slash (to match a portion of the URL) or the end + // of the path (if we've matched to the end). We used to do this with a + // word boundary but that gives false positives on routes like + // /user-preferences since `-` counts as a word boundary. + regexpSource += "(?:(?=\\/|$))"; + } else ; + + let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i"); + return [matcher, paramNames]; +} + +function safelyDecodeURI(value) { + try { + return decodeURI(value); + } catch (error) { + warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ").")); + return value; + } +} + +function safelyDecodeURIComponent(value, paramName) { + try { + return decodeURIComponent(value); + } catch (error) { + warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ").")); + return value; + } +} +/** + * @private + */ + + +function stripBasename(pathname, basename) { + if (basename === "/") return pathname; + + if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) { + return null; + } // We want to leave trailing slash behavior in the user's control, so if they + // specify a basename with a trailing slash, we should support it + + + let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length; + let nextChar = pathname.charAt(startIndex); + + if (nextChar && nextChar !== "/") { + // pathname does not start with basename/ + return null; + } + + return pathname.slice(startIndex) || "/"; +} +/** + * Returns a resolved path object relative to the given pathname. + * + * @see https://reactrouter.com/utils/resolve-path + */ + +function resolvePath(to, fromPathname) { + if (fromPathname === void 0) { + fromPathname = "/"; + } + + let { + pathname: toPathname, + search = "", + hash = "" + } = typeof to === "string" ? parsePath(to) : to; + let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname; + return { + pathname, + search: normalizeSearch(search), + hash: normalizeHash(hash) + }; +} + +function resolvePathname(relativePath, fromPathname) { + let segments = fromPathname.replace(/\/+$/, "").split("/"); + let relativeSegments = relativePath.split("/"); + relativeSegments.forEach(segment => { + if (segment === "..") { + // Keep the root "" segment so the pathname starts at / + if (segments.length > 1) segments.pop(); + } else if (segment !== ".") { + segments.push(segment); + } + }); + return segments.length > 1 ? segments.join("/") : "/"; +} + +function getInvalidPathError(char, field, dest, path) { + return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in and the router will parse it for you."; +} +/** + * @private + * + * When processing relative navigation we want to ignore ancestor routes that + * do not contribute to the path, such that index/pathless layout routes don't + * interfere. + * + * For example, when moving a route element into an index route and/or a + * pathless layout route, relative link behavior contained within should stay + * the same. Both of the following examples should link back to the root: + * + * + * + * + * + * + * + * }> // <-- Does not contribute + * // <-- Does not contribute + * + * + */ + + +function getPathContributingMatches(matches) { + return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0); +} +/** + * @private + */ + +function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) { + if (isPathRelative === void 0) { + isPathRelative = false; + } + + let to; + + if (typeof toArg === "string") { + to = parsePath(toArg); + } else { + to = _extends({}, toArg); + invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to)); + invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to)); + invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to)); + } + + let isEmptyPath = toArg === "" || to.pathname === ""; + let toPathname = isEmptyPath ? "/" : to.pathname; + let from; // Routing is relative to the current pathname if explicitly requested. + // + // If a pathname is explicitly provided in `to`, it should be relative to the + // route context. This is explained in `Note on `` values` in our + // migration guide from v5 as a means of disambiguation between `to` values + // that begin with `/` and those that do not. However, this is problematic for + // `to` values that do not provide a pathname. `to` can simply be a search or + // hash string, in which case we should assume that the navigation is relative + // to the current location's pathname and *not* the route pathname. + + if (isPathRelative || toPathname == null) { + from = locationPathname; + } else { + let routePathnameIndex = routePathnames.length - 1; + + if (toPathname.startsWith("..")) { + let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one + // URL segment". This is a key difference from how works and a + // major reason we call this a "to" value instead of a "href". + + while (toSegments[0] === "..") { + toSegments.shift(); + routePathnameIndex -= 1; + } + + to.pathname = toSegments.join("/"); + } // If there are more ".." segments than parent routes, resolve relative to + // the root / URL. + + + from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/"; + } + + let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one + + let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash + + let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/"); + + if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) { + path.pathname += "/"; + } + + return path; +} +/** + * @private + */ + +function getToPathname(to) { + // Empty strings should be treated the same as / paths + return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname; +} +/** + * @private + */ + +const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/"); +/** + * @private + */ + +const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/"); +/** + * @private + */ + +const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search; +/** + * @private + */ + +const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; +/** + * This is a shortcut for creating `application/json` responses. Converts `data` + * to JSON and sets the `Content-Type` header. + */ + +const json = function json(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + let headers = new Headers(responseInit.headers); + + if (!headers.has("Content-Type")) { + headers.set("Content-Type", "application/json; charset=utf-8"); + } + + return new Response(JSON.stringify(data), _extends({}, responseInit, { + headers + })); +}; +class AbortedDeferredError extends Error {} +class DeferredData { + constructor(data, responseInit) { + this.pendingKeysSet = new Set(); + this.subscribers = new Set(); + this.deferredKeys = []; + invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early + // cancellation + + let reject; + this.abortPromise = new Promise((_, r) => reject = r); + this.controller = new AbortController(); + + let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted")); + + this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort); + + this.controller.signal.addEventListener("abort", onAbort); + this.data = Object.entries(data).reduce((acc, _ref) => { + let [key, value] = _ref; + return Object.assign(acc, { + [key]: this.trackPromise(key, value) + }); + }, {}); + + if (this.done) { + // All incoming values were resolved + this.unlistenAbortSignal(); + } + + this.init = responseInit; + } + + trackPromise(key, value) { + if (!(value instanceof Promise)) { + return value; + } + + this.deferredKeys.push(key); + this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with + // _data/_error props upon resolve/reject + + let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on + // errors or aborted deferred values + + promise.catch(() => {}); + Object.defineProperty(promise, "_tracked", { + get: () => true + }); + return promise; + } + + onSettle(promise, key, error, data) { + if (this.controller.signal.aborted && error instanceof AbortedDeferredError) { + this.unlistenAbortSignal(); + Object.defineProperty(promise, "_error", { + get: () => error + }); + return Promise.reject(error); + } + + this.pendingKeysSet.delete(key); + + if (this.done) { + // Nothing left to abort! + this.unlistenAbortSignal(); + } + + if (error) { + Object.defineProperty(promise, "_error", { + get: () => error + }); + this.emit(false, key); + return Promise.reject(error); + } + + Object.defineProperty(promise, "_data", { + get: () => data + }); + this.emit(false, key); + return data; + } + + emit(aborted, settledKey) { + this.subscribers.forEach(subscriber => subscriber(aborted, settledKey)); + } + + subscribe(fn) { + this.subscribers.add(fn); + return () => this.subscribers.delete(fn); + } + + cancel() { + this.controller.abort(); + this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k)); + this.emit(true); + } + + async resolveData(signal) { + let aborted = false; + + if (!this.done) { + let onAbort = () => this.cancel(); + + signal.addEventListener("abort", onAbort); + aborted = await new Promise(resolve => { + this.subscribe(aborted => { + signal.removeEventListener("abort", onAbort); + + if (aborted || this.done) { + resolve(aborted); + } + }); + }); + } + + return aborted; + } + + get done() { + return this.pendingKeysSet.size === 0; + } + + get unwrappedData() { + invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds"); + return Object.entries(this.data).reduce((acc, _ref2) => { + let [key, value] = _ref2; + return Object.assign(acc, { + [key]: unwrapTrackedPromise(value) + }); + }, {}); + } + + get pendingKeys() { + return Array.from(this.pendingKeysSet); + } + +} + +function isTrackedPromise(value) { + return value instanceof Promise && value._tracked === true; +} + +function unwrapTrackedPromise(value) { + if (!isTrackedPromise(value)) { + return value; + } + + if (value._error) { + throw value._error; + } + + return value._data; +} + +const defer = function defer(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + return new DeferredData(data, responseInit); +}; +/** + * A redirect response. Sets the status code and the `Location` header. + * Defaults to "302 Found". + */ + +const redirect = function redirect(url, init) { + if (init === void 0) { + init = 302; + } + + let responseInit = init; + + if (typeof responseInit === "number") { + responseInit = { + status: responseInit + }; + } else if (typeof responseInit.status === "undefined") { + responseInit.status = 302; + } + + let headers = new Headers(responseInit.headers); + headers.set("Location", url); + return new Response(null, _extends({}, responseInit, { + headers + })); +}; +/** + * @private + * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies + */ + +class ErrorResponse { + constructor(status, statusText, data, internal) { + if (internal === void 0) { + internal = false; + } + + this.status = status; + this.statusText = statusText || ""; + this.internal = internal; + + if (data instanceof Error) { + this.data = data.toString(); + this.error = data; + } else { + this.data = data; + } + } + +} +/** + * Check if the given error is an ErrorResponse generated from a 4xx/5xx + * Response thrown from an action/loader + */ + +function isRouteErrorResponse(error) { + return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error; +} + +const validMutationMethodsArr = ["post", "put", "patch", "delete"]; +const validMutationMethods = new Set(validMutationMethodsArr); +const validRequestMethodsArr = ["get", ...validMutationMethodsArr]; +const validRequestMethods = new Set(validRequestMethodsArr); +const redirectStatusCodes = new Set([301, 302, 303, 307, 308]); +const redirectPreserveMethodStatusCodes = new Set([307, 308]); +const IDLE_NAVIGATION = { + state: "idle", + location: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined +}; +const IDLE_FETCHER = { + state: "idle", + data: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined +}; +const IDLE_BLOCKER = { + state: "unblocked", + proceed: undefined, + reset: undefined, + location: undefined +}; +const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i; +const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined"; +const isServer = !isBrowser; + +const defaultDetectErrorBoundary = route => Boolean(route.hasErrorBoundary); //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region createRouter +//////////////////////////////////////////////////////////////////////////////// + +/** + * Create a router and listen to history POP navigations + */ + + +function createRouter(init) { + invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter"); + let detectErrorBoundary = init.detectErrorBoundary || defaultDetectErrorBoundary; // Routes keyed by ID + + let manifest = {}; // Routes in tree format for matching + + let dataRoutes = convertRoutesToDataRoutes(init.routes, detectErrorBoundary, undefined, manifest); + let inFlightDataRoutes; // Config driven behavior flags + + let future = _extends({ + v7_normalizeFormMethod: false + }, init.future); // Cleanup function for history + + + let unlistenHistory = null; // Externally-provided functions to call on all state changes + + let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing + + let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys + + let getScrollRestorationKey = null; // Externally-provided function to get current scroll position + + let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration. Because + // we don't get the saved positions from until _after_ + // the initial render, we need to manually trigger a separate updateState to + // send along the restoreScrollPosition + // Set to true if we have `hydrationData` since we assume we were SSR'd and that + // SSR did the initial scroll restoration. + + let initialScrollRestored = init.hydrationData != null; + let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename); + let initialErrors = null; + + if (initialMatches == null) { + // If we do not match a user-provided-route, fall back to the root + // to allow the error boundary to take over + let error = getInternalRouterError(404, { + pathname: init.history.location.pathname + }); + let { + matches, + route + } = getShortCircuitMatches(dataRoutes); + initialMatches = matches; + initialErrors = { + [route.id]: error + }; + } + + let initialized = // All initialMatches need to be loaded before we're ready. If we have lazy + // functions around still then we'll need to run them in initialize() + !initialMatches.some(m => m.route.lazy) && ( // And we have to either have no loaders or have been provided hydrationData + !initialMatches.some(m => m.route.loader) || init.hydrationData != null); + let router; + let state = { + historyAction: init.history.action, + location: init.history.location, + matches: initialMatches, + initialized, + navigation: IDLE_NAVIGATION, + // Don't restore on initial updateState() if we were SSR'd + restoreScrollPosition: init.hydrationData != null ? false : null, + preventScrollReset: false, + revalidation: "idle", + loaderData: init.hydrationData && init.hydrationData.loaderData || {}, + actionData: init.hydrationData && init.hydrationData.actionData || null, + errors: init.hydrationData && init.hydrationData.errors || initialErrors, + fetchers: new Map(), + blockers: new Map() + }; // -- Stateful internal variables to manage navigations -- + // Current navigation in progress (to be committed in completeNavigation) + + let pendingAction = Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot + // be restored? + + let pendingPreventScrollReset = false; // AbortController for the active navigation + + let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a + // revalidation is entirely uninterrupted + + let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders: + // - submissions (completed or interrupted) + // - useRevalidate() + // - X-Remix-Revalidate (from redirect) + + let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due + // to a cancelled deferred on action submission + + let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an + // action navigation and require revalidation + + let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers + + let fetchControllers = new Map(); // Track loads based on the order in which they started + + let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against + // the globally incrementing load when a fetcher load lands after a completed + // navigation + + let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions + + let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions + + let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers + + let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches. When a + // route loader returns defer() we stick one in here. Then, when a nested + // promise resolves we update loaderData. If a new navigation starts we + // cancel active deferreds for eliminated routes. + + let activeDeferreds = new Map(); // Store blocker functions in a separate Map outside of router state since + // we don't need to update UI state if they change + + let blockerFunctions = new Map(); // Flag to ignore the next history update, so we can revert the URL change on + // a POP navigation that was blocked by the user without touching router state + + let ignoreNextHistoryUpdate = false; // Initialize the router, all side effects should be kicked off from here. + // Implemented as a Fluent API for ease of: + // let router = createRouter(init).initialize(); + + function initialize() { + // If history informs us of a POP navigation, start the navigation but do not update + // state. We'll update our own state once the navigation completes + unlistenHistory = init.history.listen(_ref => { + let { + action: historyAction, + location, + delta + } = _ref; + + // Ignore this event if it was just us resetting the URL from a + // blocked POP navigation + if (ignoreNextHistoryUpdate) { + ignoreNextHistoryUpdate = false; + return; + } + + warning(blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + "via `window.history.pushState`/`window.location.hash` instead of using " + "router navigation APIs. This can also happen if you are using " + "createHashRouter and the user manually changes the URL."); + let blockerKey = shouldBlockNavigation({ + currentLocation: state.location, + nextLocation: location, + historyAction + }); + + if (blockerKey && delta != null) { + // Restore the URL to match the current UI, but don't update router state + ignoreNextHistoryUpdate = true; + init.history.go(delta * -1); // Put the blocker into a blocked state + + updateBlocker(blockerKey, { + state: "blocked", + location, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location + }); // Re-do the same POP navigation we just blocked + + init.history.go(delta); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(router.state.blockers) + }); + } + + }); + return; + } + + return startNavigation(historyAction, location); + }); // Kick off initial data load if needed. Use Pop to avoid modifying history + // Note we don't do any handling of lazy here. For SPA's it'll get handled + // in the normal navigation flow. For SSR it's expected that lazy modules are + // resolved prior to router creation since we can't go into a fallbackElement + // UI for SSR'd apps + + if (!state.initialized) { + startNavigation(Action.Pop, state.location); + } + + return router; + } // Clean up a router and it's side effects + + + function dispose() { + if (unlistenHistory) { + unlistenHistory(); + } + + subscribers.clear(); + pendingNavigationController && pendingNavigationController.abort(); + state.fetchers.forEach((_, key) => deleteFetcher(key)); + state.blockers.forEach((_, key) => deleteBlocker(key)); + } // Subscribe to state updates for the router + + + function subscribe(fn) { + subscribers.add(fn); + return () => subscribers.delete(fn); + } // Update our state and notify the calling context of the change + + + function updateState(newState) { + state = _extends({}, state, newState); + subscribers.forEach(subscriber => subscriber(state)); + } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION + // and setting state.[historyAction/location/matches] to the new route. + // - Location is a required param + // - Navigation will always be set to IDLE_NAVIGATION + // - Can pass any other state in newState + + + function completeNavigation(location, newState) { + var _location$state, _location$state2; + + // Deduce if we're in a loading/actionReload state: + // - We have committed actionData in the store + // - The current navigation was a mutation submission + // - We're past the submitting state and into the loading state + // - The location being loaded is not the result of a redirect + let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true; + let actionData; + + if (newState.actionData) { + if (Object.keys(newState.actionData).length > 0) { + actionData = newState.actionData; + } else { + // Empty actionData -> clear prior actionData due to an action error + actionData = null; + } + } else if (isActionReload) { + // Keep the current data if we're wrapping up the action reload + actionData = state.actionData; + } else { + // Clear actionData on any other completed navigations + actionData = null; + } // Always preserve any existing loaderData from re-used routes + + + let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // On a successful navigation we can assume we got through all blockers + // so we can start fresh + + for (let [key] of blockerFunctions) { + deleteBlocker(key); + } // Always respect the user flag. Otherwise don't reset on mutation + // submission navigations unless they redirect + + + let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true; + + if (inFlightDataRoutes) { + dataRoutes = inFlightDataRoutes; + inFlightDataRoutes = undefined; + } + + updateState(_extends({}, newState, { + actionData, + loaderData, + historyAction: pendingAction, + location, + initialized: true, + navigation: IDLE_NAVIGATION, + revalidation: "idle", + restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches), + preventScrollReset, + blockers: new Map(state.blockers) + })); + + if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) { + init.history.push(location, location.state); + } else if (pendingAction === Action.Replace) { + init.history.replace(location, location.state); + } // Reset stateful navigation vars + + + pendingAction = Action.Pop; + pendingPreventScrollReset = false; + isUninterruptedRevalidation = false; + isRevalidationRequired = false; + cancelledDeferredRoutes = []; + cancelledFetcherLoads = []; + } // Trigger a navigation event, which can either be a numerical POP or a PUSH + // replace with an optional submission + + + async function navigate(to, opts) { + if (typeof to === "number") { + init.history.go(to); + return; + } + + let { + path, + submission, + error + } = normalizeNavigateOptions(to, future, opts); + let currentLocation = state.location; + let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded + // URL from window.location, so we need to encode it here so the behavior + // remains the same as POP and non-data-router usages. new URL() does all + // the same encoding we'd get from a history.pushState/window.location read + // without having to touch history + + nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation)); + let userReplace = opts && opts.replace != null ? opts.replace : undefined; + let historyAction = Action.Push; + + if (userReplace === true) { + historyAction = Action.Replace; + } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) { + // By default on submissions to the current location we REPLACE so that + // users don't have to double-click the back button to get to the prior + // location. If the user redirects to a different location from the + // action/loader this will be ignored and the redirect will be a PUSH + historyAction = Action.Replace; + } + + let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined; + let blockerKey = shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction + }); + + if (blockerKey) { + // Put the blocker into a blocked state + updateBlocker(blockerKey, { + state: "blocked", + location: nextLocation, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location: nextLocation + }); // Send the same navigation through + + navigate(to, opts); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(state.blockers) + }); + } + + }); + return; + } + + return await startNavigation(historyAction, nextLocation, { + submission, + // Send through the formData serialization error if we have one so we can + // render at the right error boundary after we match routes + pendingError: error, + preventScrollReset, + replace: opts && opts.replace + }); + } // Revalidate all current loaders. If a navigation is in progress or if this + // is interrupted by a navigation, allow this to "succeed" by calling all + // loaders during the next loader round + + + function revalidate() { + interruptActiveLoads(); + updateState({ + revalidation: "loading" + }); // If we're currently submitting an action, we don't need to start a new + // navigation, we'll just let the follow up loader execution call all loaders + + if (state.navigation.state === "submitting") { + return; + } // If we're currently in an idle state, start a new navigation for the current + // action/location and mark it as uninterrupted, which will skip the history + // update in completeNavigation + + + if (state.navigation.state === "idle") { + startNavigation(state.historyAction, state.location, { + startUninterruptedRevalidation: true + }); + return; + } // Otherwise, if we're currently in a loading state, just start a new + // navigation to the navigation.location but do not trigger an uninterrupted + // revalidation so that history correctly updates once the navigation completes + + + startNavigation(pendingAction || state.historyAction, state.navigation.location, { + overrideNavigation: state.navigation + }); + } // Start a navigation to the given action/location. Can optionally provide a + // overrideNavigation which will override the normalLoad in the case of a redirect + // navigation + + + async function startNavigation(historyAction, location, opts) { + // Abort any in-progress navigations and start a new one. Unset any ongoing + // uninterrupted revalidations unless told otherwise, since we want this + // new navigation to update history normally + pendingNavigationController && pendingNavigationController.abort(); + pendingNavigationController = null; + pendingAction = historyAction; + isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation, + // and track whether we should reset scroll on completion + + saveScrollPosition(state.location, state.matches); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + let routesToUse = inFlightDataRoutes || dataRoutes; + let loadingNavigation = opts && opts.overrideNavigation; + let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing + + if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes + + cancelActiveDeferreds(); + completeNavigation(location, { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error + } + }); + return; + } // Short circuit if it's only a hash change and not a mutation submission + // For example, on /page#hash and submit a which will + // default to a navigation to /page + + + if (isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) { + completeNavigation(location, { + matches + }); + return; + } // Create a controller/Request for this navigation + + + pendingNavigationController = new AbortController(); + let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission); + let pendingActionData; + let pendingError; + + if (opts && opts.pendingError) { + // If we have a pendingError, it means the user attempted a GET submission + // with binary FormData so assign here and skip to handleLoaders. That + // way we handle calling loaders above the boundary etc. It's not really + // different from an actionError in that sense. + pendingError = { + [findNearestBoundary(matches).route.id]: opts.pendingError + }; + } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) { + // Call action if we received an action submission + let actionOutput = await handleAction(request, location, opts.submission, matches, { + replace: opts.replace + }); + + if (actionOutput.shortCircuited) { + return; + } + + pendingActionData = actionOutput.pendingActionData; + pendingError = actionOutput.pendingActionError; + + let navigation = _extends({ + state: "loading", + location + }, opts.submission); + + loadingNavigation = navigation; // Create a GET request for the loaders + + request = new Request(request.url, { + signal: request.signal + }); + } // Call loaders + + + let { + shortCircuited, + loaderData, + errors + } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError); + + if (shortCircuited) { + return; + } // Clean up now that the action/loaders have completed. Don't clean up if + // we short circuited because pendingNavigationController will have already + // been assigned to a new controller for the next navigation + + + pendingNavigationController = null; + completeNavigation(location, _extends({ + matches + }, pendingActionData ? { + actionData: pendingActionData + } : {}, { + loaderData, + errors + })); + } // Call the action matched by the leaf route for this navigation and handle + // redirects/errors + + + async function handleAction(request, location, submission, matches, opts) { + interruptActiveLoads(); // Put us in a submitting state + + let navigation = _extends({ + state: "submitting", + location + }, submission); + + updateState({ + navigation + }); // Call our action and get the result + + let result; + let actionMatch = getTargetMatch(matches, location); + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + result = { + type: ResultType.error, + error: getInternalRouterError(405, { + method: request.method, + pathname: location.pathname, + routeId: actionMatch.route.id + }) + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, router.basename); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } + } + + if (isRedirectResult(result)) { + let replace; + + if (opts && opts.replace != null) { + replace = opts.replace; + } else { + // If the user didn't explicity indicate replace behavior, replace if + // we redirected to the exact same location we're currently at to avoid + // double back-buttons + replace = result.location === state.location.pathname + state.location.search; + } + + await startRedirectNavigation(state, result, { + submission, + replace + }); + return { + shortCircuited: true + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the + // action threw an error that'll be rendered in an errorElement, we fall + // back to PUSH so that the user can use the back button to get back to + // the pre-submission form location to try again + + if ((opts && opts.replace) !== true) { + pendingAction = Action.Push; + } + + return { + // Send back an empty object we can use to clear out any prior actionData + pendingActionData: {}, + pendingActionError: { + [boundaryMatch.route.id]: result.error + } + }; + } + + if (isDeferredResult(result)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } + + return { + pendingActionData: { + [actionMatch.route.id]: result.data + } + }; + } // Call all applicable loaders for the given matches, handling redirects, + // errors, etc. + + + async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) { + // Figure out the right navigation we want to use for data loading + let loadingNavigation = overrideNavigation; + + if (!loadingNavigation) { + let navigation = _extends({ + state: "loading", + location, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission); + + loadingNavigation = navigation; + } // If this was a redirect from an action we don't have a "submission" but + // we have it on the loading navigation so use that if available + + + let activeSubmission = submission || fetcherSubmission ? submission || fetcherSubmission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? { + formMethod: loadingNavigation.formMethod, + formAction: loadingNavigation.formAction, + formData: loadingNavigation.formData, + formEncType: loadingNavigation.formEncType + } : undefined; + let routesToUse = inFlightDataRoutes || dataRoutes; + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're + // about to reload. Note that if this is an action reload we would have + // already cancelled all pending deferreds so this would be a no-op + + cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run + + if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) { + completeNavigation(location, _extends({ + matches, + loaderData: {}, + // Commit pending error if we're short circuiting + errors: pendingError || null + }, pendingActionData ? { + actionData: pendingActionData + } : {})); + return { + shortCircuited: true + }; + } // If this is an uninterrupted revalidation, we remain in our current idle + // state. If not, we need to switch to our loading state and load data, + // preserving any new action data or existing action data (in the case of + // a revalidation interrupting an actionReload) + + + if (!isUninterruptedRevalidation) { + revalidatingFetchers.forEach(rf => { + let fetcher = state.fetchers.get(rf.key); + let revalidatingFetcher = { + state: "loading", + data: fetcher && fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(rf.key, revalidatingFetcher); + }); + let actionData = pendingActionData || state.actionData; + updateState(_extends({ + navigation: loadingNavigation + }, actionData ? Object.keys(actionData).length === 0 ? { + actionData: null + } : { + actionData + } : {}, revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {})); + } + + pendingNavigationLoadId = ++incrementingLoadId; + revalidatingFetchers.forEach(rf => fetchControllers.set(rf.key, pendingNavigationController)); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } // Clean up _after_ loaders have completed. Don't clean up if we short + // circuited because fetchControllers would have been aborted and + // reassigned to new controllers for the next navigation + + + revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key)); // If any loaders returned a redirect Response, start a new REPLACE navigation + + let redirect = findRedirect(results); + + if (redirect) { + await startRedirectNavigation(state, redirect, { + replace + }); + return { + shortCircuited: true + }; + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle + + activeDeferreds.forEach((deferredData, routeId) => { + deferredData.subscribe(aborted => { + // Note: No need to updateState here since the TrackedPromise on + // loaderData is stable across resolve/reject + // Remove this instance if we were aborted or if promises have settled + if (aborted || deferredData.done) { + activeDeferreds.delete(routeId); + } + }); + }); + markFetchRedirectsDone(); + let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId); + return _extends({ + loaderData, + errors + }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {}); + } + + function getFetcher(key) { + return state.fetchers.get(key) || IDLE_FETCHER; + } // Trigger a fetcher load/submit for the given fetcher key + + + function fetch(key, routeId, href, opts) { + if (isServer) { + throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback."); + } + + if (fetchControllers.has(key)) abortFetcher(key); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = matchRoutes(routesToUse, href, init.basename); + + if (!matches) { + setFetcherError(key, routeId, getInternalRouterError(404, { + pathname: href + })); + return; + } + + let { + path, + submission + } = normalizeNavigateOptions(href, future, opts, true); + let match = getTargetMatch(matches, path); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + + if (submission && isMutationMethod(submission.formMethod)) { + handleFetcherAction(key, routeId, path, match, matches, submission); + return; + } // Store off the match so we can call it's shouldRevalidate on subsequent + // revalidations + + + fetchLoadMatches.set(key, { + routeId, + path + }); + handleFetcherLoader(key, routeId, path, match, matches, submission); + } // Call the action for the matched fetcher.submit(), and then handle redirects, + // errors, and revalidation + + + async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) { + interruptActiveLoads(); + fetchLoadMatches.delete(key); + + if (!match.route.action && !match.route.lazy) { + let error = getInternalRouterError(405, { + method: submission.formMethod, + pathname: path, + routeId: routeId + }); + setFetcherError(key, routeId, error); + return; + } // Put this fetcher into it's submitting state + + + let existingFetcher = state.fetchers.get(key); + + let fetcher = _extends({ + state: "submitting" + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, fetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the action for the fetcher + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission); + fetchControllers.set(key, abortController); + let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, detectErrorBoundary, router.basename); + + if (fetchRequest.signal.aborted) { + // We can delete this so long as we weren't aborted by ou our own fetcher + // re-submit which would have put _new_ controller is in fetchControllers + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + return; + } + + if (isRedirectResult(actionResult)) { + fetchControllers.delete(key); + fetchRedirectIds.add(key); + + let loadingFetcher = _extends({ + state: "loading" + }, submission, { + data: undefined, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + return startRedirectNavigation(state, actionResult, { + submission, + isFetchActionRedirect: true + }); + } // Process any non-redirect errors thrown + + + if (isErrorResult(actionResult)) { + setFetcherError(key, routeId, actionResult.error); + return; + } + + if (isDeferredResult(actionResult)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } // Start the data load for current matches, or the next location if we're + // in the middle of a navigation + + + let nextLocation = state.navigation.location || state.location; + let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches; + invariant(matches, "Didn't find any matches after fetcher action"); + let loadId = ++incrementingLoadId; + fetchReloadIds.set(key, loadId); + + let loadFetcher = _extends({ + state: "loading", + data: actionResult.data + }, submission, { + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadFetcher); + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, { + [match.route.id]: actionResult.data + }, undefined // No need to send through errors since we short circuit above + ); // Put all revalidating fetchers into the loading state, except for the + // current fetcher which we want to keep in it's current loading state which + // contains it's action submission info + action data + + revalidatingFetchers.filter(rf => rf.key !== key).forEach(rf => { + let staleKey = rf.key; + let existingFetcher = state.fetchers.get(staleKey); + let revalidatingFetcher = { + state: "loading", + data: existingFetcher && existingFetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(staleKey, revalidatingFetcher); + fetchControllers.set(staleKey, abortController); + }); + updateState({ + fetchers: new Map(state.fetchers) + }); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest); + + if (abortController.signal.aborted) { + return; + } + + fetchReloadIds.delete(key); + fetchControllers.delete(key); + revalidatingFetchers.forEach(r => fetchControllers.delete(r.key)); + let redirect = findRedirect(results); + + if (redirect) { + return startRedirectNavigation(state, redirect); + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds); + let doneFetcher = { + state: "idle", + data: actionResult.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is + // more recent than the navigation, we want the newer data so abort the + // navigation and complete it with the fetcher data + + if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) { + invariant(pendingAction, "Expected pending action"); + pendingNavigationController && pendingNavigationController.abort(); + completeNavigation(state.navigation.location, { + matches, + loaderData, + errors, + fetchers: new Map(state.fetchers) + }); + } else { + // otherwise just update with the fetcher data, preserving any existing + // loaderData for loaders that did not need to reload. We have to + // manually merge here since we aren't going through completeNavigation + updateState(_extends({ + errors, + loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors) + }, didAbortFetchLoads ? { + fetchers: new Map(state.fetchers) + } : {})); + isRevalidationRequired = false; + } + } // Call the matched loader for fetcher.load(), handling redirects, errors, etc. + + + async function handleFetcherLoader(key, routeId, path, match, matches, submission) { + let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state + + let loadingFetcher = _extends({ + state: "loading", + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the loader for this fetcher route match + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal); + fetchControllers.set(key, abortController); + let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, detectErrorBoundary, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it + // as a normal load. resolveDeferredData will return undefined if this + // fetcher gets aborted, so we just leave result untouched and short circuit + // below if that happens + + if (isDeferredResult(result)) { + result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result; + } // We can delete this so long as we weren't aborted by ou our own fetcher + // re-load which would have put _new_ controller is in fetchControllers + + + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + if (fetchRequest.signal.aborted) { + return; + } // If the loader threw a redirect Response, start a new REPLACE navigation + + + if (isRedirectResult(result)) { + await startRedirectNavigation(state, result); + return; + } // Process any non-redirect errors thrown + + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch - + // do we need to behave any differently with our non-redirect errors? + // What if it was a non-redirect Response? + + updateState({ + fetchers: new Map(state.fetchers), + errors: { + [boundaryMatch.route.id]: result.error + } + }); + return; + } + + invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state + + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + } + /** + * Utility function to handle redirects returned from an action or loader. + * Normally, a redirect "replaces" the navigation that triggered it. So, for + * example: + * + * - user is on /a + * - user clicks a link to /b + * - loader for /b redirects to /c + * + * In a non-JS app the browser would track the in-flight navigation to /b and + * then replace it with /c when it encountered the redirect response. In + * the end it would only ever update the URL bar with /c. + * + * In client-side routing using pushState/replaceState, we aim to emulate + * this behavior and we also do not update history until the end of the + * navigation (including processed redirects). This means that we never + * actually touch history until we've processed redirects, so we just use + * the history action from the original navigation (PUSH or REPLACE). + */ + + + async function startRedirectNavigation(state, redirect, _temp) { + var _window; + + let { + submission, + replace, + isFetchActionRedirect + } = _temp === void 0 ? {} : _temp; + + if (redirect.revalidate) { + isRevalidationRequired = true; + } + + let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2 + _extends({ + _isRedirect: true + }, isFetchActionRedirect ? { + _isFetchActionRedirect: true + } : {})); + invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an absolute external redirect that goes to a new origin + + if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser && typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") { + let url = init.history.createURL(redirect.location); + let isDifferentBasename = stripBasename(url.pathname, init.basename || "/") == null; + + if (window.location.origin !== url.origin || isDifferentBasename) { + if (replace) { + window.location.replace(redirect.location); + } else { + window.location.assign(redirect.location); + } + + return; + } + } // There's no need to abort on redirects, since we don't detect the + // redirect until the action/loaders have settled + + + pendingNavigationController = null; + let redirectHistoryAction = replace === true ? Action.Replace : Action.Push; // Use the incoming submission if provided, fallback on the active one in + // state.navigation + + let { + formMethod, + formAction, + formEncType, + formData + } = state.navigation; + + if (!submission && formMethod && formAction && formData && formEncType) { + submission = { + formMethod, + formAction, + formEncType, + formData + }; + } // If this was a 307/308 submission we want to preserve the HTTP method and + // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the + // redirected location + + + if (redirectPreserveMethodStatusCodes.has(redirect.status) && submission && isMutationMethod(submission.formMethod)) { + await startNavigation(redirectHistoryAction, redirectLocation, { + submission: _extends({}, submission, { + formAction: redirect.location + }), + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else if (isFetchActionRedirect) { + // For a fetch action redirect, we kick off a new loading navigation + // without the fetcher submission, but we send it along for shouldRevalidate + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, + fetcherSubmission: submission, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else { + // Otherwise, we kick off a new loading navigation, preserving the + // submission info for the duration of this navigation + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: submission ? submission.formMethod : undefined, + formAction: submission ? submission.formAction : undefined, + formEncType: submission ? submission.formEncType : undefined, + formData: submission ? submission.formData : undefined + }, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } + } + + async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) { + // Call all navigation loaders and revalidating fetcher loaders in parallel, + // then slice off the results into separate arrays so we can handle them + // accordingly + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, router.basename)), ...fetchersToLoad.map(f => { + if (f.matches && f.match) { + return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, manifest, detectErrorBoundary, router.basename); + } else { + let error = { + type: ResultType.error, + error: getInternalRouterError(404, { + pathname: f.path + }) + }; + return error; + } + })]); + let loaderResults = results.slice(0, matchesToLoad.length); + let fetcherResults = results.slice(matchesToLoad.length); + await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]); + return { + results, + loaderResults, + fetcherResults + }; + } + + function interruptActiveLoads() { + // Every interruption triggers a revalidation + isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for + // revalidation + + cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads + + fetchLoadMatches.forEach((_, key) => { + if (fetchControllers.has(key)) { + cancelledFetcherLoads.push(key); + abortFetcher(key); + } + }); + } + + function setFetcherError(key, routeId, error) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + deleteFetcher(key); + updateState({ + errors: { + [boundaryMatch.route.id]: error + }, + fetchers: new Map(state.fetchers) + }); + } + + function deleteFetcher(key) { + if (fetchControllers.has(key)) abortFetcher(key); + fetchLoadMatches.delete(key); + fetchReloadIds.delete(key); + fetchRedirectIds.delete(key); + state.fetchers.delete(key); + } + + function abortFetcher(key) { + let controller = fetchControllers.get(key); + invariant(controller, "Expected fetch controller: " + key); + controller.abort(); + fetchControllers.delete(key); + } + + function markFetchersDone(keys) { + for (let key of keys) { + let fetcher = getFetcher(key); + let doneFetcher = { + state: "idle", + data: fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + function markFetchRedirectsDone() { + let doneKeys = []; + + for (let key of fetchRedirectIds) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + fetchRedirectIds.delete(key); + doneKeys.push(key); + } + } + + markFetchersDone(doneKeys); + } + + function abortStaleFetchLoads(landedId) { + let yeetedKeys = []; + + for (let [key, id] of fetchReloadIds) { + if (id < landedId) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + abortFetcher(key); + fetchReloadIds.delete(key); + yeetedKeys.push(key); + } + } + } + + markFetchersDone(yeetedKeys); + return yeetedKeys.length > 0; + } + + function getBlocker(key, fn) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + + if (blockerFunctions.get(key) !== fn) { + blockerFunctions.set(key, fn); + } + + return blocker; + } + + function deleteBlocker(key) { + state.blockers.delete(key); + blockerFunctions.delete(key); + } // Utility function to update blockers, ensuring valid state transitions + + + function updateBlocker(key, newBlocker) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; // Poor mans state machine :) + // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM + + invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state); + state.blockers.set(key, newBlocker); + updateState({ + blockers: new Map(state.blockers) + }); + } + + function shouldBlockNavigation(_ref2) { + let { + currentLocation, + nextLocation, + historyAction + } = _ref2; + + if (blockerFunctions.size === 0) { + return; + } // We ony support a single active blocker at the moment since we don't have + // any compelling use cases for multi-blocker yet + + + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); + + if (blocker && blocker.state === "proceeding") { + // If the blocker is currently proceeding, we don't need to re-check + // it and can let this navigation continue + return; + } // At this point, we know we're unblocked/blocked so we need to check the + // user-provided blocker function + + + if (blockerFunction({ + currentLocation, + nextLocation, + historyAction + })) { + return blockerKey; + } + } + + function cancelActiveDeferreds(predicate) { + let cancelledRouteIds = []; + activeDeferreds.forEach((dfd, routeId) => { + if (!predicate || predicate(routeId)) { + // Cancel the deferred - but do not remove from activeDeferreds here - + // we rely on the subscribers to do that so our tests can assert proper + // cleanup via _internalActiveDeferreds + dfd.cancel(); + cancelledRouteIds.push(routeId); + activeDeferreds.delete(routeId); + } + }); + return cancelledRouteIds; + } // Opt in to capturing and reporting scroll positions during navigations, + // used by the component + + + function enableScrollRestoration(positions, getPosition, getKey) { + savedScrollPositions = positions; + getScrollPosition = getPosition; + + getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on + // the initial updateState() because we've not yet rendered + // and therefore have no savedScrollPositions available + + + if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) { + initialScrollRestored = true; + let y = getSavedScrollPosition(state.location, state.matches); + + if (y != null) { + updateState({ + restoreScrollPosition: y + }); + } + } + + return () => { + savedScrollPositions = null; + getScrollPosition = null; + getScrollRestorationKey = null; + }; + } + + function saveScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + savedScrollPositions[key] = getScrollPosition(); + } + } + + function getSavedScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + let y = savedScrollPositions[key]; + + if (typeof y === "number") { + return y; + } + } + + return null; + } + + function _internalSetRoutes(newRoutes) { + inFlightDataRoutes = newRoutes; + } + + router = { + get basename() { + return init.basename; + }, + + get state() { + return state; + }, + + get routes() { + return dataRoutes; + }, + + initialize, + subscribe, + enableScrollRestoration, + navigate, + fetch, + revalidate, + // Passthrough to history-aware createHref used by useHref so we get proper + // hash-aware URLs in DOM paths + createHref: to => init.history.createHref(to), + encodeLocation: to => init.history.encodeLocation(to), + getFetcher, + deleteFetcher, + dispose, + getBlocker, + deleteBlocker, + _internalFetchControllers: fetchControllers, + _internalActiveDeferreds: activeDeferreds, + // TODO: Remove setRoutes, it's temporary to avoid dealing with + // updating the tree while validating the update algorithm. + _internalSetRoutes + }; + return router; +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region createStaticHandler +//////////////////////////////////////////////////////////////////////////////// + +const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred"); +function createStaticHandler(routes, opts) { + invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler"); + let manifest = {}; + let detectErrorBoundary = (opts == null ? void 0 : opts.detectErrorBoundary) || defaultDetectErrorBoundary; + let dataRoutes = convertRoutesToDataRoutes(routes, detectErrorBoundary, undefined, manifest); + let basename = (opts ? opts.basename : null) || "/"; + /** + * The query() method is intended for document requests, in which we want to + * call an optional action and potentially multiple loaders for all nested + * routes. It returns a StaticHandlerContext object, which is very similar + * to the router state (location, loaderData, actionData, errors, etc.) and + * also adds SSR-specific information such as the statusCode and headers + * from action/loaders Responses. + * + * It _should_ never throw and should report all errors through the + * returned context.errors object, properly associating errors to their error + * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be + * used to emulate React error boundaries during SSr by performing a second + * pass only down to the boundaryId. + * + * The one exception where we do not return a StaticHandlerContext is when a + * redirect response is returned or thrown from any action/loader. We + * propagate that out and return the raw Response so the HTTP server can + * return it directly. + */ + + async function query(request, _temp2) { + let { + requestContext + } = _temp2 === void 0 ? {} : _temp2; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD") { + let error = getInternalRouterError(405, { + method + }); + let { + matches: methodNotAllowedMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: methodNotAllowedMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } else if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: notFoundMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + let result = await queryImpl(request, location, matches, requestContext); + + if (isResponse(result)) { + return result; + } // When returning StaticHandlerContext, we patch back in the location here + // since we need it for React Context. But this helps keep our submit and + // loadRouteData operating on a Request instead of a Location + + + return _extends({ + location, + basename + }, result); + } + /** + * The queryRoute() method is intended for targeted route requests, either + * for fetch ?_data requests or resource route requests. In this case, we + * are only ever calling a single action or loader, and we are returning the + * returned value directly. In most cases, this will be a Response returned + * from the action/loader, but it may be a primitive or other value as well - + * and in such cases the calling context should handle that accordingly. + * + * We do respect the throw/return differentiation, so if an action/loader + * throws, then this method will throw the value. This is important so we + * can do proper boundary identification in Remix where a thrown Response + * must go to the Catch Boundary but a returned Response is happy-path. + * + * One thing to note is that any Router-initiated Errors that make sense + * to associate with a status code will be thrown as an ErrorResponse + * instance which include the raw Error, such that the calling context can + * serialize the error as they see fit while including the proper response + * code. Examples here are 404 and 405 errors that occur prior to reaching + * any user-defined loaders. + */ + + + async function queryRoute(request, _temp3) { + let { + routeId, + requestContext + } = _temp3 === void 0 ? {} : _temp3; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") { + throw getInternalRouterError(405, { + method + }); + } else if (!matches) { + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location); + + if (routeId && !match) { + throw getInternalRouterError(403, { + pathname: location.pathname, + routeId + }); + } else if (!match) { + // This should never hit I don't think? + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let result = await queryImpl(request, location, matches, requestContext, match); + + if (isResponse(result)) { + return result; + } + + let error = result.errors ? Object.values(result.errors)[0] : undefined; + + if (error !== undefined) { + // If we got back result.errors, that means the loader/action threw + // _something_ that wasn't a Response, but it's not guaranteed/required + // to be an `instanceof Error` either, so we have to use throw here to + // preserve the "error" state outside of queryImpl. + throw error; + } // Pick off the right state value to return + + + if (result.actionData) { + return Object.values(result.actionData)[0]; + } + + if (result.loaderData) { + var _result$activeDeferre; + + let data = Object.values(result.loaderData)[0]; + + if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) { + data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id]; + } + + return data; + } + + return undefined; + } + + async function queryImpl(request, location, matches, requestContext, routeMatch) { + invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal"); + + try { + if (isMutationMethod(request.method.toLowerCase())) { + let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null); + return result; + } + + let result = await loadRouteData(request, matches, requestContext, routeMatch); + return isResponse(result) ? result : _extends({}, result, { + actionData: null, + actionHeaders: {} + }); + } catch (e) { + // If the user threw/returned a Response in callLoaderOrAction, we throw + // it to bail out and then return or throw here based on whether the user + // returned or threw + if (isQueryRouteResponse(e)) { + if (e.type === ResultType.error && !isRedirectResponse(e.response)) { + throw e.response; + } + + return e.response; + } // Redirects are always returned since they don't propagate to catch + // boundaries + + + if (isRedirectResponse(e)) { + return e; + } + + throw e; + } + } + + async function submit(request, matches, actionMatch, requestContext, isRouteRequest) { + let result; + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + let error = getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: actionMatch.route.id + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } + } + + if (isRedirectResult(result)) { + // Uhhhh - this should never happen, we should always throw these from + // callLoaderOrAction, but the type narrowing here keeps TS happy and we + // can get back on the "throw all redirect responses" train here should + // this ever happen :/ + throw new Response(null, { + status: result.status, + headers: { + Location: result.location + } + }); + } + + if (isDeferredResult(result)) { + let error = getInternalRouterError(400, { + type: "defer-action" + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } + + if (isRouteRequest) { + // Note: This should only be non-Response values if we get here, since + // isRouteRequest should throw any Response received in callLoaderOrAction + if (isErrorResult(result)) { + throw result.error; + } + + return { + matches: [actionMatch], + loaderData: {}, + actionData: { + [actionMatch.route.id]: result.data + }, + errors: null, + // Note: statusCode + headers are unused here since queryRoute will + // return the raw Response or value + statusCode: 200, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + let context = await loadRouteData(request, matches, requestContext, undefined, { + [boundaryMatch.route.id]: result.error + }); // action status codes take precedence over loader status codes + + return _extends({}, context, { + statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500, + actionData: null, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } // Create a GET request for the loaders + + + let loaderRequest = new Request(request.url, { + headers: request.headers, + redirect: request.redirect, + signal: request.signal + }); + let context = await loadRouteData(loaderRequest, matches, requestContext); + return _extends({}, context, result.statusCode ? { + statusCode: result.statusCode + } : {}, { + actionData: { + [actionMatch.route.id]: result.data + }, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } + + async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) { + let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute()) + + if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader) && !(routeMatch != null && routeMatch.route.lazy)) { + throw getInternalRouterError(400, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: routeMatch == null ? void 0 : routeMatch.route.id + }); + } + + let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]); + let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy); // Short circuit if we have no loaders to run (query()) + + if (matchesToLoad.length === 0) { + return { + matches, + // Add a null for all matched routes for proper revalidation on the client + loaderData: matches.reduce((acc, m) => Object.assign(acc, { + [m.route.id]: null + }), {}), + errors: pendingActionError || null, + statusCode: 200, + loaderHeaders: {}, + activeDeferreds: null + }; + } + + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext))]); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } // Process and commit output from loaders + + + let activeDeferreds = new Map(); + let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client + + let executedLoaders = new Set(matchesToLoad.map(match => match.route.id)); + matches.forEach(match => { + if (!executedLoaders.has(match.route.id)) { + context.loaderData[match.route.id] = null; + } + }); + return _extends({}, context, { + matches, + activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null + }); + } + + return { + dataRoutes, + query, + queryRoute + }; +} //#endregion +//////////////////////////////////////////////////////////////////////////////// +//#region Helpers +//////////////////////////////////////////////////////////////////////////////// + +/** + * Given an existing StaticHandlerContext and an error thrown at render time, + * provide an updated StaticHandlerContext suitable for a second SSR render + */ + +function getStaticContextFromError(routes, context, error) { + let newContext = _extends({}, context, { + statusCode: 500, + errors: { + [context._deepestRenderedBoundaryId || routes[0].id]: error + } + }); + + return newContext; +} + +function isSubmissionNavigation(opts) { + return opts != null && "formData" in opts; +} // Normalize navigation options by converting formMethod=GET formData objects to +// URLSearchParams so they behave identically to links with query params + + +function normalizeNavigateOptions(to, future, opts, isFetcher) { + if (isFetcher === void 0) { + isFetcher = false; + } + + let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations + + if (!opts || !isSubmissionNavigation(opts)) { + return { + path + }; + } + + if (opts.formMethod && !isValidMethod(opts.formMethod)) { + return { + path, + error: getInternalRouterError(405, { + method: opts.formMethod + }) + }; + } // Create a Submission on non-GET navigations + + + let submission; + + if (opts.formData) { + let formMethod = opts.formMethod || "get"; + submission = { + formMethod: future.v7_normalizeFormMethod ? formMethod.toUpperCase() : formMethod.toLowerCase(), + formAction: stripHashFromPath(path), + formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded", + formData: opts.formData + }; + + if (isMutationMethod(submission.formMethod)) { + return { + path, + submission + }; + } + } // Flatten submission onto URLSearchParams for GET submissions + + + let parsedPath = parsePath(path); + let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to + // navigation GET submissions which run all loaders), we need to preserve + // any incoming ?index params + + if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { + searchParams.append("index", ""); + } + + parsedPath.search = "?" + searchParams; + return { + path: createPath(parsedPath), + submission + }; +} // Filter out all routes below any caught error as they aren't going to +// render so we don't need to load them + + +function getLoaderMatchesUntilBoundary(matches, boundaryId) { + let boundaryMatches = matches; + + if (boundaryId) { + let index = matches.findIndex(m => m.route.id === boundaryId); + + if (index >= 0) { + boundaryMatches = matches.slice(0, index); + } + } + + return boundaryMatches; +} + +function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) { + let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; + let currentUrl = history.createURL(state.location); + let nextUrl = history.createURL(location); + let defaultShouldRevalidate = // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate + isRevalidationRequired || // Clicked the same link, resubmitted a GET form + currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders + currentUrl.search !== nextUrl.search; // Pick navigation matches that are net-new or qualify for revalidation + + let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined; + let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId); + let navigationMatches = boundaryMatches.filter((match, index) => { + if (match.route.lazy) { + // We haven't loaded this route yet so we don't know if it's got a loader! + return true; + } + + if (match.route.loader == null) { + return false; + } // Always call the loader on new route instances and pending defer cancellations + + + if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) { + return true; + } // This is the default implementation for when we revalidate. If the route + // provides it's own implementation, then we give them full control but + // provide this value so they can leverage it if needed after they check + // their own specific use cases + + + let currentRouteMatch = state.matches[index]; + let nextRouteMatch = match; + return shouldRevalidateLoader(match, _extends({ + currentUrl, + currentParams: currentRouteMatch.params, + nextUrl, + nextParams: nextRouteMatch.params + }, submission, { + actionResult, + defaultShouldRevalidate: defaultShouldRevalidate || isNewRouteInstance(currentRouteMatch, nextRouteMatch) + })); + }); // Pick fetcher.loads that need to be revalidated + + let revalidatingFetchers = []; + fetchLoadMatches.forEach((f, key) => { + // Don't revalidate if fetcher won't be present in the subsequent render + if (!matches.some(m => m.route.id === f.routeId)) { + return; + } + + let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so + // we can trigger a 404 in callLoadersAndMaybeResolveData + + if (!fetcherMatches) { + revalidatingFetchers.push(_extends({ + key + }, f, { + matches: null, + match: null + })); + return; + } + + let fetcherMatch = getTargetMatch(fetcherMatches, f.path); + + if (cancelledFetcherLoads.includes(key)) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + return; + } // Revalidating fetchers are decoupled from the route matches since they + // hit a static href, so they _always_ check shouldRevalidate and the + // default is strictly if a revalidation is explicitly required (action + // submissions, useRevalidator, X-Remix-Revalidate). + + + let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({ + currentUrl, + currentParams: state.matches[state.matches.length - 1].params, + nextUrl, + nextParams: matches[matches.length - 1].params + }, submission, { + actionResult, + defaultShouldRevalidate + })); + + if (shouldRevalidate) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + } + }); + return [navigationMatches, revalidatingFetchers]; +} + +function isNewLoader(currentLoaderData, currentMatch, match) { + let isNew = // [a] -> [a, b] + !currentMatch || // [a, b] -> [a, c] + match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially + // from a prior error or from a cancelled pending deferred + + let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data + + return isNew || isMissingData; +} + +function isNewRouteInstance(currentMatch, match) { + let currentPath = currentMatch.route.path; + return (// param change for this match, /users/123 -> /users/456 + currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path + // e.g. /files/images/avatar.jpg -> files/finances.xls + currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"] + ); +} + +function shouldRevalidateLoader(loaderMatch, arg) { + if (loaderMatch.route.shouldRevalidate) { + let routeChoice = loaderMatch.route.shouldRevalidate(arg); + + if (typeof routeChoice === "boolean") { + return routeChoice; + } + } + + return arg.defaultShouldRevalidate; +} +/** + * Execute route.lazy() methods to lazily load route modules (loader, action, + * shouldRevalidate) and update the routeManifest in place which shares objects + * with dataRoutes so those get updated as well. + */ + + +async function loadLazyRouteModule(route, detectErrorBoundary, manifest) { + if (!route.lazy) { + return; + } + + let lazyRoute = await route.lazy(); // If the lazy route function was executed and removed by another parallel + // call then we can return - first lazy() to finish wins because the return + // value of lazy is expected to be static + + if (!route.lazy) { + return; + } + + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); // Update the route in place. This should be safe because there's no way + // we could yet be sitting on this route as we can't get there without + // resolving lazy() first. + // + // This is different than the HMR "update" use-case where we may actively be + // on the route being updated. The main concern boils down to "does this + // mutation affect any ongoing navigations or any current state.matches + // values?". If not, it should be safe to update in place. + + let routeUpdates = {}; + + for (let lazyRouteProperty in lazyRoute) { + let staticRouteValue = routeToUpdate[lazyRouteProperty]; + let isPropertyStaticallyDefined = staticRouteValue !== undefined && // This property isn't static since it should always be updated based + // on the route updates + lazyRouteProperty !== "hasErrorBoundary"; + warning(!isPropertyStaticallyDefined, "Route \"" + routeToUpdate.id + "\" has a static property \"" + lazyRouteProperty + "\" " + "defined but its lazy function is also returning a value for this property. " + ("The lazy route property \"" + lazyRouteProperty + "\" will be ignored.")); + + if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) { + routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty]; + } + } // Mutate the route with the provided updates. Do this first so we pass + // the updated version to detectErrorBoundary + + + Object.assign(routeToUpdate, routeUpdates); // Mutate the `hasErrorBoundary` property on the route based on the route + // updates and remove the `lazy` function so we don't resolve the lazy + // route again. + + Object.assign(routeToUpdate, { + // To keep things framework agnostic, we use the provided + // `detectErrorBoundary` function to set the `hasErrorBoundary` route + // property since the logic will differ between frameworks. + hasErrorBoundary: detectErrorBoundary(_extends({}, routeToUpdate)), + lazy: undefined + }); +} + +async function callLoaderOrAction(type, request, match, matches, manifest, detectErrorBoundary, basename, isStaticRequest, isRouteRequest, requestContext) { + if (basename === void 0) { + basename = "/"; + } + + if (isStaticRequest === void 0) { + isStaticRequest = false; + } + + if (isRouteRequest === void 0) { + isRouteRequest = false; + } + + let resultType; + let result; + let onReject; + + let runHandler = handler => { + // Setup a promise we can race against so that abort signals short circuit + let reject; + let abortPromise = new Promise((_, r) => reject = r); + + onReject = () => reject(); + + request.signal.addEventListener("abort", onReject); + return Promise.race([handler({ + request, + params: match.params, + context: requestContext + }), abortPromise]); + }; + + try { + let handler = match.route[type]; + + if (match.route.lazy) { + if (handler) { + // Run statically defined handler in parallel with lazy() + let values = await Promise.all([runHandler(handler), loadLazyRouteModule(match.route, detectErrorBoundary, manifest)]); + result = values[0]; + } else { + // Load lazy route module, then run any returned handler + await loadLazyRouteModule(match.route, detectErrorBoundary, manifest); + handler = match.route[type]; + + if (handler) { + // Handler still run even if we got interrupted to maintain consistency + // with un-abortable behavior of handler execution on non-lazy or + // previously-lazy-loaded routes + result = await runHandler(handler); + } else if (type === "action") { + throw getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: match.route.id + }); + } else { + // lazy() route has no loader to run. Short circuit here so we don't + // hit the invariant below that errors on returning undefined. + return { + type: ResultType.data, + data: undefined + }; + } + } + } else { + invariant(handler, "Could not find the " + type + " to run on the \"" + match.route.id + "\" route"); + result = await runHandler(handler); + } + + invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`."); + } catch (e) { + resultType = ResultType.error; + result = e; + } finally { + if (onReject) { + request.signal.removeEventListener("abort", onReject); + } + } + + if (isResponse(result)) { + let status = result.status; // Process redirects + + if (redirectStatusCodes.has(status)) { + let location = result.headers.get("Location"); + invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header"); // Support relative routing in internal redirects + + if (!ABSOLUTE_URL_REGEX.test(location)) { + let activeMatches = matches.slice(0, matches.indexOf(match) + 1); + let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase); + let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname); + invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + location); // Prepend the basename to the redirect location if we have one + + if (basename) { + let path = resolvedLocation.pathname; + resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]); + } + + location = createPath(resolvedLocation); + } else if (!isStaticRequest) { + // Strip off the protocol+origin for same-origin + same-basename absolute + // redirects. If this is a static request, we can let it go back to the + // browser as-is + let currentUrl = new URL(request.url); + let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location); + let isSameBasename = stripBasename(url.pathname, basename) != null; + + if (url.origin === currentUrl.origin && isSameBasename) { + location = url.pathname + url.search + url.hash; + } + } // Don't process redirects in the router during static requests requests. + // Instead, throw the Response and let the server handle it with an HTTP + // redirect. We also update the Location header in place in this flow so + // basename and relative routing is taken into account + + + if (isStaticRequest) { + result.headers.set("Location", location); + throw result; + } + + return { + type: ResultType.redirect, + status, + location, + revalidate: result.headers.get("X-Remix-Revalidate") !== null + }; + } // For SSR single-route requests, we want to hand Responses back directly + // without unwrapping. We do this with the QueryRouteResponse wrapper + // interface so we can know whether it was returned or thrown + + + if (isRouteRequest) { + // eslint-disable-next-line no-throw-literal + throw { + type: resultType || ResultType.data, + response: result + }; + } + + let data; + let contentType = result.headers.get("Content-Type"); // Check between word boundaries instead of startsWith() due to the last + // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type + + if (contentType && /\bapplication\/json\b/.test(contentType)) { + data = await result.json(); + } else { + data = await result.text(); + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: new ErrorResponse(status, result.statusText, data), + headers: result.headers + }; + } + + return { + type: ResultType.data, + data, + statusCode: result.status, + headers: result.headers + }; + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: result + }; + } + + if (isDeferredData(result)) { + var _result$init, _result$init2; + + return { + type: ResultType.deferred, + deferredData: result, + statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status, + headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers) + }; + } + + return { + type: ResultType.data, + data: result + }; +} // Utility method for creating the Request instances for loaders/actions during +// client-side navigations and fetches. During SSR we will always have a +// Request instance from the static handler (query/queryRoute) + + +function createClientSideRequest(history, location, signal, submission) { + let url = history.createURL(stripHashFromPath(location)).toString(); + let init = { + signal + }; + + if (submission && isMutationMethod(submission.formMethod)) { + let { + formMethod, + formEncType, + formData + } = submission; // Didn't think we needed this but it turns out unlike other methods, patch + // won't be properly normalized to uppercase and results in a 405 error. + // See: https://fetch.spec.whatwg.org/#concept-method + + init.method = formMethod.toUpperCase(); + init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData; + } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request) + + + return new Request(url, init); +} + +function convertFormDataToSearchParams(formData) { + let searchParams = new URLSearchParams(); + + for (let [key, value] of formData.entries()) { + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs + searchParams.append(key, value instanceof File ? value.name : value); + } + + return searchParams; +} + +function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) { + // Fill in loaderData/errors from our loaders + let loaderData = {}; + let errors = null; + let statusCode; + let foundError = false; + let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors + + results.forEach((result, index) => { + let id = matchesToLoad[index].route.id; + invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData"); + + if (isErrorResult(result)) { + // Look upwards from the matched route for the closest ancestor + // error boundary, defaulting to the root match + let boundaryMatch = findNearestBoundary(matches, id); + let error = result.error; // If we have a pending action error, we report it at the highest-route + // that throws a loader error, and then clear it out to indicate that + // it was consumed + + if (pendingError) { + error = Object.values(pendingError)[0]; + pendingError = undefined; + } + + errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary + + if (errors[boundaryMatch.route.id] == null) { + errors[boundaryMatch.route.id] = error; + } // Clear our any prior loaderData for the throwing route + + + loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and + // prevent deeper status codes from overriding + + if (!foundError) { + foundError = true; + statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } else { + if (isDeferredResult(result)) { + activeDeferreds.set(id, result.deferredData); + loaderData[id] = result.deferredData.data; + } else { + loaderData[id] = result.data; + } // Error status codes always override success status codes, but if all + // loaders are successful we take the deepest status code. + + + if (result.statusCode != null && result.statusCode !== 200 && !foundError) { + statusCode = result.statusCode; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } + }); // If we didn't consume the pending action error (i.e., all loaders + // resolved), then consume it here. Also clear out any loaderData for the + // throwing route + + if (pendingError) { + errors = pendingError; + loaderData[Object.keys(pendingError)[0]] = undefined; + } + + return { + loaderData, + errors, + statusCode: statusCode || 200, + loaderHeaders + }; +} + +function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) { + let { + loaderData, + errors + } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers + + for (let index = 0; index < revalidatingFetchers.length; index++) { + let { + key, + match + } = revalidatingFetchers[index]; + invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result"); + let result = fetcherResults[index]; // Process fetcher non-redirect errors + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id); + + if (!(errors && errors[boundaryMatch.route.id])) { + errors = _extends({}, errors, { + [boundaryMatch.route.id]: result.error + }); + } + + state.fetchers.delete(key); + } else if (isRedirectResult(result)) { + // Should never get here, redirects should get processed above, but we + // keep this to type narrow to a success result in the else + invariant(false, "Unhandled fetcher revalidation redirect"); + } else if (isDeferredResult(result)) { + // Should never get here, deferred data should be awaited for fetchers + // in resolveDeferredResults + invariant(false, "Unhandled fetcher deferred data"); + } else { + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + return { + loaderData, + errors + }; +} + +function mergeLoaderData(loaderData, newLoaderData, matches, errors) { + let mergedLoaderData = _extends({}, newLoaderData); + + for (let match of matches) { + let id = match.route.id; + + if (newLoaderData.hasOwnProperty(id)) { + if (newLoaderData[id] !== undefined) { + mergedLoaderData[id] = newLoaderData[id]; + } + } else if (loaderData[id] !== undefined && match.route.loader) { + // Preserve existing keys not included in newLoaderData and where a loader + // wasn't removed by HMR + mergedLoaderData[id] = loaderData[id]; + } + + if (errors && errors.hasOwnProperty(id)) { + // Don't keep any loader data below the boundary + break; + } + } + + return mergedLoaderData; +} // Find the nearest error boundary, looking upwards from the leaf route (or the +// route specified by routeId) for the closest ancestor error boundary, +// defaulting to the root match + + +function findNearestBoundary(matches, routeId) { + let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches]; + return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0]; +} + +function getShortCircuitMatches(routes) { + // Prefer a root layout route if present, otherwise shim in a route object + let route = routes.find(r => r.index || !r.path || r.path === "/") || { + id: "__shim-error-route__" + }; + return { + matches: [{ + params: {}, + pathname: "", + pathnameBase: "", + route + }], + route + }; +} + +function getInternalRouterError(status, _temp4) { + let { + pathname, + routeId, + method, + type + } = _temp4 === void 0 ? {} : _temp4; + let statusText = "Unknown Server Error"; + let errorMessage = "Unknown @remix-run/router error"; + + if (status === 400) { + statusText = "Bad Request"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (type === "defer-action") { + errorMessage = "defer() is not supported in actions"; + } + } else if (status === 403) { + statusText = "Forbidden"; + errorMessage = "Route \"" + routeId + "\" does not match URL \"" + pathname + "\""; + } else if (status === 404) { + statusText = "Not Found"; + errorMessage = "No route matches URL \"" + pathname + "\""; + } else if (status === 405) { + statusText = "Method Not Allowed"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (method) { + errorMessage = "Invalid request method \"" + method.toUpperCase() + "\""; + } + } + + return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true); +} // Find any returned redirect errors, starting from the lowest match + + +function findRedirect(results) { + for (let i = results.length - 1; i >= 0; i--) { + let result = results[i]; + + if (isRedirectResult(result)) { + return result; + } + } +} + +function stripHashFromPath(path) { + let parsedPath = typeof path === "string" ? parsePath(path) : path; + return createPath(_extends({}, parsedPath, { + hash: "" + })); +} + +function isHashChangeOnly(a, b) { + return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash; +} + +function isDeferredResult(result) { + return result.type === ResultType.deferred; +} + +function isErrorResult(result) { + return result.type === ResultType.error; +} + +function isRedirectResult(result) { + return (result && result.type) === ResultType.redirect; +} + +function isDeferredData(value) { + let deferred = value; + return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function"; +} + +function isResponse(value) { + return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; +} + +function isRedirectResponse(result) { + if (!isResponse(result)) { + return false; + } + + let status = result.status; + let location = result.headers.get("Location"); + return status >= 300 && status <= 399 && location != null; +} + +function isQueryRouteResponse(obj) { + return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error); +} + +function isValidMethod(method) { + return validRequestMethods.has(method.toLowerCase()); +} + +function isMutationMethod(method) { + return validMutationMethods.has(method.toLowerCase()); +} + +async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) { + for (let index = 0; index < results.length; index++) { + let result = results[index]; + let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do + // anything with. This is for revalidating fetchers where the route was + // removed during HMR + + if (!match) { + continue; + } + + let currentMatch = currentMatches.find(m => m.route.id === match.route.id); + let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined; + + if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) { + // Note: we do not have to touch activeDeferreds here since we race them + // against the signal in resolveDeferredData and they'll get aborted + // there if needed + await resolveDeferredData(result, signal, isFetcher).then(result => { + if (result) { + results[index] = result || results[index]; + } + }); + } + } +} + +async function resolveDeferredData(result, signal, unwrap) { + if (unwrap === void 0) { + unwrap = false; + } + + let aborted = await result.deferredData.resolveData(signal); + + if (aborted) { + return; + } + + if (unwrap) { + try { + return { + type: ResultType.data, + data: result.deferredData.unwrappedData + }; + } catch (e) { + // Handle any TrackedPromise._error values encountered while unwrapping + return { + type: ResultType.error, + error: e + }; + } + } + + return { + type: ResultType.data, + data: result.deferredData.data + }; +} + +function hasNakedIndexQuery(search) { + return new URLSearchParams(search).getAll("index").some(v => v === ""); +} // Note: This should match the format exported by useMatches, so if you change +// this please also change that :) Eventually we'll DRY this up + + +function createUseMatchesMatch(match, loaderData) { + let { + route, + pathname, + params + } = match; + return { + id: route.id, + pathname, + params, + data: loaderData[route.id], + handle: route.handle + }; +} + +function getTargetMatch(matches, location) { + let search = typeof location === "string" ? parsePath(location).search : location.search; + + if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) { + // Return the leaf index route when index is present + return matches[matches.length - 1]; + } // Otherwise grab the deepest "path contributing" match (ignoring index and + // pathless layout routes) + + + let pathMatches = getPathContributingMatches(matches); + return pathMatches[pathMatches.length - 1]; +} //#endregion + +export { AbortedDeferredError, Action, ErrorResponse, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, invariant as UNSAFE_invariant, warning as UNSAFE_warning, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename }; +//# sourceMappingURL=router.js.map diff --git a/node_modules/@remix-run/router/dist/router.js.map b/node_modules/@remix-run/router/dist/router.js.map new file mode 100644 index 00000000..a1c9c0c8 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.js.map @@ -0,0 +1 @@ +{"version":3,"file":"router.js","sources":["../history.ts","../utils.ts","../router.ts"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nexport enum Action {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Pop = \"POP\",\n\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Push = \"PUSH\",\n\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Replace = \"REPLACE\",\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\nexport interface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * An entry in a history stack. A location contains information about the\n * URL path, as well as possibly some arbitrary state and a key.\n */\nexport interface Location extends Path {\n /**\n * A value of arbitrary data associated with this location.\n */\n state: any;\n\n /**\n * A unique string associated with this location. May be used to safely store\n * and retrieve data in some other storage API, like `localStorage`.\n *\n * Note: This value is always \"default\" on the initial location.\n */\n key: string;\n}\n\n/**\n * A change to the current location.\n */\nexport interface Update {\n /**\n * The action that triggered the change.\n */\n action: Action;\n\n /**\n * The new location.\n */\n location: Location;\n\n /**\n * The delta between this location and the former location in the history stack\n */\n delta: number | null;\n}\n\n/**\n * A function that receives notifications about location changes.\n */\nexport interface Listener {\n (update: Update): void;\n}\n\n/**\n * Describes a location that is the destination of some navigation, either via\n * `history.push` or `history.replace`. May be either a URL or the pieces of a\n * URL path.\n */\nexport type To = string | Partial;\n\n/**\n * A history is an interface to the navigation stack. The history serves as the\n * source of truth for the current location, as well as provides a set of\n * methods that may be used to change it.\n *\n * It is similar to the DOM's `window.history` object, but with a smaller, more\n * focused API.\n */\nexport interface History {\n /**\n * The last action that modified the current location. This will always be\n * Action.Pop when a history instance is first created. This value is mutable.\n */\n readonly action: Action;\n\n /**\n * The current location. This value is mutable.\n */\n readonly location: Location;\n\n /**\n * Returns a valid href for the given `to` value that may be used as\n * the value of an attribute.\n *\n * @param to - The destination URL\n */\n createHref(to: To): string;\n\n /**\n * Returns a URL for the given `to` value\n *\n * @param to - The destination URL\n */\n createURL(to: To): URL;\n\n /**\n * Encode a location the same way window.history would do (no-op for memory\n * history) so we ensure our PUSH/REPLACE navigations for data routers\n * behave the same as POP\n *\n * @param to Unencoded path\n */\n encodeLocation(to: To): Path;\n\n /**\n * Pushes a new location onto the history stack, increasing its length by one.\n * If there were any entries in the stack after the current one, they are\n * lost.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n push(to: To, state?: any): void;\n\n /**\n * Replaces the current location in the history stack with a new one. The\n * location that was replaced will no longer be available.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n replace(to: To, state?: any): void;\n\n /**\n * Navigates `n` entries backward/forward in the history stack relative to the\n * current index. For example, a \"back\" navigation would use go(-1).\n *\n * @param delta - The delta in the stack index\n */\n go(delta: number): void;\n\n /**\n * Sets up a listener that will be called whenever the current location\n * changes.\n *\n * @param listener - A function that will be called when the location changes\n * @returns unlisten - A function that may be used to stop listening\n */\n listen(listener: Listener): () => void;\n}\n\ntype HistoryState = {\n usr: any;\n key?: string;\n idx: number;\n};\n\nconst PopStateEventType = \"popstate\";\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Memory History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A user-supplied object that describes a location. Used when providing\n * entries to `createMemoryHistory` via its `initialEntries` option.\n */\nexport type InitialEntry = string | Partial;\n\nexport type MemoryHistoryOptions = {\n initialEntries?: InitialEntry[];\n initialIndex?: number;\n v5Compat?: boolean;\n};\n\n/**\n * A memory history stores locations in memory. This is useful in stateful\n * environments where there is no web browser, such as node tests or React\n * Native.\n */\nexport interface MemoryHistory extends History {\n /**\n * The current index in the history stack.\n */\n readonly index: number;\n}\n\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nexport function createMemoryHistory(\n options: MemoryHistoryOptions = {}\n): MemoryHistory {\n let { initialEntries = [\"/\"], initialIndex, v5Compat = false } = options;\n let entries: Location[]; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) =>\n createMemoryLocation(\n entry,\n typeof entry === \"string\" ? null : entry.state,\n index === 0 ? \"default\" : undefined\n )\n );\n let index = clampIndex(\n initialIndex == null ? entries.length - 1 : initialIndex\n );\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n function clampIndex(n: number): number {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation(): Location {\n return entries[index];\n }\n function createMemoryLocation(\n to: To,\n state: any = null,\n key?: string\n ): Location {\n let location = createLocation(\n entries ? getCurrentLocation().pathname : \"/\",\n to,\n state,\n key\n );\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in memory history: ${JSON.stringify(\n to\n )}`\n );\n return location;\n }\n\n function createHref(to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n let history: MemoryHistory = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to: To) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\",\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 1 });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 0 });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({ action, location: nextLocation, delta });\n }\n },\n listen(fn: Listener) {\n listener = fn;\n return () => {\n listener = null;\n };\n },\n };\n\n return history;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Browser History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A browser history stores the current location in regular URLs in a web\n * browser environment. This is the standard for most web apps and provides the\n * cleanest URLs the browser's address bar.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory\n */\nexport interface BrowserHistory extends UrlHistory {}\n\nexport type BrowserHistoryOptions = UrlHistoryOptions;\n\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nexport function createBrowserHistory(\n options: BrowserHistoryOptions = {}\n): BrowserHistory {\n function createBrowserLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let { pathname, search, hash } = window.location;\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createBrowserHref(window: Window, to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(\n createBrowserLocation,\n createBrowserHref,\n null,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Hash History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A hash history stores the current location in the fragment identifier portion\n * of the URL in a web browser environment.\n *\n * This is ideal for apps that do not control the server for some reason\n * (because the fragment identifier is never sent to the server), including some\n * shared hosting environments that do not provide fine-grained controls over\n * which pages are served at which URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory\n */\nexport interface HashHistory extends UrlHistory {}\n\nexport type HashHistoryOptions = UrlHistoryOptions;\n\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nexport function createHashHistory(\n options: HashHistoryOptions = {}\n): HashHistory {\n function createHashLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createHashHref(window: Window, to: To) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location: Location, to: To) {\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in hash history.push(${JSON.stringify(\n to\n )})`\n );\n }\n\n return getUrlBasedHistory(\n createHashLocation,\n createHashHref,\n validateHashLocation,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region UTILS\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * @private\n */\nexport function invariant(value: boolean, message?: string): asserts value;\nexport function invariant(\n value: T | null | undefined,\n message?: string\n): asserts value is T;\nexport function invariant(value: any, message?: string) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nexport function warning(cond: any, message: string) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location: Location, index: number): HistoryState {\n return {\n usr: location.state,\n key: location.key,\n idx: index,\n };\n}\n\n/**\n * Creates a Location object with a unique key from the given Path\n */\nexport function createLocation(\n current: string | Location,\n to: To,\n state: any = null,\n key?: string\n): Readonly {\n let location: Readonly = {\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\",\n ...(typeof to === \"string\" ? parsePath(to) : to),\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: (to && (to as Location).key) || key || createKey(),\n };\n return location;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial {\n let parsedPath: Partial = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\nexport interface UrlHistory extends History {}\n\nexport type UrlHistoryOptions = {\n window?: Window;\n v5Compat?: boolean;\n};\n\nfunction getUrlBasedHistory(\n getLocation: (window: Window, globalHistory: Window[\"history\"]) => Location,\n createHref: (window: Window, to: To) => string,\n validateLocation: ((location: Location, to: To) => void) | null,\n options: UrlHistoryOptions = {}\n): UrlHistory {\n let { window = document.defaultView!, v5Compat = false } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n let index = getIndex()!;\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState({ ...globalHistory.state, idx: index }, \"\");\n }\n\n function getIndex(): number {\n let state = globalHistory.state || { idx: null };\n return state.idx;\n }\n\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({ action, location: history.location, delta });\n }\n }\n\n function push(to: To, state?: any) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 1 });\n }\n }\n\n function replace(to: To, state?: any) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 0 });\n }\n }\n\n function createURL(to: To): URL {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base =\n window.location.origin !== \"null\"\n ? window.location.origin\n : window.location.href;\n\n let href = typeof to === \"string\" ? to : createPath(to);\n invariant(\n base,\n `No window.location.(origin|href) available to create URL for href: ${href}`\n );\n return new URL(href, base);\n }\n\n let history: History = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn: Listener) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n },\n };\n\n return history;\n}\n\n//#endregion\n","import type { Location, Path, To } from \"./history\";\nimport { warning, invariant, parsePath } from \"./history\";\n\n/**\n * Map of routeId -> data returned from a loader/action/error\n */\nexport interface RouteData {\n [routeId: string]: any;\n}\n\nexport enum ResultType {\n data = \"data\",\n deferred = \"deferred\",\n redirect = \"redirect\",\n error = \"error\",\n}\n\n/**\n * Successful result from a loader or action\n */\nexport interface SuccessResult {\n type: ResultType.data;\n data: any;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Successful defer() result from a loader or action\n */\nexport interface DeferredResult {\n type: ResultType.deferred;\n deferredData: DeferredData;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Redirect result from a loader or action\n */\nexport interface RedirectResult {\n type: ResultType.redirect;\n status: number;\n location: string;\n revalidate: boolean;\n}\n\n/**\n * Unsuccessful result from a loader or action\n */\nexport interface ErrorResult {\n type: ResultType.error;\n error: any;\n headers?: Headers;\n}\n\n/**\n * Result from a loader or action - potentially successful or unsuccessful\n */\nexport type DataResult =\n | SuccessResult\n | DeferredResult\n | RedirectResult\n | ErrorResult;\n\ntype LowerCaseFormMethod = \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\ntype UpperCaseFormMethod = Uppercase;\n\n/**\n * Users can specify either lowercase or uppercase form methods on ,\n * useSubmit(), , etc.\n */\nexport type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;\n\n/**\n * Active navigation/fetcher form methods are exposed in lowercase on the\n * RouterState\n */\nexport type FormMethod = LowerCaseFormMethod;\nexport type MutationFormMethod = Exclude;\n\n/**\n * In v7, active navigation/fetcher form methods are exposed in uppercase on the\n * RouterState. This is to align with the normalization done via fetch().\n */\nexport type V7_FormMethod = UpperCaseFormMethod;\nexport type V7_MutationFormMethod = Exclude;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\";\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n}\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: any;\n}\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Route loader function signature\n */\nexport interface LoaderFunction {\n (args: LoaderFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n formData?: Submission[\"formData\"];\n actionResult?: DataResult;\n defaultShouldRevalidate: boolean;\n }): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set `hasErrorBoundary`\n * from the framework-aware `errorElement` prop\n */\nexport interface DetectErrorBoundaryFunction {\n (route: AgnosticRouteObject): boolean;\n}\n\n/**\n * Keys we cannot change from within a lazy() function. We spread all other keys\n * onto the route. Either they're meaningful to the router, or they'll get\n * ignored.\n */\nexport type ImmutableRouteKey =\n | \"lazy\"\n | \"caseSensitive\"\n | \"path\"\n | \"id\"\n | \"index\"\n | \"children\";\n\nexport const immutableRouteKeys = new Set([\n \"lazy\",\n \"caseSensitive\",\n \"path\",\n \"id\",\n \"index\",\n \"children\",\n]);\n\n/**\n * lazy() function to load a route definition, which can add non-matching\n * related properties to a route\n */\nexport interface LazyRouteFunction {\n (): Promise>;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n lazy?: LazyRouteFunction;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\nexport type RouteManifest = Record;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\ntype PathParam =\n // check if path is just a wildcard\n Path extends \"*\" | \"/*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n detectErrorBoundary: DetectErrorBoundaryFunction,\n parentPath: number[] = [],\n manifest: RouteManifest = {}\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !manifest[id],\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = {\n ...route,\n hasErrorBoundary: detectErrorBoundary(route),\n id,\n };\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n id,\n hasErrorBoundary: detectErrorBoundary(route),\n children: undefined,\n };\n manifest[id] = pathOrLayoutRoute;\n\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(\n route.children,\n detectErrorBoundary,\n treePath,\n manifest\n );\n }\n\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path: string = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n\n const segments = path\n .split(/\\/+/)\n .map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\" as PathParam;\n const starParam = params[star];\n\n // Apply the splat\n return starParam;\n }\n\n const keyMatch = segment.match(/^:(\\w+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key as PathParam];\n\n if (optional === \"?\") {\n return param == null ? \"\" : param;\n }\n\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n\n return param;\n }\n\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter((segment) => !!segment);\n\n return prefix + segments.join(\"/\");\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, paramNames] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = paramNames.reduce>(\n (memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(\n captureGroups[index] || \"\",\n paramName\n );\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, string[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let paramNames: string[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_: string, paramName: string) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, null, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n if (error) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\nexport class ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n error?: Error;\n internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n warning,\n} from \"./history\";\nimport type {\n DataResult,\n DeferredData,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n DeferredResult,\n ErrorResult,\n FormEncType,\n FormMethod,\n DetectErrorBoundaryFunction,\n RedirectResult,\n RouteData,\n AgnosticRouteObject,\n Submission,\n SuccessResult,\n AgnosticRouteMatch,\n ShouldRevalidateFunction,\n RouteManifest,\n ImmutableRouteKey,\n ActionFunction,\n LoaderFunction,\n V7_MutationFormMethod,\n V7_FormMethod,\n HTMLFormMethod,\n MutationFormMethod,\n} from \"./utils\";\nimport {\n ErrorResponse,\n ResultType,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n immutableRouteKeys,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n stripBasename,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterNavigateOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key?: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key?: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * HMR needs to pass in-flight route updates to React Router\n * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)\n */\n _internalSetRoutes(routes: AgnosticRouteObject[]): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface FutureConfig {\n v7_normalizeFormMethod: boolean;\n}\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n routes: AgnosticRouteObject[];\n history: History;\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n future?: FutureConfig;\n hydrationData?: HydrationState;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (state: RouterState): void;\n}\n\ninterface UseMatchesMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: unknown;\n handle: unknown;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UseMatchesMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\n/**\n * Options for a navigate() call for a Link navigation\n */\ntype LinkNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n};\n\n/**\n * Options for a navigate() call for a Form navigation\n */\ntype SubmissionNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n formMethod?: HTMLFormMethod;\n formEncType?: FormEncType;\n formData: FormData;\n};\n\n/**\n * Options to pass to navigate() for either a Link or Form navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions =\n | Omit\n | Omit;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Loading: {\n state: \"loading\";\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n match: AgnosticDataRouteMatch | null;\n matches: AgnosticDataRouteMatch[] | null;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst isBrowser =\n typeof window !== \"undefined\" &&\n typeof window.document !== \"undefined\" &&\n typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser;\n\nconst defaultDetectErrorBoundary = (route: AgnosticRouteObject) =>\n Boolean(route.hasErrorBoundary);\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let detectErrorBoundary =\n init.detectErrorBoundary || defaultDetectErrorBoundary;\n\n // Routes keyed by ID\n let manifest: RouteManifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(\n init.routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined;\n // Config driven behavior flags\n let future: FutureConfig = {\n v7_normalizeFormMethod: false,\n ...init.future,\n };\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(\n dataRoutes,\n init.history.location,\n init.basename\n );\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized =\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n !initialMatches.some((m) => m.route.lazy) &&\n // And we have to either have no loaders or have been provided hydrationData\n (!initialMatches.some((m) => m.route.loader) || init.hydrationData != null);\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations from their actions\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(router.state.blockers) });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location);\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(newState: Partial): void {\n state = {\n ...state,\n ...newState,\n };\n subscribers.forEach((subscriber) => subscriber(state));\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n for (let [key] of blockerFunctions) {\n deleteBlocker(key);\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n\n updateState({\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers: new Map(state.blockers),\n });\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(\n to,\n future,\n opts\n );\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(state.blockers) });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n submission?: Submission;\n fetcherSubmission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponse;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, init.basename);\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n });\n return;\n }\n\n // Short circuit if it's only a hash change and not a mutation submission\n // For example, on /page#hash and submit a which will\n // default to a navigation to /page\n if (\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n ...opts.submission,\n };\n loadingNavigation = navigation;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.fetcherSubmission,\n opts && opts.replace,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts?: { replace?: boolean }\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n ...submission,\n };\n updateState({ navigation });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n fetcherSubmission?: Submission,\n replace?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n if (!loadingNavigation) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n };\n loadingNavigation = navigation;\n }\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission =\n submission || fetcherSubmission\n ? submission || fetcherSubmission\n : loadingNavigation.formMethod &&\n loadingNavigation.formAction &&\n loadingNavigation.formData &&\n loadingNavigation.formEncType\n ? {\n formMethod: loadingNavigation.formMethod,\n formAction: loadingNavigation.formAction,\n formData: loadingNavigation.formData,\n formEncType: loadingNavigation.formEncType,\n }\n : undefined;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n pendingActionData,\n pendingError\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n });\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState({\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n });\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach((rf) =>\n fetchControllers.set(rf.key, pendingNavigationController!)\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n await startRedirectNavigation(state, redirect, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n\n return {\n loaderData,\n errors,\n ...(didAbortFetchLoads || revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n };\n }\n\n function getFetcher(key: string): Fetcher {\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches = matchRoutes(routesToUse, href, init.basename);\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: href })\n );\n return;\n }\n\n let { path, submission } = normalizeNavigateOptions(\n href,\n future,\n opts,\n true\n );\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path });\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action && !match.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error);\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, fetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n ...submission,\n data: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n return startRedirectNavigation(state, actionResult, {\n submission,\n isFetchActionRedirect: true,\n });\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n\n nextLocation,\n abortController.signal\n );\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(routesToUse, state.navigation.location, init.basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: actionResult.data,\n ...submission,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n { [match.route.id]: actionResult.data },\n undefined // No need to send through errors since we short circuit above\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n\n let didAbortFetchLoads = abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n // Put this fetcher into it's loading state\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key);\n // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error,\n },\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n replace,\n isFetchActionRedirect,\n }: {\n submission?: Submission;\n replace?: boolean;\n isFetchActionRedirect?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(\n state.location,\n redirect.location,\n // TODO: This can be removed once we get rid of useTransition in Remix v2\n {\n _isRedirect: true,\n ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}),\n }\n );\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n // Check if this an absolute external redirect that goes to a new origin\n if (\n ABSOLUTE_URL_REGEX.test(redirect.location) &&\n isBrowser &&\n typeof window?.location !== \"undefined\"\n ) {\n let url = init.history.createURL(redirect.location);\n let isDifferentBasename =\n stripBasename(url.pathname, init.basename || \"/\") == null;\n\n if (window.location.origin !== url.origin || isDifferentBasename) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType, formData } = state.navigation;\n if (!submission && formMethod && formAction && formData && formEncType) {\n submission = {\n formMethod,\n formAction,\n formEncType,\n formData,\n };\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n submission &&\n isMutationMethod(submission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...submission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else if (isFetchActionRedirect) {\n // For a fetch action redirect, we kick off a new loading navigation\n // without the fetcher submission, but we send it along for shouldRevalidate\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n },\n fetcherSubmission: submission,\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: submission ? submission.formMethod : undefined,\n formAction: submission ? submission.formAction : undefined,\n formEncType: submission ? submission.formEncType : undefined,\n formData: submission ? submission.formData : undefined,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n )\n ),\n ...fetchersToLoad.map((f) => {\n if (f.matches && f.match) {\n return callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, request.signal),\n f.match,\n f.matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n } else {\n let error: ErrorResult = {\n type: ResultType.error,\n error: getInternalRouterError(404, { pathname: f.path }),\n };\n return error;\n }\n }),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n request.signal,\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n request.signal,\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key: string, routeId: string, error: any) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n });\n }\n\n function deleteFetcher(key: string): void {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): void {\n let doneKeys = [];\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n state.blockers.set(key, newBlocker);\n updateState({ blockers: new Map(state.blockers) });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || ((location) => location.key);\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) {\n inFlightDataRoutes = newRoutes;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\nexport interface CreateStaticHandlerOptions {\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n}\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: CreateStaticHandlerOptions\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let manifest: RouteManifest = {};\n let detectErrorBoundary =\n opts?.detectErrorBoundary || defaultDetectErrorBoundary;\n let dataRoutes = convertRoutesToDataRoutes(\n routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let basename = (opts ? opts.basename : null) || \"/\";\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (\n isRouteRequest &&\n !routeMatch?.route.loader &&\n !routeMatch?.route.lazy\n ) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter(\n (m) => m.route.loader || m.route.lazy\n );\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: RouterNavigateOptions\n): opts is SubmissionNavigateOptions {\n return opts != null && \"formData\" in opts;\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n to: To,\n future: FutureConfig,\n opts?: RouterNavigateOptions,\n isFetcher = false\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponse;\n} {\n let path = typeof to === \"string\" ? to : createPath(to);\n\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n // Create a Submission on non-GET navigations\n let submission: Submission | undefined;\n if (opts.formData) {\n let formMethod = opts.formMethod || \"get\";\n submission = {\n formMethod: future.v7_normalizeFormMethod\n ? (formMethod.toUpperCase() as V7_FormMethod)\n : (formMethod.toLowerCase() as FormMethod),\n formAction: stripHashFromPath(path),\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData: opts.formData,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n let searchParams = convertFormDataToSearchParams(opts.formData);\n // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n fetchLoadMatches: Map,\n routesToUse: AgnosticDataRouteObject[],\n basename: string | undefined,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n let defaultShouldRevalidate =\n // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search;\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n if (match.route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n if (match.route.loader == null) {\n return false;\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n defaultShouldRevalidate ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate if fetcher won't be present in the subsequent render\n if (!matches.some((m) => m.route.id === f.routeId)) {\n return;\n }\n\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData\n if (!fetcherMatches) {\n revalidatingFetchers.push({ key, ...f, matches: null, match: null });\n return;\n }\n\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n\n if (cancelledFetcherLoads.includes(key)) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n return;\n }\n\n // Revalidating fetchers are decoupled from the route matches since they\n // hit a static href, so they _always_ check shouldRevalidate and the\n // default is strictly if a revalidation is explicitly required (action\n // submissions, useRevalidator, X-Remix-Revalidate).\n let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate,\n });\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: Parameters[0]\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(\n route: AgnosticDataRouteObject,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n manifest: RouteManifest\n) {\n if (!route.lazy) {\n return;\n }\n\n let lazyRoute = await route.lazy();\n\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates: Record = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue =\n routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];\n\n let isPropertyStaticallyDefined =\n staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n\n warning(\n !isPropertyStaticallyDefined,\n `Route \"${routeToUpdate.id}\" has a static property \"${lazyRouteProperty}\" ` +\n `defined but its lazy function is also returning a value for this property. ` +\n `The lazy route property \"${lazyRouteProperty}\" will be ignored.`\n );\n\n if (\n !isPropertyStaticallyDefined &&\n !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey)\n ) {\n routeUpdates[lazyRouteProperty] =\n lazyRoute[lazyRouteProperty as keyof typeof lazyRoute];\n }\n }\n\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to detectErrorBoundary\n Object.assign(routeToUpdate, routeUpdates);\n\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, {\n // To keep things framework agnostic, we use the provided\n // `detectErrorBoundary` function to set the `hasErrorBoundary` route\n // property since the logic will differ between frameworks.\n hasErrorBoundary: detectErrorBoundary({ ...routeToUpdate }),\n lazy: undefined,\n });\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n manifest: RouteManifest,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n basename = \"/\",\n isStaticRequest: boolean = false,\n isRouteRequest: boolean = false,\n requestContext?: unknown\n): Promise {\n let resultType;\n let result;\n let onReject: (() => void) | undefined;\n\n let runHandler = (handler: ActionFunction | LoaderFunction) => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n return Promise.race([\n handler({ request, params: match.params, context: requestContext }),\n abortPromise,\n ]);\n };\n\n try {\n let handler = match.route[type];\n\n if (match.route.lazy) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let values = await Promise.all([\n runHandler(handler),\n loadLazyRouteModule(match.route, detectErrorBoundary, manifest),\n ]);\n result = values[0];\n } else {\n // Load lazy route module, then run any returned handler\n await loadLazyRouteModule(match.route, detectErrorBoundary, manifest);\n\n handler = match.route[type];\n if (handler) {\n // Handler still run even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n throw getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: match.route.id,\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return { type: ResultType.data, data: undefined };\n }\n }\n } else {\n invariant(\n handler,\n `Could not find the ${type} to run on the \"${match.route.id}\" route`\n );\n\n result = await runHandler(handler);\n }\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(\n (match) => match.pathnameBase\n );\n let resolvedLocation = resolveTo(\n location,\n routePathnames,\n new URL(request.url).pathname\n );\n invariant(\n createPath(resolvedLocation),\n `Unable to resolve redirect location: ${location}`\n );\n\n // Prepend the basename to the redirect location if we have one\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname =\n path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } else if (!isStaticRequest) {\n // Strip off the protocol+origin for same-origin + same-basename absolute\n // redirects. If this is a static request, we can let it go back to the\n // browser as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result,\n };\n }\n\n let data: any;\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (isDeferredData(result)) {\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: result.init?.status,\n headers: result.init?.headers && new Headers(result.init.headers),\n };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType, formData } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n init.body =\n formEncType === \"application/x-www-form-urlencoded\"\n ? convertFormDataToSearchParams(formData)\n : formData;\n }\n\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, value instanceof File ? value.name : value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponse(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results: DataResult[]): RedirectResult | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n return (\n a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash\n );\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nexport function isDeferredData(value: any): value is DeferredData {\n let deferred: DeferredData = value;\n return (\n deferred &&\n typeof deferred === \"object\" &&\n typeof deferred.data === \"object\" &&\n typeof deferred.subscribe === \"function\" &&\n typeof deferred.cancel === \"function\" &&\n typeof deferred.resolveData === \"function\"\n );\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod | V7_FormMethod {\n return validRequestMethods.has(method.toLowerCase() as FormMethod);\n}\n\nfunction isMutationMethod(\n method: string\n): method is MutationFormMethod | V7_MutationFormMethod {\n return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: (AgnosticDataRouteMatch | null)[],\n results: DataResult[],\n signal: AbortSignal,\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match!.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\n// Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\nfunction createUseMatchesMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UseMatchesMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id] as unknown,\n handle: route.handle as unknown,\n };\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n//#endregion\n"],"names":["Action","PopStateEventType","createMemoryHistory","options","initialEntries","initialIndex","v5Compat","entries","map","entry","index","createMemoryLocation","state","undefined","clampIndex","length","action","Pop","listener","n","Math","min","max","getCurrentLocation","to","key","location","createLocation","pathname","warning","charAt","JSON","stringify","createHref","createPath","history","createURL","URL","encodeLocation","path","parsePath","search","hash","push","Push","nextLocation","splice","delta","replace","Replace","go","nextIndex","listen","fn","createBrowserHistory","createBrowserLocation","window","globalHistory","usr","createBrowserHref","getUrlBasedHistory","createHashHistory","createHashLocation","substr","createHashHref","base","document","querySelector","href","getAttribute","url","hashIndex","indexOf","slice","validateHashLocation","invariant","value","message","Error","cond","console","warn","e","createKey","random","toString","getHistoryState","idx","current","parsedPath","searchIndex","getLocation","validateLocation","defaultView","getIndex","replaceState","handlePop","historyState","pushState","error","assign","origin","addEventListener","removeEventListener","ResultType","immutableRouteKeys","Set","isIndexRoute","route","convertRoutesToDataRoutes","routes","detectErrorBoundary","parentPath","manifest","treePath","id","join","children","indexRoute","hasErrorBoundary","pathOrLayoutRoute","matchRoutes","locationArg","basename","stripBasename","branches","flattenRoutes","rankRouteBranches","matches","i","matchRouteBranch","safelyDecodeURI","parentsMeta","flattenRoute","relativePath","meta","caseSensitive","childrenIndex","startsWith","joinPaths","routesMeta","concat","score","computeScore","forEach","includes","exploded","explodeOptionalSegments","segments","split","first","rest","isOptional","endsWith","required","restExploded","result","subpath","sort","a","b","compareIndexes","paramRe","dynamicSegmentValue","indexRouteValue","emptySegmentValue","staticSegmentValue","splatPenalty","isSplat","s","initialScore","some","filter","reduce","segment","test","siblings","every","branch","matchedParams","matchedPathname","end","remainingPathname","match","matchPath","Object","params","pathnameBase","normalizePathname","generatePath","originalPath","prefix","array","isLastSegment","star","starParam","keyMatch","optional","param","pattern","matcher","paramNames","compilePath","captureGroups","memo","paramName","splatValue","safelyDecodeURIComponent","regexpSource","_","RegExp","decodeURI","decodeURIComponent","toLowerCase","startIndex","nextChar","resolvePath","fromPathname","toPathname","resolvePathname","normalizeSearch","normalizeHash","relativeSegments","pop","getInvalidPathError","char","field","dest","getPathContributingMatches","resolveTo","toArg","routePathnames","locationPathname","isPathRelative","isEmptyPath","from","routePathnameIndex","toSegments","shift","hasExplicitTrailingSlash","hasCurrentTrailingSlash","getToPathname","paths","json","data","init","responseInit","status","headers","Headers","has","set","Response","AbortedDeferredError","DeferredData","constructor","pendingKeysSet","subscribers","deferredKeys","Array","isArray","reject","abortPromise","Promise","r","controller","AbortController","onAbort","unlistenAbortSignal","signal","acc","trackPromise","done","add","promise","race","then","onSettle","catch","defineProperty","get","aborted","delete","emit","settledKey","subscriber","subscribe","cancel","abort","v","k","resolveData","resolve","size","unwrappedData","unwrapTrackedPromise","pendingKeys","isTrackedPromise","_tracked","_error","_data","defer","redirect","ErrorResponse","statusText","internal","isRouteErrorResponse","validMutationMethodsArr","validMutationMethods","validRequestMethodsArr","validRequestMethods","redirectStatusCodes","redirectPreserveMethodStatusCodes","IDLE_NAVIGATION","formMethod","formAction","formEncType","formData","IDLE_FETCHER","IDLE_BLOCKER","proceed","reset","ABSOLUTE_URL_REGEX","isBrowser","createElement","isServer","defaultDetectErrorBoundary","Boolean","createRouter","dataRoutes","inFlightDataRoutes","future","v7_normalizeFormMethod","unlistenHistory","savedScrollPositions","getScrollRestorationKey","getScrollPosition","initialScrollRestored","hydrationData","initialMatches","initialErrors","getInternalRouterError","getShortCircuitMatches","initialized","m","lazy","loader","router","historyAction","navigation","restoreScrollPosition","preventScrollReset","revalidation","loaderData","actionData","errors","fetchers","Map","blockers","pendingAction","HistoryAction","pendingPreventScrollReset","pendingNavigationController","isUninterruptedRevalidation","isRevalidationRequired","cancelledDeferredRoutes","cancelledFetcherLoads","fetchControllers","incrementingLoadId","pendingNavigationLoadId","fetchReloadIds","fetchRedirectIds","fetchLoadMatches","activeDeferreds","blockerFunctions","ignoreNextHistoryUpdate","initialize","blockerKey","shouldBlockNavigation","currentLocation","updateBlocker","deleteBlocker","updateState","startNavigation","dispose","clear","deleteFetcher","newState","completeNavigation","isActionReload","isMutationMethod","_isRedirect","keys","mergeLoaderData","getSavedScrollPosition","navigate","opts","submission","normalizeNavigateOptions","userReplace","pendingError","revalidate","interruptActiveLoads","startUninterruptedRevalidation","overrideNavigation","saveScrollPosition","routesToUse","loadingNavigation","notFoundMatches","cancelActiveDeferreds","isHashChangeOnly","request","createClientSideRequest","pendingActionData","findNearestBoundary","actionOutput","handleAction","shortCircuited","pendingActionError","Request","handleLoaders","fetcherSubmission","actionMatch","getTargetMatch","type","method","routeId","callLoaderOrAction","isRedirectResult","startRedirectNavigation","isErrorResult","boundaryMatch","isDeferredResult","activeSubmission","matchesToLoad","revalidatingFetchers","getMatchesToLoad","rf","fetcher","revalidatingFetcher","results","loaderResults","fetcherResults","callLoadersAndMaybeResolveData","findRedirect","processLoaderData","deferredData","markFetchRedirectsDone","didAbortFetchLoads","abortStaleFetchLoads","getFetcher","fetch","abortFetcher","setFetcherError","handleFetcherAction","handleFetcherLoader","requestMatches","existingFetcher","abortController","fetchRequest","actionResult","loadingFetcher","isFetchActionRedirect","revalidationRequest","loadId","loadFetcher","staleKey","doneFetcher","resolveDeferredData","redirectLocation","_isFetchActionRedirect","isDifferentBasename","redirectHistoryAction","currentMatches","fetchersToLoad","all","f","resolveDeferredResults","markFetchersDone","doneKeys","landedId","yeetedKeys","getBlocker","blocker","newBlocker","blockerFunction","predicate","cancelledRouteIds","dfd","enableScrollRestoration","positions","getPosition","getKey","y","userMatches","createUseMatchesMatch","_internalSetRoutes","newRoutes","_internalFetchControllers","_internalActiveDeferreds","UNSAFE_DEFERRED_SYMBOL","Symbol","createStaticHandler","query","requestContext","isValidMethod","methodNotAllowedMatches","statusCode","loaderHeaders","actionHeaders","queryImpl","isResponse","queryRoute","find","values","routeMatch","submit","loadRouteData","isQueryRouteResponse","isRedirectResponse","response","isRouteRequest","Location","context","loaderRequest","getLoaderMatchesUntilBoundary","processRouteLoaderData","executedLoaders","fromEntries","getStaticContextFromError","newContext","_deepestRenderedBoundaryId","isSubmissionNavigation","isFetcher","toUpperCase","stripHashFromPath","searchParams","convertFormDataToSearchParams","hasNakedIndexQuery","append","boundaryId","boundaryMatches","findIndex","currentUrl","nextUrl","defaultShouldRevalidate","navigationMatches","isNewLoader","currentRouteMatch","nextRouteMatch","shouldRevalidateLoader","currentParams","nextParams","isNewRouteInstance","fetcherMatches","fetcherMatch","shouldRevalidate","currentLoaderData","currentMatch","isNew","isMissingData","currentPath","loaderMatch","arg","routeChoice","loadLazyRouteModule","lazyRoute","routeToUpdate","routeUpdates","lazyRouteProperty","staticRouteValue","isPropertyStaticallyDefined","isStaticRequest","resultType","onReject","runHandler","handler","activeMatches","resolvedLocation","protocol","isSameBasename","contentType","text","isDeferredData","deferred","body","URLSearchParams","File","name","foundError","newLoaderData","mergedLoaderData","hasOwnProperty","eligibleMatches","reverse","errorMessage","obj","isRevalidatingLoader","unwrap","getAll","handle","pathMatches"],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@remix-run/router/dist/router.umd.js b/node_modules/@remix-run/router/dist/router.umd.js new file mode 100644 index 00000000..1b134a06 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.umd.js @@ -0,0 +1,4273 @@ +/** + * @remix-run/router v1.5.0 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.RemixRouter = {})); +})(this, (function (exports) { 'use strict'; + + function _extends() { + _extends = Object.assign ? Object.assign.bind() : function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + return _extends.apply(this, arguments); + } + + //////////////////////////////////////////////////////////////////////////////// + //#region Types and Constants + //////////////////////////////////////////////////////////////////////////////// + + /** + * Actions represent the type of change to a location value. + */ + exports.Action = void 0; + /** + * The pathname, search, and hash values of a URL. + */ + + (function (Action) { + Action["Pop"] = "POP"; + Action["Push"] = "PUSH"; + Action["Replace"] = "REPLACE"; + })(exports.Action || (exports.Action = {})); + + const PopStateEventType = "popstate"; //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region Memory History + //////////////////////////////////////////////////////////////////////////////// + + /** + * A user-supplied object that describes a location. Used when providing + * entries to `createMemoryHistory` via its `initialEntries` option. + */ + + /** + * Memory history stores the current location in memory. It is designed for use + * in stateful non-browser environments like tests and React Native. + */ + function createMemoryHistory(options) { + if (options === void 0) { + options = {}; + } + + let { + initialEntries = ["/"], + initialIndex, + v5Compat = false + } = options; + let entries; // Declare so we can access from createMemoryLocation + + entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined)); + let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex); + let action = exports.Action.Pop; + let listener = null; + + function clampIndex(n) { + return Math.min(Math.max(n, 0), entries.length - 1); + } + + function getCurrentLocation() { + return entries[index]; + } + + function createMemoryLocation(to, state, key) { + if (state === void 0) { + state = null; + } + + let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key); + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to)); + return location; + } + + function createHref(to) { + return typeof to === "string" ? to : createPath(to); + } + + let history = { + get index() { + return index; + }, + + get action() { + return action; + }, + + get location() { + return getCurrentLocation(); + }, + + createHref, + + createURL(to) { + return new URL(createHref(to), "http://localhost"); + }, + + encodeLocation(to) { + let path = typeof to === "string" ? parsePath(to) : to; + return { + pathname: path.pathname || "", + search: path.search || "", + hash: path.hash || "" + }; + }, + + push(to, state) { + action = exports.Action.Push; + let nextLocation = createMemoryLocation(to, state); + index += 1; + entries.splice(index, entries.length, nextLocation); + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 1 + }); + } + }, + + replace(to, state) { + action = exports.Action.Replace; + let nextLocation = createMemoryLocation(to, state); + entries[index] = nextLocation; + + if (v5Compat && listener) { + listener({ + action, + location: nextLocation, + delta: 0 + }); + } + }, + + go(delta) { + action = exports.Action.Pop; + let nextIndex = clampIndex(index + delta); + let nextLocation = entries[nextIndex]; + index = nextIndex; + + if (listener) { + listener({ + action, + location: nextLocation, + delta + }); + } + }, + + listen(fn) { + listener = fn; + return () => { + listener = null; + }; + } + + }; + return history; + } //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region Browser History + //////////////////////////////////////////////////////////////////////////////// + + /** + * A browser history stores the current location in regular URLs in a web + * browser environment. This is the standard for most web apps and provides the + * cleanest URLs the browser's address bar. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory + */ + + /** + * Browser history stores the location in regular URLs. This is the standard for + * most web apps, but it requires some configuration on the server to ensure you + * serve the same app at multiple URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory + */ + function createBrowserHistory(options) { + if (options === void 0) { + options = {}; + } + + function createBrowserLocation(window, globalHistory) { + let { + pathname, + search, + hash + } = window.location; + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createBrowserHref(window, to) { + return typeof to === "string" ? to : createPath(to); + } + + return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options); + } //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region Hash History + //////////////////////////////////////////////////////////////////////////////// + + /** + * A hash history stores the current location in the fragment identifier portion + * of the URL in a web browser environment. + * + * This is ideal for apps that do not control the server for some reason + * (because the fragment identifier is never sent to the server), including some + * shared hosting environments that do not provide fine-grained controls over + * which pages are served at which URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory + */ + + /** + * Hash history stores the location in window.location.hash. This makes it ideal + * for situations where you don't want to send the location to the server for + * some reason, either because you do cannot configure it or the URL space is + * reserved for something else. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory + */ + function createHashHistory(options) { + if (options === void 0) { + options = {}; + } + + function createHashLocation(window, globalHistory) { + let { + pathname = "/", + search = "", + hash = "" + } = parsePath(window.location.hash.substr(1)); + return createLocation("", { + pathname, + search, + hash + }, // state defaults to `null` because `window.history.state` does + globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default"); + } + + function createHashHref(window, to) { + let base = window.document.querySelector("base"); + let href = ""; + + if (base && base.getAttribute("href")) { + let url = window.location.href; + let hashIndex = url.indexOf("#"); + href = hashIndex === -1 ? url : url.slice(0, hashIndex); + } + + return href + "#" + (typeof to === "string" ? to : createPath(to)); + } + + function validateHashLocation(location, to) { + warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")"); + } + + return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options); + } //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region UTILS + //////////////////////////////////////////////////////////////////////////////// + + /** + * @private + */ + + function invariant(value, message) { + if (value === false || value === null || typeof value === "undefined") { + throw new Error(message); + } + } + function warning(cond, message) { + if (!cond) { + // eslint-disable-next-line no-console + if (typeof console !== "undefined") console.warn(message); + + try { + // Welcome to debugging history! + // + // This error is thrown as a convenience so you can more easily + // find the source for a warning that appears in the console by + // enabling "pause on exceptions" in your JavaScript debugger. + throw new Error(message); // eslint-disable-next-line no-empty + } catch (e) {} + } + } + + function createKey() { + return Math.random().toString(36).substr(2, 8); + } + /** + * For browser-based histories, we combine the state and key into an object + */ + + + function getHistoryState(location, index) { + return { + usr: location.state, + key: location.key, + idx: index + }; + } + /** + * Creates a Location object with a unique key from the given Path + */ + + + function createLocation(current, to, state, key) { + if (state === void 0) { + state = null; + } + + let location = _extends({ + pathname: typeof current === "string" ? current : current.pathname, + search: "", + hash: "" + }, typeof to === "string" ? parsePath(to) : to, { + state, + // TODO: This could be cleaned up. push/replace should probably just take + // full Locations now and avoid the need to run through this flow at all + // But that's a pretty big refactor to the current test suite so going to + // keep as is for the time being and just let any incoming keys take precedence + key: to && to.key || key || createKey() + }); + + return location; + } + /** + * Creates a string URL path from the given pathname, search, and hash components. + */ + + function createPath(_ref) { + let { + pathname = "/", + search = "", + hash = "" + } = _ref; + if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search; + if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash; + return pathname; + } + /** + * Parses a string URL path into its separate pathname, search, and hash components. + */ + + function parsePath(path) { + let parsedPath = {}; + + if (path) { + let hashIndex = path.indexOf("#"); + + if (hashIndex >= 0) { + parsedPath.hash = path.substr(hashIndex); + path = path.substr(0, hashIndex); + } + + let searchIndex = path.indexOf("?"); + + if (searchIndex >= 0) { + parsedPath.search = path.substr(searchIndex); + path = path.substr(0, searchIndex); + } + + if (path) { + parsedPath.pathname = path; + } + } + + return parsedPath; + } + + function getUrlBasedHistory(getLocation, createHref, validateLocation, options) { + if (options === void 0) { + options = {}; + } + + let { + window = document.defaultView, + v5Compat = false + } = options; + let globalHistory = window.history; + let action = exports.Action.Pop; + let listener = null; + let index = getIndex(); // Index should only be null when we initialize. If not, it's because the + // user called history.pushState or history.replaceState directly, in which + // case we should log a warning as it will result in bugs. + + if (index == null) { + index = 0; + globalHistory.replaceState(_extends({}, globalHistory.state, { + idx: index + }), ""); + } + + function getIndex() { + let state = globalHistory.state || { + idx: null + }; + return state.idx; + } + + function handlePop() { + action = exports.Action.Pop; + let nextIndex = getIndex(); + let delta = nextIndex == null ? null : nextIndex - index; + index = nextIndex; + + if (listener) { + listener({ + action, + location: history.location, + delta + }); + } + } + + function push(to, state) { + action = exports.Action.Push; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex() + 1; + let historyState = getHistoryState(location, index); + let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/ + + try { + globalHistory.pushState(historyState, "", url); + } catch (error) { + // They are going to lose state here, but there is no real + // way to warn them about it since the page will refresh... + window.location.assign(url); + } + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 1 + }); + } + } + + function replace(to, state) { + action = exports.Action.Replace; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + index = getIndex(); + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + globalHistory.replaceState(historyState, "", url); + + if (v5Compat && listener) { + listener({ + action, + location: history.location, + delta: 0 + }); + } + } + + function createURL(to) { + // window.location.origin is "null" (the literal string value) in Firefox + // under certain conditions, notably when serving from a local HTML file + // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297 + let base = window.location.origin !== "null" ? window.location.origin : window.location.href; + let href = typeof to === "string" ? to : createPath(to); + invariant(base, "No window.location.(origin|href) available to create URL for href: " + href); + return new URL(href, base); + } + + let history = { + get action() { + return action; + }, + + get location() { + return getLocation(window, globalHistory); + }, + + listen(fn) { + if (listener) { + throw new Error("A history only accepts one active listener"); + } + + window.addEventListener(PopStateEventType, handlePop); + listener = fn; + return () => { + window.removeEventListener(PopStateEventType, handlePop); + listener = null; + }; + }, + + createHref(to) { + return createHref(window, to); + }, + + createURL, + + encodeLocation(to) { + // Encode a Location the same way window.location would + let url = createURL(to); + return { + pathname: url.pathname, + search: url.search, + hash: url.hash + }; + }, + + push, + replace, + + go(n) { + return globalHistory.go(n); + } + + }; + return history; + } //#endregion + + /** + * Map of routeId -> data returned from a loader/action/error + */ + + let ResultType; + /** + * Successful result from a loader or action + */ + + (function (ResultType) { + ResultType["data"] = "data"; + ResultType["deferred"] = "deferred"; + ResultType["redirect"] = "redirect"; + ResultType["error"] = "error"; + })(ResultType || (ResultType = {})); + + const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]); + /** + * lazy() function to load a route definition, which can add non-matching + * related properties to a route + */ + + function isIndexRoute(route) { + return route.index === true; + } // Walk the route tree generating unique IDs where necessary so we are working + // solely with AgnosticDataRouteObject's within the Router + + + function convertRoutesToDataRoutes(routes, detectErrorBoundary, parentPath, manifest) { + if (parentPath === void 0) { + parentPath = []; + } + + if (manifest === void 0) { + manifest = {}; + } + + return routes.map((route, index) => { + let treePath = [...parentPath, index]; + let id = typeof route.id === "string" ? route.id : treePath.join("-"); + invariant(route.index !== true || !route.children, "Cannot specify children on an index route"); + invariant(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages"); + + if (isIndexRoute(route)) { + let indexRoute = _extends({}, route, { + hasErrorBoundary: detectErrorBoundary(route), + id + }); + + manifest[id] = indexRoute; + return indexRoute; + } else { + let pathOrLayoutRoute = _extends({}, route, { + id, + hasErrorBoundary: detectErrorBoundary(route), + children: undefined + }); + + manifest[id] = pathOrLayoutRoute; + + if (route.children) { + pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, detectErrorBoundary, treePath, manifest); + } + + return pathOrLayoutRoute; + } + }); + } + /** + * Matches the given routes to a location and returns the match data. + * + * @see https://reactrouter.com/utils/match-routes + */ + + function matchRoutes(routes, locationArg, basename) { + if (basename === void 0) { + basename = "/"; + } + + let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + let pathname = stripBasename(location.pathname || "/", basename); + + if (pathname == null) { + return null; + } + + let branches = flattenRoutes(routes); + rankRouteBranches(branches); + let matches = null; + + for (let i = 0; matches == null && i < branches.length; ++i) { + matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location + // or from router.navigate, but we want to match against the unencoded + // paths in the route definitions. Memory router locations won't be + // encoded here but there also shouldn't be anything to decode so this + // should be a safe operation. This avoids needing matchRoutes to be + // history-aware. + safelyDecodeURI(pathname)); + } + + return matches; + } + + function flattenRoutes(routes, branches, parentsMeta, parentPath) { + if (branches === void 0) { + branches = []; + } + + if (parentsMeta === void 0) { + parentsMeta = []; + } + + if (parentPath === void 0) { + parentPath = ""; + } + + let flattenRoute = (route, index, relativePath) => { + let meta = { + relativePath: relativePath === undefined ? route.path || "" : relativePath, + caseSensitive: route.caseSensitive === true, + childrenIndex: index, + route + }; + + if (meta.relativePath.startsWith("/")) { + invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes."); + meta.relativePath = meta.relativePath.slice(parentPath.length); + } + + let path = joinPaths([parentPath, meta.relativePath]); + let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the + // route tree depth-first and child routes appear before their parents in + // the "flattened" version. + + if (route.children && route.children.length > 0) { + invariant( // Our types know better, but runtime JS may not! + // @ts-expect-error + route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\".")); + flattenRoutes(route.children, branches, routesMeta, path); + } // Routes without a path shouldn't ever match by themselves unless they are + // index routes, so don't add them to the list of possible branches. + + + if (route.path == null && !route.index) { + return; + } + + branches.push({ + path, + score: computeScore(path, route.index), + routesMeta + }); + }; + + routes.forEach((route, index) => { + var _route$path; + + // coarse-grain check for optional params + if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) { + flattenRoute(route, index); + } else { + for (let exploded of explodeOptionalSegments(route.path)) { + flattenRoute(route, index, exploded); + } + } + }); + return branches; + } + /** + * Computes all combinations of optional path segments for a given path, + * excluding combinations that are ambiguous and of lower priority. + * + * For example, `/one/:two?/three/:four?/:five?` explodes to: + * - `/one/three` + * - `/one/:two/three` + * - `/one/three/:four` + * - `/one/three/:five` + * - `/one/:two/three/:four` + * - `/one/:two/three/:five` + * - `/one/three/:four/:five` + * - `/one/:two/three/:four/:five` + */ + + + function explodeOptionalSegments(path) { + let segments = path.split("/"); + if (segments.length === 0) return []; + let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?` + + let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo` + + let required = first.replace(/\?$/, ""); + + if (rest.length === 0) { + // Intepret empty string as omitting an optional segment + // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three` + return isOptional ? [required, ""] : [required]; + } + + let restExploded = explodeOptionalSegments(rest.join("/")); + let result = []; // All child paths with the prefix. Do this for all children before the + // optional version for all children so we get consistent ordering where the + // parent optional aspect is preferred as required. Otherwise, we can get + // child sections interspersed where deeper optional segments are higher than + // parent optional segments, where for example, /:two would explodes _earlier_ + // then /:one. By always including the parent as required _for all children_ + // first, we avoid this issue + + result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without + + if (isOptional) { + result.push(...restExploded); + } // for absolute paths, ensure `/` instead of empty segment + + + return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded); + } + + function rankRouteBranches(branches) { + branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first + : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex))); + } + + const paramRe = /^:\w+$/; + const dynamicSegmentValue = 3; + const indexRouteValue = 2; + const emptySegmentValue = 1; + const staticSegmentValue = 10; + const splatPenalty = -2; + + const isSplat = s => s === "*"; + + function computeScore(path, index) { + let segments = path.split("/"); + let initialScore = segments.length; + + if (segments.some(isSplat)) { + initialScore += splatPenalty; + } + + if (index) { + initialScore += indexRouteValue; + } + + return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore); + } + + function compareIndexes(a, b) { + let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]); + return siblings ? // If two routes are siblings, we should try to match the earlier sibling + // first. This allows people to have fine-grained control over the matching + // behavior by simply putting routes with identical paths in the order they + // want them tried. + a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index, + // so they sort equally. + 0; + } + + function matchRouteBranch(branch, pathname) { + let { + routesMeta + } = branch; + let matchedParams = {}; + let matchedPathname = "/"; + let matches = []; + + for (let i = 0; i < routesMeta.length; ++i) { + let meta = routesMeta[i]; + let end = i === routesMeta.length - 1; + let remainingPathname = matchedPathname === "/" ? pathname : pathname.slice(matchedPathname.length) || "/"; + let match = matchPath({ + path: meta.relativePath, + caseSensitive: meta.caseSensitive, + end + }, remainingPathname); + if (!match) return null; + Object.assign(matchedParams, match.params); + let route = meta.route; + matches.push({ + // TODO: Can this as be avoided? + params: matchedParams, + pathname: joinPaths([matchedPathname, match.pathname]), + pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])), + route + }); + + if (match.pathnameBase !== "/") { + matchedPathname = joinPaths([matchedPathname, match.pathnameBase]); + } + } + + return matches; + } + /** + * Returns a path with params interpolated. + * + * @see https://reactrouter.com/utils/generate-path + */ + + + function generatePath(originalPath, params) { + if (params === void 0) { + params = {}; + } + + let path = originalPath; + + if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) { + warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + path = path.replace(/\*$/, "/*"); + } // ensure `/` is added at the beginning if the path is absolute + + + const prefix = path.startsWith("/") ? "/" : ""; + const segments = path.split(/\/+/).map((segment, index, array) => { + const isLastSegment = index === array.length - 1; // only apply the splat if it's the last segment + + if (isLastSegment && segment === "*") { + const star = "*"; + const starParam = params[star]; // Apply the splat + + return starParam; + } + + const keyMatch = segment.match(/^:(\w+)(\??)$/); + + if (keyMatch) { + const [, key, optional] = keyMatch; + let param = params[key]; + + if (optional === "?") { + return param == null ? "" : param; + } + + if (param == null) { + invariant(false, "Missing \":" + key + "\" param"); + } + + return param; + } // Remove any optional markers from optional static segments + + + return segment.replace(/\?$/g, ""); + }) // Remove empty segments + .filter(segment => !!segment); + return prefix + segments.join("/"); + } + /** + * A PathPattern is used to match on some portion of a URL pathname. + */ + + /** + * Performs pattern matching on a URL pathname and returns information about + * the match. + * + * @see https://reactrouter.com/utils/match-path + */ + function matchPath(pattern, pathname) { + if (typeof pattern === "string") { + pattern = { + path: pattern, + caseSensitive: false, + end: true + }; + } + + let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end); + let match = pathname.match(matcher); + if (!match) return null; + let matchedPathname = match[0]; + let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1"); + let captureGroups = match.slice(1); + let params = paramNames.reduce((memo, paramName, index) => { + // We need to compute the pathnameBase here using the raw splat value + // instead of using params["*"] later because it will be decoded then + if (paramName === "*") { + let splatValue = captureGroups[index] || ""; + pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1"); + } + + memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName); + return memo; + }, {}); + return { + params, + pathname: matchedPathname, + pathnameBase, + pattern + }; + } + + function compilePath(path, caseSensitive, end) { + if (caseSensitive === void 0) { + caseSensitive = false; + } + + if (end === void 0) { + end = true; + } + + warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\".")); + let paramNames = []; + let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below + .replace(/^\/*/, "/") // Make sure it has a leading / + .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars + .replace(/\/:(\w+)/g, (_, paramName) => { + paramNames.push(paramName); + return "/([^\\/]+)"; + }); + + if (path.endsWith("*")) { + paramNames.push("*"); + regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest + : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"] + } else if (end) { + // When matching to the end, ignore trailing slashes + regexpSource += "\\/*$"; + } else if (path !== "" && path !== "/") { + // If our path is non-empty and contains anything beyond an initial slash, + // then we have _some_ form of path in our regex so we should expect to + // match only if we find the end of this path segment. Look for an optional + // non-captured trailing slash (to match a portion of the URL) or the end + // of the path (if we've matched to the end). We used to do this with a + // word boundary but that gives false positives on routes like + // /user-preferences since `-` counts as a word boundary. + regexpSource += "(?:(?=\\/|$))"; + } else ; + + let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i"); + return [matcher, paramNames]; + } + + function safelyDecodeURI(value) { + try { + return decodeURI(value); + } catch (error) { + warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ").")); + return value; + } + } + + function safelyDecodeURIComponent(value, paramName) { + try { + return decodeURIComponent(value); + } catch (error) { + warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ").")); + return value; + } + } + /** + * @private + */ + + + function stripBasename(pathname, basename) { + if (basename === "/") return pathname; + + if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) { + return null; + } // We want to leave trailing slash behavior in the user's control, so if they + // specify a basename with a trailing slash, we should support it + + + let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length; + let nextChar = pathname.charAt(startIndex); + + if (nextChar && nextChar !== "/") { + // pathname does not start with basename/ + return null; + } + + return pathname.slice(startIndex) || "/"; + } + /** + * Returns a resolved path object relative to the given pathname. + * + * @see https://reactrouter.com/utils/resolve-path + */ + + function resolvePath(to, fromPathname) { + if (fromPathname === void 0) { + fromPathname = "/"; + } + + let { + pathname: toPathname, + search = "", + hash = "" + } = typeof to === "string" ? parsePath(to) : to; + let pathname = toPathname ? toPathname.startsWith("/") ? toPathname : resolvePathname(toPathname, fromPathname) : fromPathname; + return { + pathname, + search: normalizeSearch(search), + hash: normalizeHash(hash) + }; + } + + function resolvePathname(relativePath, fromPathname) { + let segments = fromPathname.replace(/\/+$/, "").split("/"); + let relativeSegments = relativePath.split("/"); + relativeSegments.forEach(segment => { + if (segment === "..") { + // Keep the root "" segment so the pathname starts at / + if (segments.length > 1) segments.pop(); + } else if (segment !== ".") { + segments.push(segment); + } + }); + return segments.length > 1 ? segments.join("/") : "/"; + } + + function getInvalidPathError(char, field, dest, path) { + return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in and the router will parse it for you."; + } + /** + * @private + * + * When processing relative navigation we want to ignore ancestor routes that + * do not contribute to the path, such that index/pathless layout routes don't + * interfere. + * + * For example, when moving a route element into an index route and/or a + * pathless layout route, relative link behavior contained within should stay + * the same. Both of the following examples should link back to the root: + * + * + * + * + * + * + * + * }> // <-- Does not contribute + * // <-- Does not contribute + * + * + */ + + + function getPathContributingMatches(matches) { + return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0); + } + /** + * @private + */ + + function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) { + if (isPathRelative === void 0) { + isPathRelative = false; + } + + let to; + + if (typeof toArg === "string") { + to = parsePath(toArg); + } else { + to = _extends({}, toArg); + invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to)); + invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to)); + invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to)); + } + + let isEmptyPath = toArg === "" || to.pathname === ""; + let toPathname = isEmptyPath ? "/" : to.pathname; + let from; // Routing is relative to the current pathname if explicitly requested. + // + // If a pathname is explicitly provided in `to`, it should be relative to the + // route context. This is explained in `Note on `` values` in our + // migration guide from v5 as a means of disambiguation between `to` values + // that begin with `/` and those that do not. However, this is problematic for + // `to` values that do not provide a pathname. `to` can simply be a search or + // hash string, in which case we should assume that the navigation is relative + // to the current location's pathname and *not* the route pathname. + + if (isPathRelative || toPathname == null) { + from = locationPathname; + } else { + let routePathnameIndex = routePathnames.length - 1; + + if (toPathname.startsWith("..")) { + let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one + // URL segment". This is a key difference from how works and a + // major reason we call this a "to" value instead of a "href". + + while (toSegments[0] === "..") { + toSegments.shift(); + routePathnameIndex -= 1; + } + + to.pathname = toSegments.join("/"); + } // If there are more ".." segments than parent routes, resolve relative to + // the root / URL. + + + from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/"; + } + + let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one + + let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash + + let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/"); + + if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) { + path.pathname += "/"; + } + + return path; + } + /** + * @private + */ + + function getToPathname(to) { + // Empty strings should be treated the same as / paths + return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname; + } + /** + * @private + */ + + const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/"); + /** + * @private + */ + + const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/"); + /** + * @private + */ + + const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search; + /** + * @private + */ + + const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; + + /** + * This is a shortcut for creating `application/json` responses. Converts `data` + * to JSON and sets the `Content-Type` header. + */ + const json = function json(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + let headers = new Headers(responseInit.headers); + + if (!headers.has("Content-Type")) { + headers.set("Content-Type", "application/json; charset=utf-8"); + } + + return new Response(JSON.stringify(data), _extends({}, responseInit, { + headers + })); + }; + class AbortedDeferredError extends Error {} + class DeferredData { + constructor(data, responseInit) { + this.pendingKeysSet = new Set(); + this.subscribers = new Set(); + this.deferredKeys = []; + invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early + // cancellation + + let reject; + this.abortPromise = new Promise((_, r) => reject = r); + this.controller = new AbortController(); + + let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted")); + + this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort); + + this.controller.signal.addEventListener("abort", onAbort); + this.data = Object.entries(data).reduce((acc, _ref) => { + let [key, value] = _ref; + return Object.assign(acc, { + [key]: this.trackPromise(key, value) + }); + }, {}); + + if (this.done) { + // All incoming values were resolved + this.unlistenAbortSignal(); + } + + this.init = responseInit; + } + + trackPromise(key, value) { + if (!(value instanceof Promise)) { + return value; + } + + this.deferredKeys.push(key); + this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with + // _data/_error props upon resolve/reject + + let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on + // errors or aborted deferred values + + promise.catch(() => {}); + Object.defineProperty(promise, "_tracked", { + get: () => true + }); + return promise; + } + + onSettle(promise, key, error, data) { + if (this.controller.signal.aborted && error instanceof AbortedDeferredError) { + this.unlistenAbortSignal(); + Object.defineProperty(promise, "_error", { + get: () => error + }); + return Promise.reject(error); + } + + this.pendingKeysSet.delete(key); + + if (this.done) { + // Nothing left to abort! + this.unlistenAbortSignal(); + } + + if (error) { + Object.defineProperty(promise, "_error", { + get: () => error + }); + this.emit(false, key); + return Promise.reject(error); + } + + Object.defineProperty(promise, "_data", { + get: () => data + }); + this.emit(false, key); + return data; + } + + emit(aborted, settledKey) { + this.subscribers.forEach(subscriber => subscriber(aborted, settledKey)); + } + + subscribe(fn) { + this.subscribers.add(fn); + return () => this.subscribers.delete(fn); + } + + cancel() { + this.controller.abort(); + this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k)); + this.emit(true); + } + + async resolveData(signal) { + let aborted = false; + + if (!this.done) { + let onAbort = () => this.cancel(); + + signal.addEventListener("abort", onAbort); + aborted = await new Promise(resolve => { + this.subscribe(aborted => { + signal.removeEventListener("abort", onAbort); + + if (aborted || this.done) { + resolve(aborted); + } + }); + }); + } + + return aborted; + } + + get done() { + return this.pendingKeysSet.size === 0; + } + + get unwrappedData() { + invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds"); + return Object.entries(this.data).reduce((acc, _ref2) => { + let [key, value] = _ref2; + return Object.assign(acc, { + [key]: unwrapTrackedPromise(value) + }); + }, {}); + } + + get pendingKeys() { + return Array.from(this.pendingKeysSet); + } + + } + + function isTrackedPromise(value) { + return value instanceof Promise && value._tracked === true; + } + + function unwrapTrackedPromise(value) { + if (!isTrackedPromise(value)) { + return value; + } + + if (value._error) { + throw value._error; + } + + return value._data; + } + + const defer = function defer(data, init) { + if (init === void 0) { + init = {}; + } + + let responseInit = typeof init === "number" ? { + status: init + } : init; + return new DeferredData(data, responseInit); + }; + + /** + * A redirect response. Sets the status code and the `Location` header. + * Defaults to "302 Found". + */ + const redirect = function redirect(url, init) { + if (init === void 0) { + init = 302; + } + + let responseInit = init; + + if (typeof responseInit === "number") { + responseInit = { + status: responseInit + }; + } else if (typeof responseInit.status === "undefined") { + responseInit.status = 302; + } + + let headers = new Headers(responseInit.headers); + headers.set("Location", url); + return new Response(null, _extends({}, responseInit, { + headers + })); + }; + /** + * @private + * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies + */ + + class ErrorResponse { + constructor(status, statusText, data, internal) { + if (internal === void 0) { + internal = false; + } + + this.status = status; + this.statusText = statusText || ""; + this.internal = internal; + + if (data instanceof Error) { + this.data = data.toString(); + this.error = data; + } else { + this.data = data; + } + } + + } + /** + * Check if the given error is an ErrorResponse generated from a 4xx/5xx + * Response thrown from an action/loader + */ + + function isRouteErrorResponse(error) { + return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error; + } + + //#region Types and Constants + //////////////////////////////////////////////////////////////////////////////// + + /** + * A Router instance manages all navigation and data loading/mutations + */ + + const validMutationMethodsArr = ["post", "put", "patch", "delete"]; + const validMutationMethods = new Set(validMutationMethodsArr); + const validRequestMethodsArr = ["get", ...validMutationMethodsArr]; + const validRequestMethods = new Set(validRequestMethodsArr); + const redirectStatusCodes = new Set([301, 302, 303, 307, 308]); + const redirectPreserveMethodStatusCodes = new Set([307, 308]); + const IDLE_NAVIGATION = { + state: "idle", + location: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }; + const IDLE_FETCHER = { + state: "idle", + data: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }; + const IDLE_BLOCKER = { + state: "unblocked", + proceed: undefined, + reset: undefined, + location: undefined + }; + const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i; + const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined"; + const isServer = !isBrowser; + + const defaultDetectErrorBoundary = route => Boolean(route.hasErrorBoundary); //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region createRouter + //////////////////////////////////////////////////////////////////////////////// + + /** + * Create a router and listen to history POP navigations + */ + + + function createRouter(init) { + invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter"); + let detectErrorBoundary = init.detectErrorBoundary || defaultDetectErrorBoundary; // Routes keyed by ID + + let manifest = {}; // Routes in tree format for matching + + let dataRoutes = convertRoutesToDataRoutes(init.routes, detectErrorBoundary, undefined, manifest); + let inFlightDataRoutes; // Config driven behavior flags + + let future = _extends({ + v7_normalizeFormMethod: false + }, init.future); // Cleanup function for history + + + let unlistenHistory = null; // Externally-provided functions to call on all state changes + + let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing + + let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys + + let getScrollRestorationKey = null; // Externally-provided function to get current scroll position + + let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration. Because + // we don't get the saved positions from until _after_ + // the initial render, we need to manually trigger a separate updateState to + // send along the restoreScrollPosition + // Set to true if we have `hydrationData` since we assume we were SSR'd and that + // SSR did the initial scroll restoration. + + let initialScrollRestored = init.hydrationData != null; + let initialMatches = matchRoutes(dataRoutes, init.history.location, init.basename); + let initialErrors = null; + + if (initialMatches == null) { + // If we do not match a user-provided-route, fall back to the root + // to allow the error boundary to take over + let error = getInternalRouterError(404, { + pathname: init.history.location.pathname + }); + let { + matches, + route + } = getShortCircuitMatches(dataRoutes); + initialMatches = matches; + initialErrors = { + [route.id]: error + }; + } + + let initialized = // All initialMatches need to be loaded before we're ready. If we have lazy + // functions around still then we'll need to run them in initialize() + !initialMatches.some(m => m.route.lazy) && ( // And we have to either have no loaders or have been provided hydrationData + !initialMatches.some(m => m.route.loader) || init.hydrationData != null); + let router; + let state = { + historyAction: init.history.action, + location: init.history.location, + matches: initialMatches, + initialized, + navigation: IDLE_NAVIGATION, + // Don't restore on initial updateState() if we were SSR'd + restoreScrollPosition: init.hydrationData != null ? false : null, + preventScrollReset: false, + revalidation: "idle", + loaderData: init.hydrationData && init.hydrationData.loaderData || {}, + actionData: init.hydrationData && init.hydrationData.actionData || null, + errors: init.hydrationData && init.hydrationData.errors || initialErrors, + fetchers: new Map(), + blockers: new Map() + }; // -- Stateful internal variables to manage navigations -- + // Current navigation in progress (to be committed in completeNavigation) + + let pendingAction = exports.Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot + // be restored? + + let pendingPreventScrollReset = false; // AbortController for the active navigation + + let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a + // revalidation is entirely uninterrupted + + let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders: + // - submissions (completed or interrupted) + // - useRevalidate() + // - X-Remix-Revalidate (from redirect) + + let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due + // to a cancelled deferred on action submission + + let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an + // action navigation and require revalidation + + let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers + + let fetchControllers = new Map(); // Track loads based on the order in which they started + + let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against + // the globally incrementing load when a fetcher load lands after a completed + // navigation + + let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions + + let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations from their actions + + let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers + + let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches. When a + // route loader returns defer() we stick one in here. Then, when a nested + // promise resolves we update loaderData. If a new navigation starts we + // cancel active deferreds for eliminated routes. + + let activeDeferreds = new Map(); // Store blocker functions in a separate Map outside of router state since + // we don't need to update UI state if they change + + let blockerFunctions = new Map(); // Flag to ignore the next history update, so we can revert the URL change on + // a POP navigation that was blocked by the user without touching router state + + let ignoreNextHistoryUpdate = false; // Initialize the router, all side effects should be kicked off from here. + // Implemented as a Fluent API for ease of: + // let router = createRouter(init).initialize(); + + function initialize() { + // If history informs us of a POP navigation, start the navigation but do not update + // state. We'll update our own state once the navigation completes + unlistenHistory = init.history.listen(_ref => { + let { + action: historyAction, + location, + delta + } = _ref; + + // Ignore this event if it was just us resetting the URL from a + // blocked POP navigation + if (ignoreNextHistoryUpdate) { + ignoreNextHistoryUpdate = false; + return; + } + + warning(blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + "via `window.history.pushState`/`window.location.hash` instead of using " + "router navigation APIs. This can also happen if you are using " + "createHashRouter and the user manually changes the URL."); + let blockerKey = shouldBlockNavigation({ + currentLocation: state.location, + nextLocation: location, + historyAction + }); + + if (blockerKey && delta != null) { + // Restore the URL to match the current UI, but don't update router state + ignoreNextHistoryUpdate = true; + init.history.go(delta * -1); // Put the blocker into a blocked state + + updateBlocker(blockerKey, { + state: "blocked", + location, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location + }); // Re-do the same POP navigation we just blocked + + init.history.go(delta); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(router.state.blockers) + }); + } + + }); + return; + } + + return startNavigation(historyAction, location); + }); // Kick off initial data load if needed. Use Pop to avoid modifying history + // Note we don't do any handling of lazy here. For SPA's it'll get handled + // in the normal navigation flow. For SSR it's expected that lazy modules are + // resolved prior to router creation since we can't go into a fallbackElement + // UI for SSR'd apps + + if (!state.initialized) { + startNavigation(exports.Action.Pop, state.location); + } + + return router; + } // Clean up a router and it's side effects + + + function dispose() { + if (unlistenHistory) { + unlistenHistory(); + } + + subscribers.clear(); + pendingNavigationController && pendingNavigationController.abort(); + state.fetchers.forEach((_, key) => deleteFetcher(key)); + state.blockers.forEach((_, key) => deleteBlocker(key)); + } // Subscribe to state updates for the router + + + function subscribe(fn) { + subscribers.add(fn); + return () => subscribers.delete(fn); + } // Update our state and notify the calling context of the change + + + function updateState(newState) { + state = _extends({}, state, newState); + subscribers.forEach(subscriber => subscriber(state)); + } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION + // and setting state.[historyAction/location/matches] to the new route. + // - Location is a required param + // - Navigation will always be set to IDLE_NAVIGATION + // - Can pass any other state in newState + + + function completeNavigation(location, newState) { + var _location$state, _location$state2; + + // Deduce if we're in a loading/actionReload state: + // - We have committed actionData in the store + // - The current navigation was a mutation submission + // - We're past the submitting state and into the loading state + // - The location being loaded is not the result of a redirect + let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true; + let actionData; + + if (newState.actionData) { + if (Object.keys(newState.actionData).length > 0) { + actionData = newState.actionData; + } else { + // Empty actionData -> clear prior actionData due to an action error + actionData = null; + } + } else if (isActionReload) { + // Keep the current data if we're wrapping up the action reload + actionData = state.actionData; + } else { + // Clear actionData on any other completed navigations + actionData = null; + } // Always preserve any existing loaderData from re-used routes + + + let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // On a successful navigation we can assume we got through all blockers + // so we can start fresh + + for (let [key] of blockerFunctions) { + deleteBlocker(key); + } // Always respect the user flag. Otherwise don't reset on mutation + // submission navigations unless they redirect + + + let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true; + + if (inFlightDataRoutes) { + dataRoutes = inFlightDataRoutes; + inFlightDataRoutes = undefined; + } + + updateState(_extends({}, newState, { + // matches, errors, fetchers go through as-is + actionData, + loaderData, + historyAction: pendingAction, + location, + initialized: true, + navigation: IDLE_NAVIGATION, + revalidation: "idle", + restoreScrollPosition: getSavedScrollPosition(location, newState.matches || state.matches), + preventScrollReset, + blockers: new Map(state.blockers) + })); + + if (isUninterruptedRevalidation) ; else if (pendingAction === exports.Action.Pop) ; else if (pendingAction === exports.Action.Push) { + init.history.push(location, location.state); + } else if (pendingAction === exports.Action.Replace) { + init.history.replace(location, location.state); + } // Reset stateful navigation vars + + + pendingAction = exports.Action.Pop; + pendingPreventScrollReset = false; + isUninterruptedRevalidation = false; + isRevalidationRequired = false; + cancelledDeferredRoutes = []; + cancelledFetcherLoads = []; + } // Trigger a navigation event, which can either be a numerical POP or a PUSH + // replace with an optional submission + + + async function navigate(to, opts) { + if (typeof to === "number") { + init.history.go(to); + return; + } + + let { + path, + submission, + error + } = normalizeNavigateOptions(to, future, opts); + let currentLocation = state.location; + let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded + // URL from window.location, so we need to encode it here so the behavior + // remains the same as POP and non-data-router usages. new URL() does all + // the same encoding we'd get from a history.pushState/window.location read + // without having to touch history + + nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation)); + let userReplace = opts && opts.replace != null ? opts.replace : undefined; + let historyAction = exports.Action.Push; + + if (userReplace === true) { + historyAction = exports.Action.Replace; + } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) { + // By default on submissions to the current location we REPLACE so that + // users don't have to double-click the back button to get to the prior + // location. If the user redirects to a different location from the + // action/loader this will be ignored and the redirect will be a PUSH + historyAction = exports.Action.Replace; + } + + let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined; + let blockerKey = shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction + }); + + if (blockerKey) { + // Put the blocker into a blocked state + updateBlocker(blockerKey, { + state: "blocked", + location: nextLocation, + + proceed() { + updateBlocker(blockerKey, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location: nextLocation + }); // Send the same navigation through + + navigate(to, opts); + }, + + reset() { + deleteBlocker(blockerKey); + updateState({ + blockers: new Map(state.blockers) + }); + } + + }); + return; + } + + return await startNavigation(historyAction, nextLocation, { + submission, + // Send through the formData serialization error if we have one so we can + // render at the right error boundary after we match routes + pendingError: error, + preventScrollReset, + replace: opts && opts.replace + }); + } // Revalidate all current loaders. If a navigation is in progress or if this + // is interrupted by a navigation, allow this to "succeed" by calling all + // loaders during the next loader round + + + function revalidate() { + interruptActiveLoads(); + updateState({ + revalidation: "loading" + }); // If we're currently submitting an action, we don't need to start a new + // navigation, we'll just let the follow up loader execution call all loaders + + if (state.navigation.state === "submitting") { + return; + } // If we're currently in an idle state, start a new navigation for the current + // action/location and mark it as uninterrupted, which will skip the history + // update in completeNavigation + + + if (state.navigation.state === "idle") { + startNavigation(state.historyAction, state.location, { + startUninterruptedRevalidation: true + }); + return; + } // Otherwise, if we're currently in a loading state, just start a new + // navigation to the navigation.location but do not trigger an uninterrupted + // revalidation so that history correctly updates once the navigation completes + + + startNavigation(pendingAction || state.historyAction, state.navigation.location, { + overrideNavigation: state.navigation + }); + } // Start a navigation to the given action/location. Can optionally provide a + // overrideNavigation which will override the normalLoad in the case of a redirect + // navigation + + + async function startNavigation(historyAction, location, opts) { + // Abort any in-progress navigations and start a new one. Unset any ongoing + // uninterrupted revalidations unless told otherwise, since we want this + // new navigation to update history normally + pendingNavigationController && pendingNavigationController.abort(); + pendingNavigationController = null; + pendingAction = historyAction; + isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation, + // and track whether we should reset scroll on completion + + saveScrollPosition(state.location, state.matches); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + let routesToUse = inFlightDataRoutes || dataRoutes; + let loadingNavigation = opts && opts.overrideNavigation; + let matches = matchRoutes(routesToUse, location, init.basename); // Short circuit with a 404 on the root error boundary if we match nothing + + if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes + + cancelActiveDeferreds(); + completeNavigation(location, { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error + } + }); + return; + } // Short circuit if it's only a hash change and not a mutation submission + // For example, on /page#hash and submit a which will + // default to a navigation to /page + + + if (isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) { + completeNavigation(location, { + matches + }); + return; + } // Create a controller/Request for this navigation + + + pendingNavigationController = new AbortController(); + let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission); + let pendingActionData; + let pendingError; + + if (opts && opts.pendingError) { + // If we have a pendingError, it means the user attempted a GET submission + // with binary FormData so assign here and skip to handleLoaders. That + // way we handle calling loaders above the boundary etc. It's not really + // different from an actionError in that sense. + pendingError = { + [findNearestBoundary(matches).route.id]: opts.pendingError + }; + } else if (opts && opts.submission && isMutationMethod(opts.submission.formMethod)) { + // Call action if we received an action submission + let actionOutput = await handleAction(request, location, opts.submission, matches, { + replace: opts.replace + }); + + if (actionOutput.shortCircuited) { + return; + } + + pendingActionData = actionOutput.pendingActionData; + pendingError = actionOutput.pendingActionError; + + let navigation = _extends({ + state: "loading", + location + }, opts.submission); + + loadingNavigation = navigation; // Create a GET request for the loaders + + request = new Request(request.url, { + signal: request.signal + }); + } // Call loaders + + + let { + shortCircuited, + loaderData, + errors + } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError); + + if (shortCircuited) { + return; + } // Clean up now that the action/loaders have completed. Don't clean up if + // we short circuited because pendingNavigationController will have already + // been assigned to a new controller for the next navigation + + + pendingNavigationController = null; + completeNavigation(location, _extends({ + matches + }, pendingActionData ? { + actionData: pendingActionData + } : {}, { + loaderData, + errors + })); + } // Call the action matched by the leaf route for this navigation and handle + // redirects/errors + + + async function handleAction(request, location, submission, matches, opts) { + interruptActiveLoads(); // Put us in a submitting state + + let navigation = _extends({ + state: "submitting", + location + }, submission); + + updateState({ + navigation + }); // Call our action and get the result + + let result; + let actionMatch = getTargetMatch(matches, location); + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + result = { + type: ResultType.error, + error: getInternalRouterError(405, { + method: request.method, + pathname: location.pathname, + routeId: actionMatch.route.id + }) + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, router.basename); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } + } + + if (isRedirectResult(result)) { + let replace; + + if (opts && opts.replace != null) { + replace = opts.replace; + } else { + // If the user didn't explicity indicate replace behavior, replace if + // we redirected to the exact same location we're currently at to avoid + // double back-buttons + replace = result.location === state.location.pathname + state.location.search; + } + + await startRedirectNavigation(state, result, { + submission, + replace + }); + return { + shortCircuited: true + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the + // action threw an error that'll be rendered in an errorElement, we fall + // back to PUSH so that the user can use the back button to get back to + // the pre-submission form location to try again + + if ((opts && opts.replace) !== true) { + pendingAction = exports.Action.Push; + } + + return { + // Send back an empty object we can use to clear out any prior actionData + pendingActionData: {}, + pendingActionError: { + [boundaryMatch.route.id]: result.error + } + }; + } + + if (isDeferredResult(result)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } + + return { + pendingActionData: { + [actionMatch.route.id]: result.data + } + }; + } // Call all applicable loaders for the given matches, handling redirects, + // errors, etc. + + + async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) { + // Figure out the right navigation we want to use for data loading + let loadingNavigation = overrideNavigation; + + if (!loadingNavigation) { + let navigation = _extends({ + state: "loading", + location, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission); + + loadingNavigation = navigation; + } // If this was a redirect from an action we don't have a "submission" but + // we have it on the loading navigation so use that if available + + + let activeSubmission = submission || fetcherSubmission ? submission || fetcherSubmission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? { + formMethod: loadingNavigation.formMethod, + formAction: loadingNavigation.formAction, + formData: loadingNavigation.formData, + formEncType: loadingNavigation.formEncType + } : undefined; + let routesToUse = inFlightDataRoutes || dataRoutes; + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're + // about to reload. Note that if this is an action reload we would have + // already cancelled all pending deferreds so this would be a no-op + + cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run + + if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) { + completeNavigation(location, _extends({ + matches, + loaderData: {}, + // Commit pending error if we're short circuiting + errors: pendingError || null + }, pendingActionData ? { + actionData: pendingActionData + } : {})); + return { + shortCircuited: true + }; + } // If this is an uninterrupted revalidation, we remain in our current idle + // state. If not, we need to switch to our loading state and load data, + // preserving any new action data or existing action data (in the case of + // a revalidation interrupting an actionReload) + + + if (!isUninterruptedRevalidation) { + revalidatingFetchers.forEach(rf => { + let fetcher = state.fetchers.get(rf.key); + let revalidatingFetcher = { + state: "loading", + data: fetcher && fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(rf.key, revalidatingFetcher); + }); + let actionData = pendingActionData || state.actionData; + updateState(_extends({ + navigation: loadingNavigation + }, actionData ? Object.keys(actionData).length === 0 ? { + actionData: null + } : { + actionData + } : {}, revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {})); + } + + pendingNavigationLoadId = ++incrementingLoadId; + revalidatingFetchers.forEach(rf => fetchControllers.set(rf.key, pendingNavigationController)); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request); + + if (request.signal.aborted) { + return { + shortCircuited: true + }; + } // Clean up _after_ loaders have completed. Don't clean up if we short + // circuited because fetchControllers would have been aborted and + // reassigned to new controllers for the next navigation + + + revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key)); // If any loaders returned a redirect Response, start a new REPLACE navigation + + let redirect = findRedirect(results); + + if (redirect) { + await startRedirectNavigation(state, redirect, { + replace + }); + return { + shortCircuited: true + }; + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle + + activeDeferreds.forEach((deferredData, routeId) => { + deferredData.subscribe(aborted => { + // Note: No need to updateState here since the TrackedPromise on + // loaderData is stable across resolve/reject + // Remove this instance if we were aborted or if promises have settled + if (aborted || deferredData.done) { + activeDeferreds.delete(routeId); + } + }); + }); + markFetchRedirectsDone(); + let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId); + return _extends({ + loaderData, + errors + }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? { + fetchers: new Map(state.fetchers) + } : {}); + } + + function getFetcher(key) { + return state.fetchers.get(key) || IDLE_FETCHER; + } // Trigger a fetcher load/submit for the given fetcher key + + + function fetch(key, routeId, href, opts) { + if (isServer) { + throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback."); + } + + if (fetchControllers.has(key)) abortFetcher(key); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = matchRoutes(routesToUse, href, init.basename); + + if (!matches) { + setFetcherError(key, routeId, getInternalRouterError(404, { + pathname: href + })); + return; + } + + let { + path, + submission + } = normalizeNavigateOptions(href, future, opts, true); + let match = getTargetMatch(matches, path); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + + if (submission && isMutationMethod(submission.formMethod)) { + handleFetcherAction(key, routeId, path, match, matches, submission); + return; + } // Store off the match so we can call it's shouldRevalidate on subsequent + // revalidations + + + fetchLoadMatches.set(key, { + routeId, + path + }); + handleFetcherLoader(key, routeId, path, match, matches, submission); + } // Call the action for the matched fetcher.submit(), and then handle redirects, + // errors, and revalidation + + + async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) { + interruptActiveLoads(); + fetchLoadMatches.delete(key); + + if (!match.route.action && !match.route.lazy) { + let error = getInternalRouterError(405, { + method: submission.formMethod, + pathname: path, + routeId: routeId + }); + setFetcherError(key, routeId, error); + return; + } // Put this fetcher into it's submitting state + + + let existingFetcher = state.fetchers.get(key); + + let fetcher = _extends({ + state: "submitting" + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, fetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the action for the fetcher + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission); + fetchControllers.set(key, abortController); + let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, detectErrorBoundary, router.basename); + + if (fetchRequest.signal.aborted) { + // We can delete this so long as we weren't aborted by ou our own fetcher + // re-submit which would have put _new_ controller is in fetchControllers + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + return; + } + + if (isRedirectResult(actionResult)) { + fetchControllers.delete(key); + fetchRedirectIds.add(key); + + let loadingFetcher = _extends({ + state: "loading" + }, submission, { + data: undefined, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + return startRedirectNavigation(state, actionResult, { + submission, + isFetchActionRedirect: true + }); + } // Process any non-redirect errors thrown + + + if (isErrorResult(actionResult)) { + setFetcherError(key, routeId, actionResult.error); + return; + } + + if (isDeferredResult(actionResult)) { + throw getInternalRouterError(400, { + type: "defer-action" + }); + } // Start the data load for current matches, or the next location if we're + // in the middle of a navigation + + + let nextLocation = state.navigation.location || state.location; + let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = state.navigation.state !== "idle" ? matchRoutes(routesToUse, state.navigation.location, init.basename) : state.matches; + invariant(matches, "Didn't find any matches after fetcher action"); + let loadId = ++incrementingLoadId; + fetchReloadIds.set(key, loadId); + + let loadFetcher = _extends({ + state: "loading", + data: actionResult.data + }, submission, { + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadFetcher); + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, init.basename, { + [match.route.id]: actionResult.data + }, undefined // No need to send through errors since we short circuit above + ); // Put all revalidating fetchers into the loading state, except for the + // current fetcher which we want to keep in it's current loading state which + // contains it's action submission info + action data + + revalidatingFetchers.filter(rf => rf.key !== key).forEach(rf => { + let staleKey = rf.key; + let existingFetcher = state.fetchers.get(staleKey); + let revalidatingFetcher = { + state: "loading", + data: existingFetcher && existingFetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(staleKey, revalidatingFetcher); + fetchControllers.set(staleKey, abortController); + }); + updateState({ + fetchers: new Map(state.fetchers) + }); + let { + results, + loaderResults, + fetcherResults + } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest); + + if (abortController.signal.aborted) { + return; + } + + fetchReloadIds.delete(key); + fetchControllers.delete(key); + revalidatingFetchers.forEach(r => fetchControllers.delete(r.key)); + let redirect = findRedirect(results); + + if (redirect) { + return startRedirectNavigation(state, redirect); + } // Process and commit output from loaders + + + let { + loaderData, + errors + } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds); + let doneFetcher = { + state: "idle", + data: actionResult.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is + // more recent than the navigation, we want the newer data so abort the + // navigation and complete it with the fetcher data + + if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) { + invariant(pendingAction, "Expected pending action"); + pendingNavigationController && pendingNavigationController.abort(); + completeNavigation(state.navigation.location, { + matches, + loaderData, + errors, + fetchers: new Map(state.fetchers) + }); + } else { + // otherwise just update with the fetcher data, preserving any existing + // loaderData for loaders that did not need to reload. We have to + // manually merge here since we aren't going through completeNavigation + updateState(_extends({ + errors, + loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors) + }, didAbortFetchLoads ? { + fetchers: new Map(state.fetchers) + } : {})); + isRevalidationRequired = false; + } + } // Call the matched loader for fetcher.load(), handling redirects, errors, etc. + + + async function handleFetcherLoader(key, routeId, path, match, matches, submission) { + let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state + + let loadingFetcher = _extends({ + state: "loading", + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, submission, { + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true + }); + + state.fetchers.set(key, loadingFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); // Call the loader for this fetcher route match + + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest(init.history, path, abortController.signal); + fetchControllers.set(key, abortController); + let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, detectErrorBoundary, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it + // as a normal load. resolveDeferredData will return undefined if this + // fetcher gets aborted, so we just leave result untouched and short circuit + // below if that happens + + if (isDeferredResult(result)) { + result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result; + } // We can delete this so long as we weren't aborted by ou our own fetcher + // re-load which would have put _new_ controller is in fetchControllers + + + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + if (fetchRequest.signal.aborted) { + return; + } // If the loader threw a redirect Response, start a new REPLACE navigation + + + if (isRedirectResult(result)) { + await startRedirectNavigation(state, result); + return; + } // Process any non-redirect errors thrown + + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch - + // do we need to behave any differently with our non-redirect errors? + // What if it was a non-redirect Response? + + updateState({ + fetchers: new Map(state.fetchers), + errors: { + [boundaryMatch.route.id]: result.error + } + }); + return; + } + + invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state + + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + updateState({ + fetchers: new Map(state.fetchers) + }); + } + /** + * Utility function to handle redirects returned from an action or loader. + * Normally, a redirect "replaces" the navigation that triggered it. So, for + * example: + * + * - user is on /a + * - user clicks a link to /b + * - loader for /b redirects to /c + * + * In a non-JS app the browser would track the in-flight navigation to /b and + * then replace it with /c when it encountered the redirect response. In + * the end it would only ever update the URL bar with /c. + * + * In client-side routing using pushState/replaceState, we aim to emulate + * this behavior and we also do not update history until the end of the + * navigation (including processed redirects). This means that we never + * actually touch history until we've processed redirects, so we just use + * the history action from the original navigation (PUSH or REPLACE). + */ + + + async function startRedirectNavigation(state, redirect, _temp) { + var _window; + + let { + submission, + replace, + isFetchActionRedirect + } = _temp === void 0 ? {} : _temp; + + if (redirect.revalidate) { + isRevalidationRequired = true; + } + + let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2 + _extends({ + _isRedirect: true + }, isFetchActionRedirect ? { + _isFetchActionRedirect: true + } : {})); + invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an absolute external redirect that goes to a new origin + + if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser && typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") { + let url = init.history.createURL(redirect.location); + let isDifferentBasename = stripBasename(url.pathname, init.basename || "/") == null; + + if (window.location.origin !== url.origin || isDifferentBasename) { + if (replace) { + window.location.replace(redirect.location); + } else { + window.location.assign(redirect.location); + } + + return; + } + } // There's no need to abort on redirects, since we don't detect the + // redirect until the action/loaders have settled + + + pendingNavigationController = null; + let redirectHistoryAction = replace === true ? exports.Action.Replace : exports.Action.Push; // Use the incoming submission if provided, fallback on the active one in + // state.navigation + + let { + formMethod, + formAction, + formEncType, + formData + } = state.navigation; + + if (!submission && formMethod && formAction && formData && formEncType) { + submission = { + formMethod, + formAction, + formEncType, + formData + }; + } // If this was a 307/308 submission we want to preserve the HTTP method and + // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the + // redirected location + + + if (redirectPreserveMethodStatusCodes.has(redirect.status) && submission && isMutationMethod(submission.formMethod)) { + await startNavigation(redirectHistoryAction, redirectLocation, { + submission: _extends({}, submission, { + formAction: redirect.location + }), + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else if (isFetchActionRedirect) { + // For a fetch action redirect, we kick off a new loading navigation + // without the fetcher submission, but we send it along for shouldRevalidate + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined + }, + fetcherSubmission: submission, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } else { + // Otherwise, we kick off a new loading navigation, preserving the + // submission info for the duration of this navigation + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: submission ? submission.formMethod : undefined, + formAction: submission ? submission.formAction : undefined, + formEncType: submission ? submission.formEncType : undefined, + formData: submission ? submission.formData : undefined + }, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset + }); + } + } + + async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) { + // Call all navigation loaders and revalidating fetcher loaders in parallel, + // then slice off the results into separate arrays so we can handle them + // accordingly + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, router.basename)), ...fetchersToLoad.map(f => { + if (f.matches && f.match) { + return callLoaderOrAction("loader", createClientSideRequest(init.history, f.path, request.signal), f.match, f.matches, manifest, detectErrorBoundary, router.basename); + } else { + let error = { + type: ResultType.error, + error: getInternalRouterError(404, { + pathname: f.path + }) + }; + return error; + } + })]); + let loaderResults = results.slice(0, matchesToLoad.length); + let fetcherResults = results.slice(matchesToLoad.length); + await Promise.all([resolveDeferredResults(currentMatches, matchesToLoad, loaderResults, request.signal, false, state.loaderData), resolveDeferredResults(currentMatches, fetchersToLoad.map(f => f.match), fetcherResults, request.signal, true)]); + return { + results, + loaderResults, + fetcherResults + }; + } + + function interruptActiveLoads() { + // Every interruption triggers a revalidation + isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for + // revalidation + + cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads + + fetchLoadMatches.forEach((_, key) => { + if (fetchControllers.has(key)) { + cancelledFetcherLoads.push(key); + abortFetcher(key); + } + }); + } + + function setFetcherError(key, routeId, error) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + deleteFetcher(key); + updateState({ + errors: { + [boundaryMatch.route.id]: error + }, + fetchers: new Map(state.fetchers) + }); + } + + function deleteFetcher(key) { + if (fetchControllers.has(key)) abortFetcher(key); + fetchLoadMatches.delete(key); + fetchReloadIds.delete(key); + fetchRedirectIds.delete(key); + state.fetchers.delete(key); + } + + function abortFetcher(key) { + let controller = fetchControllers.get(key); + invariant(controller, "Expected fetch controller: " + key); + controller.abort(); + fetchControllers.delete(key); + } + + function markFetchersDone(keys) { + for (let key of keys) { + let fetcher = getFetcher(key); + let doneFetcher = { + state: "idle", + data: fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + function markFetchRedirectsDone() { + let doneKeys = []; + + for (let key of fetchRedirectIds) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + fetchRedirectIds.delete(key); + doneKeys.push(key); + } + } + + markFetchersDone(doneKeys); + } + + function abortStaleFetchLoads(landedId) { + let yeetedKeys = []; + + for (let [key, id] of fetchReloadIds) { + if (id < landedId) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, "Expected fetcher: " + key); + + if (fetcher.state === "loading") { + abortFetcher(key); + fetchReloadIds.delete(key); + yeetedKeys.push(key); + } + } + } + + markFetchersDone(yeetedKeys); + return yeetedKeys.length > 0; + } + + function getBlocker(key, fn) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + + if (blockerFunctions.get(key) !== fn) { + blockerFunctions.set(key, fn); + } + + return blocker; + } + + function deleteBlocker(key) { + state.blockers.delete(key); + blockerFunctions.delete(key); + } // Utility function to update blockers, ensuring valid state transitions + + + function updateBlocker(key, newBlocker) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; // Poor mans state machine :) + // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM + + invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state); + state.blockers.set(key, newBlocker); + updateState({ + blockers: new Map(state.blockers) + }); + } + + function shouldBlockNavigation(_ref2) { + let { + currentLocation, + nextLocation, + historyAction + } = _ref2; + + if (blockerFunctions.size === 0) { + return; + } // We ony support a single active blocker at the moment since we don't have + // any compelling use cases for multi-blocker yet + + + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); + + if (blocker && blocker.state === "proceeding") { + // If the blocker is currently proceeding, we don't need to re-check + // it and can let this navigation continue + return; + } // At this point, we know we're unblocked/blocked so we need to check the + // user-provided blocker function + + + if (blockerFunction({ + currentLocation, + nextLocation, + historyAction + })) { + return blockerKey; + } + } + + function cancelActiveDeferreds(predicate) { + let cancelledRouteIds = []; + activeDeferreds.forEach((dfd, routeId) => { + if (!predicate || predicate(routeId)) { + // Cancel the deferred - but do not remove from activeDeferreds here - + // we rely on the subscribers to do that so our tests can assert proper + // cleanup via _internalActiveDeferreds + dfd.cancel(); + cancelledRouteIds.push(routeId); + activeDeferreds.delete(routeId); + } + }); + return cancelledRouteIds; + } // Opt in to capturing and reporting scroll positions during navigations, + // used by the component + + + function enableScrollRestoration(positions, getPosition, getKey) { + savedScrollPositions = positions; + getScrollPosition = getPosition; + + getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on + // the initial updateState() because we've not yet rendered + // and therefore have no savedScrollPositions available + + + if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) { + initialScrollRestored = true; + let y = getSavedScrollPosition(state.location, state.matches); + + if (y != null) { + updateState({ + restoreScrollPosition: y + }); + } + } + + return () => { + savedScrollPositions = null; + getScrollPosition = null; + getScrollRestorationKey = null; + }; + } + + function saveScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + savedScrollPositions[key] = getScrollPosition(); + } + } + + function getSavedScrollPosition(location, matches) { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData)); + let key = getScrollRestorationKey(location, userMatches) || location.key; + let y = savedScrollPositions[key]; + + if (typeof y === "number") { + return y; + } + } + + return null; + } + + function _internalSetRoutes(newRoutes) { + inFlightDataRoutes = newRoutes; + } + + router = { + get basename() { + return init.basename; + }, + + get state() { + return state; + }, + + get routes() { + return dataRoutes; + }, + + initialize, + subscribe, + enableScrollRestoration, + navigate, + fetch, + revalidate, + // Passthrough to history-aware createHref used by useHref so we get proper + // hash-aware URLs in DOM paths + createHref: to => init.history.createHref(to), + encodeLocation: to => init.history.encodeLocation(to), + getFetcher, + deleteFetcher, + dispose, + getBlocker, + deleteBlocker, + _internalFetchControllers: fetchControllers, + _internalActiveDeferreds: activeDeferreds, + // TODO: Remove setRoutes, it's temporary to avoid dealing with + // updating the tree while validating the update algorithm. + _internalSetRoutes + }; + return router; + } //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region createStaticHandler + //////////////////////////////////////////////////////////////////////////////// + + const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred"); + function createStaticHandler(routes, opts) { + invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler"); + let manifest = {}; + let detectErrorBoundary = (opts == null ? void 0 : opts.detectErrorBoundary) || defaultDetectErrorBoundary; + let dataRoutes = convertRoutesToDataRoutes(routes, detectErrorBoundary, undefined, manifest); + let basename = (opts ? opts.basename : null) || "/"; + /** + * The query() method is intended for document requests, in which we want to + * call an optional action and potentially multiple loaders for all nested + * routes. It returns a StaticHandlerContext object, which is very similar + * to the router state (location, loaderData, actionData, errors, etc.) and + * also adds SSR-specific information such as the statusCode and headers + * from action/loaders Responses. + * + * It _should_ never throw and should report all errors through the + * returned context.errors object, properly associating errors to their error + * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be + * used to emulate React error boundaries during SSr by performing a second + * pass only down to the boundaryId. + * + * The one exception where we do not return a StaticHandlerContext is when a + * redirect response is returned or thrown from any action/loader. We + * propagate that out and return the raw Response so the HTTP server can + * return it directly. + */ + + async function query(request, _temp2) { + let { + requestContext + } = _temp2 === void 0 ? {} : _temp2; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD") { + let error = getInternalRouterError(405, { + method + }); + let { + matches: methodNotAllowedMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: methodNotAllowedMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } else if (!matches) { + let error = getInternalRouterError(404, { + pathname: location.pathname + }); + let { + matches: notFoundMatches, + route + } = getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: notFoundMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + let result = await queryImpl(request, location, matches, requestContext); + + if (isResponse(result)) { + return result; + } // When returning StaticHandlerContext, we patch back in the location here + // since we need it for React Context. But this helps keep our submit and + // loadRouteData operating on a Request instead of a Location + + + return _extends({ + location, + basename + }, result); + } + /** + * The queryRoute() method is intended for targeted route requests, either + * for fetch ?_data requests or resource route requests. In this case, we + * are only ever calling a single action or loader, and we are returning the + * returned value directly. In most cases, this will be a Response returned + * from the action/loader, but it may be a primitive or other value as well - + * and in such cases the calling context should handle that accordingly. + * + * We do respect the throw/return differentiation, so if an action/loader + * throws, then this method will throw the value. This is important so we + * can do proper boundary identification in Remix where a thrown Response + * must go to the Catch Boundary but a returned Response is happy-path. + * + * One thing to note is that any Router-initiated Errors that make sense + * to associate with a status code will be thrown as an ErrorResponse + * instance which include the raw Error, such that the calling context can + * serialize the error as they see fit while including the proper response + * code. Examples here are 404 and 405 errors that occur prior to reaching + * any user-defined loaders. + */ + + + async function queryRoute(request, _temp3) { + let { + routeId, + requestContext + } = _temp3 === void 0 ? {} : _temp3; + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't + + if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") { + throw getInternalRouterError(405, { + method + }); + } else if (!matches) { + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location); + + if (routeId && !match) { + throw getInternalRouterError(403, { + pathname: location.pathname, + routeId + }); + } else if (!match) { + // This should never hit I don't think? + throw getInternalRouterError(404, { + pathname: location.pathname + }); + } + + let result = await queryImpl(request, location, matches, requestContext, match); + + if (isResponse(result)) { + return result; + } + + let error = result.errors ? Object.values(result.errors)[0] : undefined; + + if (error !== undefined) { + // If we got back result.errors, that means the loader/action threw + // _something_ that wasn't a Response, but it's not guaranteed/required + // to be an `instanceof Error` either, so we have to use throw here to + // preserve the "error" state outside of queryImpl. + throw error; + } // Pick off the right state value to return + + + if (result.actionData) { + return Object.values(result.actionData)[0]; + } + + if (result.loaderData) { + var _result$activeDeferre; + + let data = Object.values(result.loaderData)[0]; + + if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) { + data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id]; + } + + return data; + } + + return undefined; + } + + async function queryImpl(request, location, matches, requestContext, routeMatch) { + invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal"); + + try { + if (isMutationMethod(request.method.toLowerCase())) { + let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null); + return result; + } + + let result = await loadRouteData(request, matches, requestContext, routeMatch); + return isResponse(result) ? result : _extends({}, result, { + actionData: null, + actionHeaders: {} + }); + } catch (e) { + // If the user threw/returned a Response in callLoaderOrAction, we throw + // it to bail out and then return or throw here based on whether the user + // returned or threw + if (isQueryRouteResponse(e)) { + if (e.type === ResultType.error && !isRedirectResponse(e.response)) { + throw e.response; + } + + return e.response; + } // Redirects are always returned since they don't propagate to catch + // boundaries + + + if (isRedirectResponse(e)) { + return e; + } + + throw e; + } + } + + async function submit(request, matches, actionMatch, requestContext, isRouteRequest) { + let result; + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + let error = getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: actionMatch.route.id + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } else { + result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } + } + + if (isRedirectResult(result)) { + // Uhhhh - this should never happen, we should always throw these from + // callLoaderOrAction, but the type narrowing here keeps TS happy and we + // can get back on the "throw all redirect responses" train here should + // this ever happen :/ + throw new Response(null, { + status: result.status, + headers: { + Location: result.location + } + }); + } + + if (isDeferredResult(result)) { + let error = getInternalRouterError(400, { + type: "defer-action" + }); + + if (isRouteRequest) { + throw error; + } + + result = { + type: ResultType.error, + error + }; + } + + if (isRouteRequest) { + // Note: This should only be non-Response values if we get here, since + // isRouteRequest should throw any Response received in callLoaderOrAction + if (isErrorResult(result)) { + throw result.error; + } + + return { + matches: [actionMatch], + loaderData: {}, + actionData: { + [actionMatch.route.id]: result.data + }, + errors: null, + // Note: statusCode + headers are unused here since queryRoute will + // return the raw Response or value + statusCode: 200, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + let context = await loadRouteData(request, matches, requestContext, undefined, { + [boundaryMatch.route.id]: result.error + }); // action status codes take precedence over loader status codes + + return _extends({}, context, { + statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500, + actionData: null, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } // Create a GET request for the loaders + + + let loaderRequest = new Request(request.url, { + headers: request.headers, + redirect: request.redirect, + signal: request.signal + }); + let context = await loadRouteData(loaderRequest, matches, requestContext); + return _extends({}, context, result.statusCode ? { + statusCode: result.statusCode + } : {}, { + actionData: { + [actionMatch.route.id]: result.data + }, + actionHeaders: _extends({}, result.headers ? { + [actionMatch.route.id]: result.headers + } : {}) + }); + } + + async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) { + let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute()) + + if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader) && !(routeMatch != null && routeMatch.route.lazy)) { + throw getInternalRouterError(400, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: routeMatch == null ? void 0 : routeMatch.route.id + }); + } + + let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]); + let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy); // Short circuit if we have no loaders to run (query()) + + if (matchesToLoad.length === 0) { + return { + matches, + // Add a null for all matched routes for proper revalidation on the client + loaderData: matches.reduce((acc, m) => Object.assign(acc, { + [m.route.id]: null + }), {}), + errors: pendingActionError || null, + statusCode: 200, + loaderHeaders: {}, + activeDeferreds: null + }; + } + + let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, detectErrorBoundary, basename, true, isRouteRequest, requestContext))]); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(method + "() call aborted"); + } // Process and commit output from loaders + + + let activeDeferreds = new Map(); + let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client + + let executedLoaders = new Set(matchesToLoad.map(match => match.route.id)); + matches.forEach(match => { + if (!executedLoaders.has(match.route.id)) { + context.loaderData[match.route.id] = null; + } + }); + return _extends({}, context, { + matches, + activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null + }); + } + + return { + dataRoutes, + query, + queryRoute + }; + } //#endregion + //////////////////////////////////////////////////////////////////////////////// + //#region Helpers + //////////////////////////////////////////////////////////////////////////////// + + /** + * Given an existing StaticHandlerContext and an error thrown at render time, + * provide an updated StaticHandlerContext suitable for a second SSR render + */ + + function getStaticContextFromError(routes, context, error) { + let newContext = _extends({}, context, { + statusCode: 500, + errors: { + [context._deepestRenderedBoundaryId || routes[0].id]: error + } + }); + + return newContext; + } + + function isSubmissionNavigation(opts) { + return opts != null && "formData" in opts; + } // Normalize navigation options by converting formMethod=GET formData objects to + // URLSearchParams so they behave identically to links with query params + + + function normalizeNavigateOptions(to, future, opts, isFetcher) { + if (isFetcher === void 0) { + isFetcher = false; + } + + let path = typeof to === "string" ? to : createPath(to); // Return location verbatim on non-submission navigations + + if (!opts || !isSubmissionNavigation(opts)) { + return { + path + }; + } + + if (opts.formMethod && !isValidMethod(opts.formMethod)) { + return { + path, + error: getInternalRouterError(405, { + method: opts.formMethod + }) + }; + } // Create a Submission on non-GET navigations + + + let submission; + + if (opts.formData) { + let formMethod = opts.formMethod || "get"; + submission = { + formMethod: future.v7_normalizeFormMethod ? formMethod.toUpperCase() : formMethod.toLowerCase(), + formAction: stripHashFromPath(path), + formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded", + formData: opts.formData + }; + + if (isMutationMethod(submission.formMethod)) { + return { + path, + submission + }; + } + } // Flatten submission onto URLSearchParams for GET submissions + + + let parsedPath = parsePath(path); + let searchParams = convertFormDataToSearchParams(opts.formData); // Since fetcher GET submissions only run a single loader (as opposed to + // navigation GET submissions which run all loaders), we need to preserve + // any incoming ?index params + + if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { + searchParams.append("index", ""); + } + + parsedPath.search = "?" + searchParams; + return { + path: createPath(parsedPath), + submission + }; + } // Filter out all routes below any caught error as they aren't going to + // render so we don't need to load them + + + function getLoaderMatchesUntilBoundary(matches, boundaryId) { + let boundaryMatches = matches; + + if (boundaryId) { + let index = matches.findIndex(m => m.route.id === boundaryId); + + if (index >= 0) { + boundaryMatches = matches.slice(0, index); + } + } + + return boundaryMatches; + } + + function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) { + let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; + let currentUrl = history.createURL(state.location); + let nextUrl = history.createURL(location); + let defaultShouldRevalidate = // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate + isRevalidationRequired || // Clicked the same link, resubmitted a GET form + currentUrl.toString() === nextUrl.toString() || // Search params affect all loaders + currentUrl.search !== nextUrl.search; // Pick navigation matches that are net-new or qualify for revalidation + + let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined; + let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId); + let navigationMatches = boundaryMatches.filter((match, index) => { + if (match.route.lazy) { + // We haven't loaded this route yet so we don't know if it's got a loader! + return true; + } + + if (match.route.loader == null) { + return false; + } // Always call the loader on new route instances and pending defer cancellations + + + if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) { + return true; + } // This is the default implementation for when we revalidate. If the route + // provides it's own implementation, then we give them full control but + // provide this value so they can leverage it if needed after they check + // their own specific use cases + + + let currentRouteMatch = state.matches[index]; + let nextRouteMatch = match; + return shouldRevalidateLoader(match, _extends({ + currentUrl, + currentParams: currentRouteMatch.params, + nextUrl, + nextParams: nextRouteMatch.params + }, submission, { + actionResult, + defaultShouldRevalidate: defaultShouldRevalidate || isNewRouteInstance(currentRouteMatch, nextRouteMatch) + })); + }); // Pick fetcher.loads that need to be revalidated + + let revalidatingFetchers = []; + fetchLoadMatches.forEach((f, key) => { + // Don't revalidate if fetcher won't be present in the subsequent render + if (!matches.some(m => m.route.id === f.routeId)) { + return; + } + + let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so + // we can trigger a 404 in callLoadersAndMaybeResolveData + + if (!fetcherMatches) { + revalidatingFetchers.push(_extends({ + key + }, f, { + matches: null, + match: null + })); + return; + } + + let fetcherMatch = getTargetMatch(fetcherMatches, f.path); + + if (cancelledFetcherLoads.includes(key)) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + return; + } // Revalidating fetchers are decoupled from the route matches since they + // hit a static href, so they _always_ check shouldRevalidate and the + // default is strictly if a revalidation is explicitly required (action + // submissions, useRevalidator, X-Remix-Revalidate). + + + let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({ + currentUrl, + currentParams: state.matches[state.matches.length - 1].params, + nextUrl, + nextParams: matches[matches.length - 1].params + }, submission, { + actionResult, + defaultShouldRevalidate + })); + + if (shouldRevalidate) { + revalidatingFetchers.push(_extends({ + key, + matches: fetcherMatches, + match: fetcherMatch + }, f)); + } + }); + return [navigationMatches, revalidatingFetchers]; + } + + function isNewLoader(currentLoaderData, currentMatch, match) { + let isNew = // [a] -> [a, b] + !currentMatch || // [a, b] -> [a, c] + match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially + // from a prior error or from a cancelled pending deferred + + let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data + + return isNew || isMissingData; + } + + function isNewRouteInstance(currentMatch, match) { + let currentPath = currentMatch.route.path; + return (// param change for this match, /users/123 -> /users/456 + currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path + // e.g. /files/images/avatar.jpg -> files/finances.xls + currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"] + ); + } + + function shouldRevalidateLoader(loaderMatch, arg) { + if (loaderMatch.route.shouldRevalidate) { + let routeChoice = loaderMatch.route.shouldRevalidate(arg); + + if (typeof routeChoice === "boolean") { + return routeChoice; + } + } + + return arg.defaultShouldRevalidate; + } + /** + * Execute route.lazy() methods to lazily load route modules (loader, action, + * shouldRevalidate) and update the routeManifest in place which shares objects + * with dataRoutes so those get updated as well. + */ + + + async function loadLazyRouteModule(route, detectErrorBoundary, manifest) { + if (!route.lazy) { + return; + } + + let lazyRoute = await route.lazy(); // If the lazy route function was executed and removed by another parallel + // call then we can return - first lazy() to finish wins because the return + // value of lazy is expected to be static + + if (!route.lazy) { + return; + } + + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); // Update the route in place. This should be safe because there's no way + // we could yet be sitting on this route as we can't get there without + // resolving lazy() first. + // + // This is different than the HMR "update" use-case where we may actively be + // on the route being updated. The main concern boils down to "does this + // mutation affect any ongoing navigations or any current state.matches + // values?". If not, it should be safe to update in place. + + let routeUpdates = {}; + + for (let lazyRouteProperty in lazyRoute) { + let staticRouteValue = routeToUpdate[lazyRouteProperty]; + let isPropertyStaticallyDefined = staticRouteValue !== undefined && // This property isn't static since it should always be updated based + // on the route updates + lazyRouteProperty !== "hasErrorBoundary"; + warning(!isPropertyStaticallyDefined, "Route \"" + routeToUpdate.id + "\" has a static property \"" + lazyRouteProperty + "\" " + "defined but its lazy function is also returning a value for this property. " + ("The lazy route property \"" + lazyRouteProperty + "\" will be ignored.")); + + if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) { + routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty]; + } + } // Mutate the route with the provided updates. Do this first so we pass + // the updated version to detectErrorBoundary + + + Object.assign(routeToUpdate, routeUpdates); // Mutate the `hasErrorBoundary` property on the route based on the route + // updates and remove the `lazy` function so we don't resolve the lazy + // route again. + + Object.assign(routeToUpdate, { + // To keep things framework agnostic, we use the provided + // `detectErrorBoundary` function to set the `hasErrorBoundary` route + // property since the logic will differ between frameworks. + hasErrorBoundary: detectErrorBoundary(_extends({}, routeToUpdate)), + lazy: undefined + }); + } + + async function callLoaderOrAction(type, request, match, matches, manifest, detectErrorBoundary, basename, isStaticRequest, isRouteRequest, requestContext) { + if (basename === void 0) { + basename = "/"; + } + + if (isStaticRequest === void 0) { + isStaticRequest = false; + } + + if (isRouteRequest === void 0) { + isRouteRequest = false; + } + + let resultType; + let result; + let onReject; + + let runHandler = handler => { + // Setup a promise we can race against so that abort signals short circuit + let reject; + let abortPromise = new Promise((_, r) => reject = r); + + onReject = () => reject(); + + request.signal.addEventListener("abort", onReject); + return Promise.race([handler({ + request, + params: match.params, + context: requestContext + }), abortPromise]); + }; + + try { + let handler = match.route[type]; + + if (match.route.lazy) { + if (handler) { + // Run statically defined handler in parallel with lazy() + let values = await Promise.all([runHandler(handler), loadLazyRouteModule(match.route, detectErrorBoundary, manifest)]); + result = values[0]; + } else { + // Load lazy route module, then run any returned handler + await loadLazyRouteModule(match.route, detectErrorBoundary, manifest); + handler = match.route[type]; + + if (handler) { + // Handler still run even if we got interrupted to maintain consistency + // with un-abortable behavior of handler execution on non-lazy or + // previously-lazy-loaded routes + result = await runHandler(handler); + } else if (type === "action") { + throw getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: match.route.id + }); + } else { + // lazy() route has no loader to run. Short circuit here so we don't + // hit the invariant below that errors on returning undefined. + return { + type: ResultType.data, + data: undefined + }; + } + } + } else { + invariant(handler, "Could not find the " + type + " to run on the \"" + match.route.id + "\" route"); + result = await runHandler(handler); + } + + invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`."); + } catch (e) { + resultType = ResultType.error; + result = e; + } finally { + if (onReject) { + request.signal.removeEventListener("abort", onReject); + } + } + + if (isResponse(result)) { + let status = result.status; // Process redirects + + if (redirectStatusCodes.has(status)) { + let location = result.headers.get("Location"); + invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header"); // Support relative routing in internal redirects + + if (!ABSOLUTE_URL_REGEX.test(location)) { + let activeMatches = matches.slice(0, matches.indexOf(match) + 1); + let routePathnames = getPathContributingMatches(activeMatches).map(match => match.pathnameBase); + let resolvedLocation = resolveTo(location, routePathnames, new URL(request.url).pathname); + invariant(createPath(resolvedLocation), "Unable to resolve redirect location: " + location); // Prepend the basename to the redirect location if we have one + + if (basename) { + let path = resolvedLocation.pathname; + resolvedLocation.pathname = path === "/" ? basename : joinPaths([basename, path]); + } + + location = createPath(resolvedLocation); + } else if (!isStaticRequest) { + // Strip off the protocol+origin for same-origin + same-basename absolute + // redirects. If this is a static request, we can let it go back to the + // browser as-is + let currentUrl = new URL(request.url); + let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location); + let isSameBasename = stripBasename(url.pathname, basename) != null; + + if (url.origin === currentUrl.origin && isSameBasename) { + location = url.pathname + url.search + url.hash; + } + } // Don't process redirects in the router during static requests requests. + // Instead, throw the Response and let the server handle it with an HTTP + // redirect. We also update the Location header in place in this flow so + // basename and relative routing is taken into account + + + if (isStaticRequest) { + result.headers.set("Location", location); + throw result; + } + + return { + type: ResultType.redirect, + status, + location, + revalidate: result.headers.get("X-Remix-Revalidate") !== null + }; + } // For SSR single-route requests, we want to hand Responses back directly + // without unwrapping. We do this with the QueryRouteResponse wrapper + // interface so we can know whether it was returned or thrown + + + if (isRouteRequest) { + // eslint-disable-next-line no-throw-literal + throw { + type: resultType || ResultType.data, + response: result + }; + } + + let data; + let contentType = result.headers.get("Content-Type"); // Check between word boundaries instead of startsWith() due to the last + // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type + + if (contentType && /\bapplication\/json\b/.test(contentType)) { + data = await result.json(); + } else { + data = await result.text(); + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: new ErrorResponse(status, result.statusText, data), + headers: result.headers + }; + } + + return { + type: ResultType.data, + data, + statusCode: result.status, + headers: result.headers + }; + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: result + }; + } + + if (isDeferredData(result)) { + var _result$init, _result$init2; + + return { + type: ResultType.deferred, + deferredData: result, + statusCode: (_result$init = result.init) == null ? void 0 : _result$init.status, + headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers) + }; + } + + return { + type: ResultType.data, + data: result + }; + } // Utility method for creating the Request instances for loaders/actions during + // client-side navigations and fetches. During SSR we will always have a + // Request instance from the static handler (query/queryRoute) + + + function createClientSideRequest(history, location, signal, submission) { + let url = history.createURL(stripHashFromPath(location)).toString(); + let init = { + signal + }; + + if (submission && isMutationMethod(submission.formMethod)) { + let { + formMethod, + formEncType, + formData + } = submission; // Didn't think we needed this but it turns out unlike other methods, patch + // won't be properly normalized to uppercase and results in a 405 error. + // See: https://fetch.spec.whatwg.org/#concept-method + + init.method = formMethod.toUpperCase(); + init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData; + } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request) + + + return new Request(url, init); + } + + function convertFormDataToSearchParams(formData) { + let searchParams = new URLSearchParams(); + + for (let [key, value] of formData.entries()) { + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs + searchParams.append(key, value instanceof File ? value.name : value); + } + + return searchParams; + } + + function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) { + // Fill in loaderData/errors from our loaders + let loaderData = {}; + let errors = null; + let statusCode; + let foundError = false; + let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors + + results.forEach((result, index) => { + let id = matchesToLoad[index].route.id; + invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData"); + + if (isErrorResult(result)) { + // Look upwards from the matched route for the closest ancestor + // error boundary, defaulting to the root match + let boundaryMatch = findNearestBoundary(matches, id); + let error = result.error; // If we have a pending action error, we report it at the highest-route + // that throws a loader error, and then clear it out to indicate that + // it was consumed + + if (pendingError) { + error = Object.values(pendingError)[0]; + pendingError = undefined; + } + + errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary + + if (errors[boundaryMatch.route.id] == null) { + errors[boundaryMatch.route.id] = error; + } // Clear our any prior loaderData for the throwing route + + + loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and + // prevent deeper status codes from overriding + + if (!foundError) { + foundError = true; + statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } else { + if (isDeferredResult(result)) { + activeDeferreds.set(id, result.deferredData); + loaderData[id] = result.deferredData.data; + } else { + loaderData[id] = result.data; + } // Error status codes always override success status codes, but if all + // loaders are successful we take the deepest status code. + + + if (result.statusCode != null && result.statusCode !== 200 && !foundError) { + statusCode = result.statusCode; + } + + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } + }); // If we didn't consume the pending action error (i.e., all loaders + // resolved), then consume it here. Also clear out any loaderData for the + // throwing route + + if (pendingError) { + errors = pendingError; + loaderData[Object.keys(pendingError)[0]] = undefined; + } + + return { + loaderData, + errors, + statusCode: statusCode || 200, + loaderHeaders + }; + } + + function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) { + let { + loaderData, + errors + } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers + + for (let index = 0; index < revalidatingFetchers.length; index++) { + let { + key, + match + } = revalidatingFetchers[index]; + invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result"); + let result = fetcherResults[index]; // Process fetcher non-redirect errors + + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id); + + if (!(errors && errors[boundaryMatch.route.id])) { + errors = _extends({}, errors, { + [boundaryMatch.route.id]: result.error + }); + } + + state.fetchers.delete(key); + } else if (isRedirectResult(result)) { + // Should never get here, redirects should get processed above, but we + // keep this to type narrow to a success result in the else + invariant(false, "Unhandled fetcher revalidation redirect"); + } else if (isDeferredResult(result)) { + // Should never get here, deferred data should be awaited for fetchers + // in resolveDeferredResults + invariant(false, "Unhandled fetcher deferred data"); + } else { + let doneFetcher = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true + }; + state.fetchers.set(key, doneFetcher); + } + } + + return { + loaderData, + errors + }; + } + + function mergeLoaderData(loaderData, newLoaderData, matches, errors) { + let mergedLoaderData = _extends({}, newLoaderData); + + for (let match of matches) { + let id = match.route.id; + + if (newLoaderData.hasOwnProperty(id)) { + if (newLoaderData[id] !== undefined) { + mergedLoaderData[id] = newLoaderData[id]; + } + } else if (loaderData[id] !== undefined && match.route.loader) { + // Preserve existing keys not included in newLoaderData and where a loader + // wasn't removed by HMR + mergedLoaderData[id] = loaderData[id]; + } + + if (errors && errors.hasOwnProperty(id)) { + // Don't keep any loader data below the boundary + break; + } + } + + return mergedLoaderData; + } // Find the nearest error boundary, looking upwards from the leaf route (or the + // route specified by routeId) for the closest ancestor error boundary, + // defaulting to the root match + + + function findNearestBoundary(matches, routeId) { + let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches]; + return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0]; + } + + function getShortCircuitMatches(routes) { + // Prefer a root layout route if present, otherwise shim in a route object + let route = routes.find(r => r.index || !r.path || r.path === "/") || { + id: "__shim-error-route__" + }; + return { + matches: [{ + params: {}, + pathname: "", + pathnameBase: "", + route + }], + route + }; + } + + function getInternalRouterError(status, _temp4) { + let { + pathname, + routeId, + method, + type + } = _temp4 === void 0 ? {} : _temp4; + let statusText = "Unknown Server Error"; + let errorMessage = "Unknown @remix-run/router error"; + + if (status === 400) { + statusText = "Bad Request"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (type === "defer-action") { + errorMessage = "defer() is not supported in actions"; + } + } else if (status === 403) { + statusText = "Forbidden"; + errorMessage = "Route \"" + routeId + "\" does not match URL \"" + pathname + "\""; + } else if (status === 404) { + statusText = "Not Found"; + errorMessage = "No route matches URL \"" + pathname + "\""; + } else if (status === 405) { + statusText = "Method Not Allowed"; + + if (method && pathname && routeId) { + errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request."; + } else if (method) { + errorMessage = "Invalid request method \"" + method.toUpperCase() + "\""; + } + } + + return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true); + } // Find any returned redirect errors, starting from the lowest match + + + function findRedirect(results) { + for (let i = results.length - 1; i >= 0; i--) { + let result = results[i]; + + if (isRedirectResult(result)) { + return result; + } + } + } + + function stripHashFromPath(path) { + let parsedPath = typeof path === "string" ? parsePath(path) : path; + return createPath(_extends({}, parsedPath, { + hash: "" + })); + } + + function isHashChangeOnly(a, b) { + return a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash; + } + + function isDeferredResult(result) { + return result.type === ResultType.deferred; + } + + function isErrorResult(result) { + return result.type === ResultType.error; + } + + function isRedirectResult(result) { + return (result && result.type) === ResultType.redirect; + } + + function isDeferredData(value) { + let deferred = value; + return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function"; + } + + function isResponse(value) { + return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; + } + + function isRedirectResponse(result) { + if (!isResponse(result)) { + return false; + } + + let status = result.status; + let location = result.headers.get("Location"); + return status >= 300 && status <= 399 && location != null; + } + + function isQueryRouteResponse(obj) { + return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error); + } + + function isValidMethod(method) { + return validRequestMethods.has(method.toLowerCase()); + } + + function isMutationMethod(method) { + return validMutationMethods.has(method.toLowerCase()); + } + + async function resolveDeferredResults(currentMatches, matchesToLoad, results, signal, isFetcher, currentLoaderData) { + for (let index = 0; index < results.length; index++) { + let result = results[index]; + let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do + // anything with. This is for revalidating fetchers where the route was + // removed during HMR + + if (!match) { + continue; + } + + let currentMatch = currentMatches.find(m => m.route.id === match.route.id); + let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined; + + if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) { + // Note: we do not have to touch activeDeferreds here since we race them + // against the signal in resolveDeferredData and they'll get aborted + // there if needed + await resolveDeferredData(result, signal, isFetcher).then(result => { + if (result) { + results[index] = result || results[index]; + } + }); + } + } + } + + async function resolveDeferredData(result, signal, unwrap) { + if (unwrap === void 0) { + unwrap = false; + } + + let aborted = await result.deferredData.resolveData(signal); + + if (aborted) { + return; + } + + if (unwrap) { + try { + return { + type: ResultType.data, + data: result.deferredData.unwrappedData + }; + } catch (e) { + // Handle any TrackedPromise._error values encountered while unwrapping + return { + type: ResultType.error, + error: e + }; + } + } + + return { + type: ResultType.data, + data: result.deferredData.data + }; + } + + function hasNakedIndexQuery(search) { + return new URLSearchParams(search).getAll("index").some(v => v === ""); + } // Note: This should match the format exported by useMatches, so if you change + // this please also change that :) Eventually we'll DRY this up + + + function createUseMatchesMatch(match, loaderData) { + let { + route, + pathname, + params + } = match; + return { + id: route.id, + pathname, + params, + data: loaderData[route.id], + handle: route.handle + }; + } + + function getTargetMatch(matches, location) { + let search = typeof location === "string" ? parsePath(location).search : location.search; + + if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) { + // Return the leaf index route when index is present + return matches[matches.length - 1]; + } // Otherwise grab the deepest "path contributing" match (ignoring index and + // pathless layout routes) + + + let pathMatches = getPathContributingMatches(matches); + return pathMatches[pathMatches.length - 1]; + } //#endregion + + exports.AbortedDeferredError = AbortedDeferredError; + exports.ErrorResponse = ErrorResponse; + exports.IDLE_BLOCKER = IDLE_BLOCKER; + exports.IDLE_FETCHER = IDLE_FETCHER; + exports.IDLE_NAVIGATION = IDLE_NAVIGATION; + exports.UNSAFE_DEFERRED_SYMBOL = UNSAFE_DEFERRED_SYMBOL; + exports.UNSAFE_DeferredData = DeferredData; + exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes; + exports.UNSAFE_getPathContributingMatches = getPathContributingMatches; + exports.UNSAFE_invariant = invariant; + exports.UNSAFE_warning = warning; + exports.createBrowserHistory = createBrowserHistory; + exports.createHashHistory = createHashHistory; + exports.createMemoryHistory = createMemoryHistory; + exports.createPath = createPath; + exports.createRouter = createRouter; + exports.createStaticHandler = createStaticHandler; + exports.defer = defer; + exports.generatePath = generatePath; + exports.getStaticContextFromError = getStaticContextFromError; + exports.getToPathname = getToPathname; + exports.isDeferredData = isDeferredData; + exports.isRouteErrorResponse = isRouteErrorResponse; + exports.joinPaths = joinPaths; + exports.json = json; + exports.matchPath = matchPath; + exports.matchRoutes = matchRoutes; + exports.normalizePathname = normalizePathname; + exports.parsePath = parsePath; + exports.redirect = redirect; + exports.resolvePath = resolvePath; + exports.resolveTo = resolveTo; + exports.stripBasename = stripBasename; + + Object.defineProperty(exports, '__esModule', { value: true }); + +})); +//# sourceMappingURL=router.umd.js.map diff --git a/node_modules/@remix-run/router/dist/router.umd.js.map b/node_modules/@remix-run/router/dist/router.umd.js.map new file mode 100644 index 00000000..05107846 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"router.umd.js","sources":["../history.ts","../utils.ts","../router.ts"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nexport enum Action {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Pop = \"POP\",\n\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Push = \"PUSH\",\n\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Replace = \"REPLACE\",\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\nexport interface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * An entry in a history stack. A location contains information about the\n * URL path, as well as possibly some arbitrary state and a key.\n */\nexport interface Location extends Path {\n /**\n * A value of arbitrary data associated with this location.\n */\n state: any;\n\n /**\n * A unique string associated with this location. May be used to safely store\n * and retrieve data in some other storage API, like `localStorage`.\n *\n * Note: This value is always \"default\" on the initial location.\n */\n key: string;\n}\n\n/**\n * A change to the current location.\n */\nexport interface Update {\n /**\n * The action that triggered the change.\n */\n action: Action;\n\n /**\n * The new location.\n */\n location: Location;\n\n /**\n * The delta between this location and the former location in the history stack\n */\n delta: number | null;\n}\n\n/**\n * A function that receives notifications about location changes.\n */\nexport interface Listener {\n (update: Update): void;\n}\n\n/**\n * Describes a location that is the destination of some navigation, either via\n * `history.push` or `history.replace`. May be either a URL or the pieces of a\n * URL path.\n */\nexport type To = string | Partial;\n\n/**\n * A history is an interface to the navigation stack. The history serves as the\n * source of truth for the current location, as well as provides a set of\n * methods that may be used to change it.\n *\n * It is similar to the DOM's `window.history` object, but with a smaller, more\n * focused API.\n */\nexport interface History {\n /**\n * The last action that modified the current location. This will always be\n * Action.Pop when a history instance is first created. This value is mutable.\n */\n readonly action: Action;\n\n /**\n * The current location. This value is mutable.\n */\n readonly location: Location;\n\n /**\n * Returns a valid href for the given `to` value that may be used as\n * the value of an attribute.\n *\n * @param to - The destination URL\n */\n createHref(to: To): string;\n\n /**\n * Returns a URL for the given `to` value\n *\n * @param to - The destination URL\n */\n createURL(to: To): URL;\n\n /**\n * Encode a location the same way window.history would do (no-op for memory\n * history) so we ensure our PUSH/REPLACE navigations for data routers\n * behave the same as POP\n *\n * @param to Unencoded path\n */\n encodeLocation(to: To): Path;\n\n /**\n * Pushes a new location onto the history stack, increasing its length by one.\n * If there were any entries in the stack after the current one, they are\n * lost.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n push(to: To, state?: any): void;\n\n /**\n * Replaces the current location in the history stack with a new one. The\n * location that was replaced will no longer be available.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n replace(to: To, state?: any): void;\n\n /**\n * Navigates `n` entries backward/forward in the history stack relative to the\n * current index. For example, a \"back\" navigation would use go(-1).\n *\n * @param delta - The delta in the stack index\n */\n go(delta: number): void;\n\n /**\n * Sets up a listener that will be called whenever the current location\n * changes.\n *\n * @param listener - A function that will be called when the location changes\n * @returns unlisten - A function that may be used to stop listening\n */\n listen(listener: Listener): () => void;\n}\n\ntype HistoryState = {\n usr: any;\n key?: string;\n idx: number;\n};\n\nconst PopStateEventType = \"popstate\";\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Memory History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A user-supplied object that describes a location. Used when providing\n * entries to `createMemoryHistory` via its `initialEntries` option.\n */\nexport type InitialEntry = string | Partial;\n\nexport type MemoryHistoryOptions = {\n initialEntries?: InitialEntry[];\n initialIndex?: number;\n v5Compat?: boolean;\n};\n\n/**\n * A memory history stores locations in memory. This is useful in stateful\n * environments where there is no web browser, such as node tests or React\n * Native.\n */\nexport interface MemoryHistory extends History {\n /**\n * The current index in the history stack.\n */\n readonly index: number;\n}\n\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nexport function createMemoryHistory(\n options: MemoryHistoryOptions = {}\n): MemoryHistory {\n let { initialEntries = [\"/\"], initialIndex, v5Compat = false } = options;\n let entries: Location[]; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) =>\n createMemoryLocation(\n entry,\n typeof entry === \"string\" ? null : entry.state,\n index === 0 ? \"default\" : undefined\n )\n );\n let index = clampIndex(\n initialIndex == null ? entries.length - 1 : initialIndex\n );\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n function clampIndex(n: number): number {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation(): Location {\n return entries[index];\n }\n function createMemoryLocation(\n to: To,\n state: any = null,\n key?: string\n ): Location {\n let location = createLocation(\n entries ? getCurrentLocation().pathname : \"/\",\n to,\n state,\n key\n );\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in memory history: ${JSON.stringify(\n to\n )}`\n );\n return location;\n }\n\n function createHref(to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n let history: MemoryHistory = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to: To) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\",\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 1 });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 0 });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({ action, location: nextLocation, delta });\n }\n },\n listen(fn: Listener) {\n listener = fn;\n return () => {\n listener = null;\n };\n },\n };\n\n return history;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Browser History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A browser history stores the current location in regular URLs in a web\n * browser environment. This is the standard for most web apps and provides the\n * cleanest URLs the browser's address bar.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory\n */\nexport interface BrowserHistory extends UrlHistory {}\n\nexport type BrowserHistoryOptions = UrlHistoryOptions;\n\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nexport function createBrowserHistory(\n options: BrowserHistoryOptions = {}\n): BrowserHistory {\n function createBrowserLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let { pathname, search, hash } = window.location;\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createBrowserHref(window: Window, to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(\n createBrowserLocation,\n createBrowserHref,\n null,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Hash History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A hash history stores the current location in the fragment identifier portion\n * of the URL in a web browser environment.\n *\n * This is ideal for apps that do not control the server for some reason\n * (because the fragment identifier is never sent to the server), including some\n * shared hosting environments that do not provide fine-grained controls over\n * which pages are served at which URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory\n */\nexport interface HashHistory extends UrlHistory {}\n\nexport type HashHistoryOptions = UrlHistoryOptions;\n\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nexport function createHashHistory(\n options: HashHistoryOptions = {}\n): HashHistory {\n function createHashLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createHashHref(window: Window, to: To) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location: Location, to: To) {\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in hash history.push(${JSON.stringify(\n to\n )})`\n );\n }\n\n return getUrlBasedHistory(\n createHashLocation,\n createHashHref,\n validateHashLocation,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region UTILS\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * @private\n */\nexport function invariant(value: boolean, message?: string): asserts value;\nexport function invariant(\n value: T | null | undefined,\n message?: string\n): asserts value is T;\nexport function invariant(value: any, message?: string) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nexport function warning(cond: any, message: string) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location: Location, index: number): HistoryState {\n return {\n usr: location.state,\n key: location.key,\n idx: index,\n };\n}\n\n/**\n * Creates a Location object with a unique key from the given Path\n */\nexport function createLocation(\n current: string | Location,\n to: To,\n state: any = null,\n key?: string\n): Readonly {\n let location: Readonly = {\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\",\n ...(typeof to === \"string\" ? parsePath(to) : to),\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: (to && (to as Location).key) || key || createKey(),\n };\n return location;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial {\n let parsedPath: Partial = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\nexport interface UrlHistory extends History {}\n\nexport type UrlHistoryOptions = {\n window?: Window;\n v5Compat?: boolean;\n};\n\nfunction getUrlBasedHistory(\n getLocation: (window: Window, globalHistory: Window[\"history\"]) => Location,\n createHref: (window: Window, to: To) => string,\n validateLocation: ((location: Location, to: To) => void) | null,\n options: UrlHistoryOptions = {}\n): UrlHistory {\n let { window = document.defaultView!, v5Compat = false } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n let index = getIndex()!;\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState({ ...globalHistory.state, idx: index }, \"\");\n }\n\n function getIndex(): number {\n let state = globalHistory.state || { idx: null };\n return state.idx;\n }\n\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({ action, location: history.location, delta });\n }\n }\n\n function push(to: To, state?: any) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 1 });\n }\n }\n\n function replace(to: To, state?: any) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 0 });\n }\n }\n\n function createURL(to: To): URL {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base =\n window.location.origin !== \"null\"\n ? window.location.origin\n : window.location.href;\n\n let href = typeof to === \"string\" ? to : createPath(to);\n invariant(\n base,\n `No window.location.(origin|href) available to create URL for href: ${href}`\n );\n return new URL(href, base);\n }\n\n let history: History = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn: Listener) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n },\n };\n\n return history;\n}\n\n//#endregion\n","import type { Location, Path, To } from \"./history\";\nimport { warning, invariant, parsePath } from \"./history\";\n\n/**\n * Map of routeId -> data returned from a loader/action/error\n */\nexport interface RouteData {\n [routeId: string]: any;\n}\n\nexport enum ResultType {\n data = \"data\",\n deferred = \"deferred\",\n redirect = \"redirect\",\n error = \"error\",\n}\n\n/**\n * Successful result from a loader or action\n */\nexport interface SuccessResult {\n type: ResultType.data;\n data: any;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Successful defer() result from a loader or action\n */\nexport interface DeferredResult {\n type: ResultType.deferred;\n deferredData: DeferredData;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Redirect result from a loader or action\n */\nexport interface RedirectResult {\n type: ResultType.redirect;\n status: number;\n location: string;\n revalidate: boolean;\n}\n\n/**\n * Unsuccessful result from a loader or action\n */\nexport interface ErrorResult {\n type: ResultType.error;\n error: any;\n headers?: Headers;\n}\n\n/**\n * Result from a loader or action - potentially successful or unsuccessful\n */\nexport type DataResult =\n | SuccessResult\n | DeferredResult\n | RedirectResult\n | ErrorResult;\n\ntype LowerCaseFormMethod = \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\ntype UpperCaseFormMethod = Uppercase;\n\n/**\n * Users can specify either lowercase or uppercase form methods on ,\n * useSubmit(), , etc.\n */\nexport type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;\n\n/**\n * Active navigation/fetcher form methods are exposed in lowercase on the\n * RouterState\n */\nexport type FormMethod = LowerCaseFormMethod;\nexport type MutationFormMethod = Exclude;\n\n/**\n * In v7, active navigation/fetcher form methods are exposed in uppercase on the\n * RouterState. This is to align with the normalization done via fetch().\n */\nexport type V7_FormMethod = UpperCaseFormMethod;\nexport type V7_MutationFormMethod = Exclude;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\";\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n}\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: any;\n}\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Route loader function signature\n */\nexport interface LoaderFunction {\n (args: LoaderFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n formData?: Submission[\"formData\"];\n actionResult?: DataResult;\n defaultShouldRevalidate: boolean;\n }): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set `hasErrorBoundary`\n * from the framework-aware `errorElement` prop\n */\nexport interface DetectErrorBoundaryFunction {\n (route: AgnosticRouteObject): boolean;\n}\n\n/**\n * Keys we cannot change from within a lazy() function. We spread all other keys\n * onto the route. Either they're meaningful to the router, or they'll get\n * ignored.\n */\nexport type ImmutableRouteKey =\n | \"lazy\"\n | \"caseSensitive\"\n | \"path\"\n | \"id\"\n | \"index\"\n | \"children\";\n\nexport const immutableRouteKeys = new Set([\n \"lazy\",\n \"caseSensitive\",\n \"path\",\n \"id\",\n \"index\",\n \"children\",\n]);\n\n/**\n * lazy() function to load a route definition, which can add non-matching\n * related properties to a route\n */\nexport interface LazyRouteFunction {\n (): Promise>;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n lazy?: LazyRouteFunction;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\nexport type RouteManifest = Record;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\ntype PathParam =\n // check if path is just a wildcard\n Path extends \"*\" | \"/*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n detectErrorBoundary: DetectErrorBoundaryFunction,\n parentPath: number[] = [],\n manifest: RouteManifest = {}\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !manifest[id],\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = {\n ...route,\n hasErrorBoundary: detectErrorBoundary(route),\n id,\n };\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n id,\n hasErrorBoundary: detectErrorBoundary(route),\n children: undefined,\n };\n manifest[id] = pathOrLayoutRoute;\n\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(\n route.children,\n detectErrorBoundary,\n treePath,\n manifest\n );\n }\n\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path: string = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n\n const segments = path\n .split(/\\/+/)\n .map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\" as PathParam;\n const starParam = params[star];\n\n // Apply the splat\n return starParam;\n }\n\n const keyMatch = segment.match(/^:(\\w+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key as PathParam];\n\n if (optional === \"?\") {\n return param == null ? \"\" : param;\n }\n\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n\n return param;\n }\n\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter((segment) => !!segment);\n\n return prefix + segments.join(\"/\");\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, paramNames] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = paramNames.reduce>(\n (memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(\n captureGroups[index] || \"\",\n paramName\n );\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, string[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let paramNames: string[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_: string, paramName: string) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, null, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n if (error) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\nexport class ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n error?: Error;\n internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n warning,\n} from \"./history\";\nimport type {\n DataResult,\n DeferredData,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n DeferredResult,\n ErrorResult,\n FormEncType,\n FormMethod,\n DetectErrorBoundaryFunction,\n RedirectResult,\n RouteData,\n AgnosticRouteObject,\n Submission,\n SuccessResult,\n AgnosticRouteMatch,\n ShouldRevalidateFunction,\n RouteManifest,\n ImmutableRouteKey,\n ActionFunction,\n LoaderFunction,\n V7_MutationFormMethod,\n V7_FormMethod,\n HTMLFormMethod,\n MutationFormMethod,\n} from \"./utils\";\nimport {\n ErrorResponse,\n ResultType,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n immutableRouteKeys,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n stripBasename,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterNavigateOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key?: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key?: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * HMR needs to pass in-flight route updates to React Router\n * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)\n */\n _internalSetRoutes(routes: AgnosticRouteObject[]): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface FutureConfig {\n v7_normalizeFormMethod: boolean;\n}\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n routes: AgnosticRouteObject[];\n history: History;\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n future?: FutureConfig;\n hydrationData?: HydrationState;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (state: RouterState): void;\n}\n\ninterface UseMatchesMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: unknown;\n handle: unknown;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UseMatchesMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\n/**\n * Options for a navigate() call for a Link navigation\n */\ntype LinkNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n};\n\n/**\n * Options for a navigate() call for a Form navigation\n */\ntype SubmissionNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n formMethod?: HTMLFormMethod;\n formEncType?: FormEncType;\n formData: FormData;\n};\n\n/**\n * Options to pass to navigate() for either a Link or Form navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions =\n | Omit\n | Omit;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Loading: {\n state: \"loading\";\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n match: AgnosticDataRouteMatch | null;\n matches: AgnosticDataRouteMatch[] | null;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst isBrowser =\n typeof window !== \"undefined\" &&\n typeof window.document !== \"undefined\" &&\n typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser;\n\nconst defaultDetectErrorBoundary = (route: AgnosticRouteObject) =>\n Boolean(route.hasErrorBoundary);\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let detectErrorBoundary =\n init.detectErrorBoundary || defaultDetectErrorBoundary;\n\n // Routes keyed by ID\n let manifest: RouteManifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(\n init.routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined;\n // Config driven behavior flags\n let future: FutureConfig = {\n v7_normalizeFormMethod: false,\n ...init.future,\n };\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(\n dataRoutes,\n init.history.location,\n init.basename\n );\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized =\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n !initialMatches.some((m) => m.route.lazy) &&\n // And we have to either have no loaders or have been provided hydrationData\n (!initialMatches.some((m) => m.route.loader) || init.hydrationData != null);\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations from their actions\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(router.state.blockers) });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location);\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(newState: Partial): void {\n state = {\n ...state,\n ...newState,\n };\n subscribers.forEach((subscriber) => subscriber(state));\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n for (let [key] of blockerFunctions) {\n deleteBlocker(key);\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n\n updateState({\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers: new Map(state.blockers),\n });\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(\n to,\n future,\n opts\n );\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(state.blockers) });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n submission?: Submission;\n fetcherSubmission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponse;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, init.basename);\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n });\n return;\n }\n\n // Short circuit if it's only a hash change and not a mutation submission\n // For example, on /page#hash and submit a which will\n // default to a navigation to /page\n if (\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n ...opts.submission,\n };\n loadingNavigation = navigation;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.fetcherSubmission,\n opts && opts.replace,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts?: { replace?: boolean }\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n ...submission,\n };\n updateState({ navigation });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n fetcherSubmission?: Submission,\n replace?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n if (!loadingNavigation) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n };\n loadingNavigation = navigation;\n }\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission =\n submission || fetcherSubmission\n ? submission || fetcherSubmission\n : loadingNavigation.formMethod &&\n loadingNavigation.formAction &&\n loadingNavigation.formData &&\n loadingNavigation.formEncType\n ? {\n formMethod: loadingNavigation.formMethod,\n formAction: loadingNavigation.formAction,\n formData: loadingNavigation.formData,\n formEncType: loadingNavigation.formEncType,\n }\n : undefined;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n pendingActionData,\n pendingError\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n });\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState({\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n });\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach((rf) =>\n fetchControllers.set(rf.key, pendingNavigationController!)\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n await startRedirectNavigation(state, redirect, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n\n return {\n loaderData,\n errors,\n ...(didAbortFetchLoads || revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n };\n }\n\n function getFetcher(key: string): Fetcher {\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches = matchRoutes(routesToUse, href, init.basename);\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: href })\n );\n return;\n }\n\n let { path, submission } = normalizeNavigateOptions(\n href,\n future,\n opts,\n true\n );\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path });\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action && !match.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error);\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, fetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n ...submission,\n data: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n return startRedirectNavigation(state, actionResult, {\n submission,\n isFetchActionRedirect: true,\n });\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n\n nextLocation,\n abortController.signal\n );\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(routesToUse, state.navigation.location, init.basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: actionResult.data,\n ...submission,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n { [match.route.id]: actionResult.data },\n undefined // No need to send through errors since we short circuit above\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n\n let didAbortFetchLoads = abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n // Put this fetcher into it's loading state\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key);\n // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error,\n },\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n replace,\n isFetchActionRedirect,\n }: {\n submission?: Submission;\n replace?: boolean;\n isFetchActionRedirect?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(\n state.location,\n redirect.location,\n // TODO: This can be removed once we get rid of useTransition in Remix v2\n {\n _isRedirect: true,\n ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}),\n }\n );\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n // Check if this an absolute external redirect that goes to a new origin\n if (\n ABSOLUTE_URL_REGEX.test(redirect.location) &&\n isBrowser &&\n typeof window?.location !== \"undefined\"\n ) {\n let url = init.history.createURL(redirect.location);\n let isDifferentBasename =\n stripBasename(url.pathname, init.basename || \"/\") == null;\n\n if (window.location.origin !== url.origin || isDifferentBasename) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType, formData } = state.navigation;\n if (!submission && formMethod && formAction && formData && formEncType) {\n submission = {\n formMethod,\n formAction,\n formEncType,\n formData,\n };\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n submission &&\n isMutationMethod(submission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...submission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else if (isFetchActionRedirect) {\n // For a fetch action redirect, we kick off a new loading navigation\n // without the fetcher submission, but we send it along for shouldRevalidate\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n },\n fetcherSubmission: submission,\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: submission ? submission.formMethod : undefined,\n formAction: submission ? submission.formAction : undefined,\n formEncType: submission ? submission.formEncType : undefined,\n formData: submission ? submission.formData : undefined,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n )\n ),\n ...fetchersToLoad.map((f) => {\n if (f.matches && f.match) {\n return callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, request.signal),\n f.match,\n f.matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n } else {\n let error: ErrorResult = {\n type: ResultType.error,\n error: getInternalRouterError(404, { pathname: f.path }),\n };\n return error;\n }\n }),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n request.signal,\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n request.signal,\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key: string, routeId: string, error: any) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n });\n }\n\n function deleteFetcher(key: string): void {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): void {\n let doneKeys = [];\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n state.blockers.set(key, newBlocker);\n updateState({ blockers: new Map(state.blockers) });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || ((location) => location.key);\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) {\n inFlightDataRoutes = newRoutes;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\nexport interface CreateStaticHandlerOptions {\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n}\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: CreateStaticHandlerOptions\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let manifest: RouteManifest = {};\n let detectErrorBoundary =\n opts?.detectErrorBoundary || defaultDetectErrorBoundary;\n let dataRoutes = convertRoutesToDataRoutes(\n routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let basename = (opts ? opts.basename : null) || \"/\";\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (\n isRouteRequest &&\n !routeMatch?.route.loader &&\n !routeMatch?.route.lazy\n ) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter(\n (m) => m.route.loader || m.route.lazy\n );\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: RouterNavigateOptions\n): opts is SubmissionNavigateOptions {\n return opts != null && \"formData\" in opts;\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n to: To,\n future: FutureConfig,\n opts?: RouterNavigateOptions,\n isFetcher = false\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponse;\n} {\n let path = typeof to === \"string\" ? to : createPath(to);\n\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n // Create a Submission on non-GET navigations\n let submission: Submission | undefined;\n if (opts.formData) {\n let formMethod = opts.formMethod || \"get\";\n submission = {\n formMethod: future.v7_normalizeFormMethod\n ? (formMethod.toUpperCase() as V7_FormMethod)\n : (formMethod.toLowerCase() as FormMethod),\n formAction: stripHashFromPath(path),\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData: opts.formData,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n let searchParams = convertFormDataToSearchParams(opts.formData);\n // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n fetchLoadMatches: Map,\n routesToUse: AgnosticDataRouteObject[],\n basename: string | undefined,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n let defaultShouldRevalidate =\n // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search;\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n if (match.route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n if (match.route.loader == null) {\n return false;\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n defaultShouldRevalidate ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate if fetcher won't be present in the subsequent render\n if (!matches.some((m) => m.route.id === f.routeId)) {\n return;\n }\n\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData\n if (!fetcherMatches) {\n revalidatingFetchers.push({ key, ...f, matches: null, match: null });\n return;\n }\n\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n\n if (cancelledFetcherLoads.includes(key)) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n return;\n }\n\n // Revalidating fetchers are decoupled from the route matches since they\n // hit a static href, so they _always_ check shouldRevalidate and the\n // default is strictly if a revalidation is explicitly required (action\n // submissions, useRevalidator, X-Remix-Revalidate).\n let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate,\n });\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: Parameters[0]\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(\n route: AgnosticDataRouteObject,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n manifest: RouteManifest\n) {\n if (!route.lazy) {\n return;\n }\n\n let lazyRoute = await route.lazy();\n\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates: Record = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue =\n routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];\n\n let isPropertyStaticallyDefined =\n staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n\n warning(\n !isPropertyStaticallyDefined,\n `Route \"${routeToUpdate.id}\" has a static property \"${lazyRouteProperty}\" ` +\n `defined but its lazy function is also returning a value for this property. ` +\n `The lazy route property \"${lazyRouteProperty}\" will be ignored.`\n );\n\n if (\n !isPropertyStaticallyDefined &&\n !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey)\n ) {\n routeUpdates[lazyRouteProperty] =\n lazyRoute[lazyRouteProperty as keyof typeof lazyRoute];\n }\n }\n\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to detectErrorBoundary\n Object.assign(routeToUpdate, routeUpdates);\n\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, {\n // To keep things framework agnostic, we use the provided\n // `detectErrorBoundary` function to set the `hasErrorBoundary` route\n // property since the logic will differ between frameworks.\n hasErrorBoundary: detectErrorBoundary({ ...routeToUpdate }),\n lazy: undefined,\n });\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n manifest: RouteManifest,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n basename = \"/\",\n isStaticRequest: boolean = false,\n isRouteRequest: boolean = false,\n requestContext?: unknown\n): Promise {\n let resultType;\n let result;\n let onReject: (() => void) | undefined;\n\n let runHandler = (handler: ActionFunction | LoaderFunction) => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n return Promise.race([\n handler({ request, params: match.params, context: requestContext }),\n abortPromise,\n ]);\n };\n\n try {\n let handler = match.route[type];\n\n if (match.route.lazy) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let values = await Promise.all([\n runHandler(handler),\n loadLazyRouteModule(match.route, detectErrorBoundary, manifest),\n ]);\n result = values[0];\n } else {\n // Load lazy route module, then run any returned handler\n await loadLazyRouteModule(match.route, detectErrorBoundary, manifest);\n\n handler = match.route[type];\n if (handler) {\n // Handler still run even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n throw getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: match.route.id,\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return { type: ResultType.data, data: undefined };\n }\n }\n } else {\n invariant(\n handler,\n `Could not find the ${type} to run on the \"${match.route.id}\" route`\n );\n\n result = await runHandler(handler);\n }\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(\n (match) => match.pathnameBase\n );\n let resolvedLocation = resolveTo(\n location,\n routePathnames,\n new URL(request.url).pathname\n );\n invariant(\n createPath(resolvedLocation),\n `Unable to resolve redirect location: ${location}`\n );\n\n // Prepend the basename to the redirect location if we have one\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname =\n path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } else if (!isStaticRequest) {\n // Strip off the protocol+origin for same-origin + same-basename absolute\n // redirects. If this is a static request, we can let it go back to the\n // browser as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result,\n };\n }\n\n let data: any;\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (isDeferredData(result)) {\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: result.init?.status,\n headers: result.init?.headers && new Headers(result.init.headers),\n };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType, formData } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n init.body =\n formEncType === \"application/x-www-form-urlencoded\"\n ? convertFormDataToSearchParams(formData)\n : formData;\n }\n\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, value instanceof File ? value.name : value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponse(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results: DataResult[]): RedirectResult | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n return (\n a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash\n );\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nexport function isDeferredData(value: any): value is DeferredData {\n let deferred: DeferredData = value;\n return (\n deferred &&\n typeof deferred === \"object\" &&\n typeof deferred.data === \"object\" &&\n typeof deferred.subscribe === \"function\" &&\n typeof deferred.cancel === \"function\" &&\n typeof deferred.resolveData === \"function\"\n );\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod | V7_FormMethod {\n return validRequestMethods.has(method.toLowerCase() as FormMethod);\n}\n\nfunction isMutationMethod(\n method: string\n): method is MutationFormMethod | V7_MutationFormMethod {\n return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: (AgnosticDataRouteMatch | null)[],\n results: DataResult[],\n signal: AbortSignal,\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match!.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\n// Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\nfunction createUseMatchesMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UseMatchesMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id] as unknown,\n handle: route.handle as unknown,\n };\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n//#endregion\n"],"names":["Action","PopStateEventType","createMemoryHistory","options","initialEntries","initialIndex","v5Compat","entries","map","entry","index","createMemoryLocation","state","undefined","clampIndex","length","action","Pop","listener","n","Math","min","max","getCurrentLocation","to","key","location","createLocation","pathname","warning","charAt","JSON","stringify","createHref","createPath","history","createURL","URL","encodeLocation","path","parsePath","search","hash","push","Push","nextLocation","splice","delta","replace","Replace","go","nextIndex","listen","fn","createBrowserHistory","createBrowserLocation","window","globalHistory","usr","createBrowserHref","getUrlBasedHistory","createHashHistory","createHashLocation","substr","createHashHref","base","document","querySelector","href","getAttribute","url","hashIndex","indexOf","slice","validateHashLocation","invariant","value","message","Error","cond","console","warn","e","createKey","random","toString","getHistoryState","idx","current","parsedPath","searchIndex","getLocation","validateLocation","defaultView","getIndex","replaceState","handlePop","historyState","pushState","error","assign","origin","addEventListener","removeEventListener","ResultType","immutableRouteKeys","Set","isIndexRoute","route","convertRoutesToDataRoutes","routes","detectErrorBoundary","parentPath","manifest","treePath","id","join","children","indexRoute","hasErrorBoundary","pathOrLayoutRoute","matchRoutes","locationArg","basename","stripBasename","branches","flattenRoutes","rankRouteBranches","matches","i","matchRouteBranch","safelyDecodeURI","parentsMeta","flattenRoute","relativePath","meta","caseSensitive","childrenIndex","startsWith","joinPaths","routesMeta","concat","score","computeScore","forEach","includes","exploded","explodeOptionalSegments","segments","split","first","rest","isOptional","endsWith","required","restExploded","result","subpath","sort","a","b","compareIndexes","paramRe","dynamicSegmentValue","indexRouteValue","emptySegmentValue","staticSegmentValue","splatPenalty","isSplat","s","initialScore","some","filter","reduce","segment","test","siblings","every","branch","matchedParams","matchedPathname","end","remainingPathname","match","matchPath","Object","params","pathnameBase","normalizePathname","generatePath","originalPath","prefix","array","isLastSegment","star","starParam","keyMatch","optional","param","pattern","matcher","paramNames","compilePath","captureGroups","memo","paramName","splatValue","safelyDecodeURIComponent","regexpSource","_","RegExp","decodeURI","decodeURIComponent","toLowerCase","startIndex","nextChar","resolvePath","fromPathname","toPathname","resolvePathname","normalizeSearch","normalizeHash","relativeSegments","pop","getInvalidPathError","char","field","dest","getPathContributingMatches","resolveTo","toArg","routePathnames","locationPathname","isPathRelative","isEmptyPath","from","routePathnameIndex","toSegments","shift","hasExplicitTrailingSlash","hasCurrentTrailingSlash","getToPathname","paths","json","data","init","responseInit","status","headers","Headers","has","set","Response","AbortedDeferredError","DeferredData","constructor","pendingKeysSet","subscribers","deferredKeys","Array","isArray","reject","abortPromise","Promise","r","controller","AbortController","onAbort","unlistenAbortSignal","signal","acc","trackPromise","done","add","promise","race","then","onSettle","catch","defineProperty","get","aborted","delete","emit","settledKey","subscriber","subscribe","cancel","abort","v","k","resolveData","resolve","size","unwrappedData","unwrapTrackedPromise","pendingKeys","isTrackedPromise","_tracked","_error","_data","defer","redirect","ErrorResponse","statusText","internal","isRouteErrorResponse","validMutationMethodsArr","validMutationMethods","validRequestMethodsArr","validRequestMethods","redirectStatusCodes","redirectPreserveMethodStatusCodes","IDLE_NAVIGATION","formMethod","formAction","formEncType","formData","IDLE_FETCHER","IDLE_BLOCKER","proceed","reset","ABSOLUTE_URL_REGEX","isBrowser","createElement","isServer","defaultDetectErrorBoundary","Boolean","createRouter","dataRoutes","inFlightDataRoutes","future","v7_normalizeFormMethod","unlistenHistory","savedScrollPositions","getScrollRestorationKey","getScrollPosition","initialScrollRestored","hydrationData","initialMatches","initialErrors","getInternalRouterError","getShortCircuitMatches","initialized","m","lazy","loader","router","historyAction","navigation","restoreScrollPosition","preventScrollReset","revalidation","loaderData","actionData","errors","fetchers","Map","blockers","pendingAction","HistoryAction","pendingPreventScrollReset","pendingNavigationController","isUninterruptedRevalidation","isRevalidationRequired","cancelledDeferredRoutes","cancelledFetcherLoads","fetchControllers","incrementingLoadId","pendingNavigationLoadId","fetchReloadIds","fetchRedirectIds","fetchLoadMatches","activeDeferreds","blockerFunctions","ignoreNextHistoryUpdate","initialize","blockerKey","shouldBlockNavigation","currentLocation","updateBlocker","deleteBlocker","updateState","startNavigation","dispose","clear","deleteFetcher","newState","completeNavigation","isActionReload","isMutationMethod","_isRedirect","keys","mergeLoaderData","getSavedScrollPosition","navigate","opts","submission","normalizeNavigateOptions","userReplace","pendingError","revalidate","interruptActiveLoads","startUninterruptedRevalidation","overrideNavigation","saveScrollPosition","routesToUse","loadingNavigation","notFoundMatches","cancelActiveDeferreds","isHashChangeOnly","request","createClientSideRequest","pendingActionData","findNearestBoundary","actionOutput","handleAction","shortCircuited","pendingActionError","Request","handleLoaders","fetcherSubmission","actionMatch","getTargetMatch","type","method","routeId","callLoaderOrAction","isRedirectResult","startRedirectNavigation","isErrorResult","boundaryMatch","isDeferredResult","activeSubmission","matchesToLoad","revalidatingFetchers","getMatchesToLoad","rf","fetcher","revalidatingFetcher","results","loaderResults","fetcherResults","callLoadersAndMaybeResolveData","findRedirect","processLoaderData","deferredData","markFetchRedirectsDone","didAbortFetchLoads","abortStaleFetchLoads","getFetcher","fetch","abortFetcher","setFetcherError","handleFetcherAction","handleFetcherLoader","requestMatches","existingFetcher","abortController","fetchRequest","actionResult","loadingFetcher","isFetchActionRedirect","revalidationRequest","loadId","loadFetcher","staleKey","doneFetcher","resolveDeferredData","redirectLocation","_isFetchActionRedirect","isDifferentBasename","redirectHistoryAction","currentMatches","fetchersToLoad","all","f","resolveDeferredResults","markFetchersDone","doneKeys","landedId","yeetedKeys","getBlocker","blocker","newBlocker","blockerFunction","predicate","cancelledRouteIds","dfd","enableScrollRestoration","positions","getPosition","getKey","y","userMatches","createUseMatchesMatch","_internalSetRoutes","newRoutes","_internalFetchControllers","_internalActiveDeferreds","UNSAFE_DEFERRED_SYMBOL","Symbol","createStaticHandler","query","requestContext","isValidMethod","methodNotAllowedMatches","statusCode","loaderHeaders","actionHeaders","queryImpl","isResponse","queryRoute","find","values","routeMatch","submit","loadRouteData","isQueryRouteResponse","isRedirectResponse","response","isRouteRequest","Location","context","loaderRequest","getLoaderMatchesUntilBoundary","processRouteLoaderData","executedLoaders","fromEntries","getStaticContextFromError","newContext","_deepestRenderedBoundaryId","isSubmissionNavigation","isFetcher","toUpperCase","stripHashFromPath","searchParams","convertFormDataToSearchParams","hasNakedIndexQuery","append","boundaryId","boundaryMatches","findIndex","currentUrl","nextUrl","defaultShouldRevalidate","navigationMatches","isNewLoader","currentRouteMatch","nextRouteMatch","shouldRevalidateLoader","currentParams","nextParams","isNewRouteInstance","fetcherMatches","fetcherMatch","shouldRevalidate","currentLoaderData","currentMatch","isNew","isMissingData","currentPath","loaderMatch","arg","routeChoice","loadLazyRouteModule","lazyRoute","routeToUpdate","routeUpdates","lazyRouteProperty","staticRouteValue","isPropertyStaticallyDefined","isStaticRequest","resultType","onReject","runHandler","handler","activeMatches","resolvedLocation","protocol","isSameBasename","contentType","text","isDeferredData","deferred","body","URLSearchParams","File","name","foundError","newLoaderData","mergedLoaderData","hasOwnProperty","eligibleMatches","reverse","errorMessage","obj","isRevalidatingLoader","unwrap","getAll","handle","pathMatches"],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@remix-run/router/dist/router.umd.min.js b/node_modules/@remix-run/router/dist/router.umd.min.js new file mode 100644 index 00000000..026f5e01 --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.umd.min.js @@ -0,0 +1,12 @@ +/** + * @remix-run/router v1.5.0 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).RemixRouter={})}(this,(function(e){"use strict";function t(){return t=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0&&(t.hash=e.substr(r),e=e.substr(0,r));let a=e.indexOf("?");a>=0&&(t.search=e.substr(a),e=e.substr(0,a)),e&&(t.pathname=e)}return t}function d(r,n,c,d){void 0===d&&(d={});let{window:u=document.defaultView,v5Compat:h=!1}=d,f=u.history,p=e.Action.Pop,m=null,y=v();function v(){return(f.state||{idx:null}).idx}function g(){p=e.Action.Pop;let t=v(),r=null==t?null:t-y;y=t,m&&m({action:p,location:w.location,delta:r})}function b(e){let t="null"!==u.location.origin?u.location.origin:u.location.href,r="string"==typeof e?e:l(e);return o(t,"No window.location.(origin|href) available to create URL for href: "+r),new URL(r,t)}null==y&&(y=0,f.replaceState(t({},f.state,{idx:y}),""));let w={get action(){return p},get location(){return r(u,f)},listen(e){if(m)throw new Error("A history only accepts one active listener");return u.addEventListener(a,g),m=e,()=>{u.removeEventListener(a,g),m=null}},createHref:e=>n(u,e),createURL:b,encodeLocation(e){let t=b(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:function(t,r){p=e.Action.Push;let a=s(w.location,t,r);c&&c(a,t),y=v()+1;let o=i(a,y),n=w.createHref(a);try{f.pushState(o,"",n)}catch(e){u.location.assign(n)}h&&m&&m({action:p,location:w.location,delta:1})},replace:function(t,r){p=e.Action.Replace;let a=s(w.location,t,r);c&&c(a,t),y=v();let o=i(a,y),n=w.createHref(a);f.replaceState(o,"",n),h&&m&&m({action:p,location:w.location,delta:0})},go:e=>f.go(e)};return w}let u;!function(e){e.data="data",e.deferred="deferred",e.redirect="redirect",e.error="error"}(u||(u={}));const h=new Set(["lazy","caseSensitive","path","id","index","children"]);function f(e,r,a,n){return void 0===a&&(a=[]),void 0===n&&(n={}),e.map(((e,i)=>{let s=[...a,i],l="string"==typeof e.id?e.id:s.join("-");if(o(!0!==e.index||!e.children,"Cannot specify children on an index route"),o(!n[l],'Found a route id collision on id "'+l+"\". Route id's must be globally unique within Data Router usages"),function(e){return!0===e.index}(e)){let a=t({},e,{hasErrorBoundary:r(e),id:l});return n[l]=a,a}{let a=t({},e,{id:l,hasErrorBoundary:r(e),children:void 0});return n[l]=a,e.children&&(a.children=f(e.children,r,s,n)),a}}))}function p(e,t,r){void 0===r&&(r="/");let a=R(("string"==typeof t?c(t):t).pathname||"/",r);if(null==a)return null;let o=m(e);!function(e){e.sort(((e,t)=>e.score!==t.score?t.score-e.score:function(e,t){return e.length===t.length&&e.slice(0,-1).every(((e,r)=>e===t[r]))?e[e.length-1]-t[t.length-1]:0}(e.routesMeta.map((e=>e.childrenIndex)),t.routesMeta.map((e=>e.childrenIndex)))))}(o);let n=null;for(let e=0;null==n&&e{let s={relativePath:void 0===i?e.path||"":i,caseSensitive:!0===e.caseSensitive,childrenIndex:n,route:e};s.relativePath.startsWith("/")&&(o(s.relativePath.startsWith(a),'Absolute route path "'+s.relativePath+'" nested under path "'+a+'" is not valid. An absolute child route path must start with the combined path of all its parent routes.'),s.relativePath=s.relativePath.slice(a.length));let l=L([a,s.relativePath]),c=r.concat(s);e.children&&e.children.length>0&&(o(!0!==e.index,'Index routes must not have child routes. Please remove all child routes from route path "'+l+'".'),m(e.children,t,c,l)),(null!=e.path||e.index)&&t.push({path:l,score:b(l,e.index),routesMeta:c})};return e.forEach(((e,t)=>{var r;if(""!==e.path&&null!=(r=e.path)&&r.includes("?"))for(let r of y(e.path))n(e,t,r);else n(e,t)})),t}function y(e){let t=e.split("/");if(0===t.length)return[];let[r,...a]=t,o=r.endsWith("?"),n=r.replace(/\?$/,"");if(0===a.length)return o?[n,""]:[n];let i=y(a.join("/")),s=[];return s.push(...i.map((e=>""===e?n:[n,e].join("/")))),o&&s.push(...i),s.map((t=>e.startsWith("/")&&""===t?"/":t))}const v=/^:\w+$/,g=e=>"*"===e;function b(e,t){let r=e.split("/"),a=r.length;return r.some(g)&&(a+=-2),t&&(a+=2),r.filter((e=>!g(e))).reduce(((e,t)=>e+(v.test(t)?3:""===t?1:10)),a)}function w(e,t){let{routesMeta:r}=e,a={},o="/",n=[];for(let e=0;e(a.push(t),"/([^\\/]+)")));e.endsWith("*")?(a.push("*"),o+="*"===e||"/*"===e?"(.*)$":"(?:\\/(.+)|\\/*)$"):r?o+="\\/*$":""!==e&&"/"!==e&&(o+="(?:(?=\\/|$))");return[new RegExp(o,t?void 0:"i"),a]}(e.path,e.caseSensitive,e.end),o=t.match(r);if(!o)return null;let i=o[0],s=i.replace(/(.)\/+$/,"$1"),l=o.slice(1);return{params:a.reduce(((e,t,r)=>{if("*"===t){let e=l[r]||"";s=i.slice(0,i.length-e.length).replace(/(.)\/+$/,"$1")}return e[t]=function(e,t){try{return decodeURIComponent(e)}catch(r){return n(!1,'The value for the URL param "'+t+'" will not be decoded because the string "'+e+'" is a malformed URL segment. This is probably due to a bad percent encoding ('+r+")."),e}}(l[r]||"",t),e}),{}),pathname:i,pathnameBase:s,pattern:e}}function A(e){try{return decodeURI(e)}catch(t){return n(!1,'The URL path "'+e+'" could not be decoded because it is is a malformed URL segment. This is probably due to a bad percent encoding ('+t+")."),e}}function R(e,t){if("/"===t)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let r=t.endsWith("/")?t.length-1:t.length,a=e.charAt(r);return a&&"/"!==a?null:e.slice(r)||"/"}function E(e,t){void 0===t&&(t="/");let{pathname:r,search:a="",hash:o=""}="string"==typeof e?c(e):e,n=r?r.startsWith("/")?r:function(e,t){let r=t.replace(/\/+$/,"").split("/");return e.split("/").forEach((e=>{".."===e?r.length>1&&r.pop():"."!==e&&r.push(e)})),r.length>1?r.join("/"):"/"}(r,t):t;return{pathname:n,search:x(a),hash:C(o)}}function S(e,t,r,a){return"Cannot include a '"+e+"' character in a manually specified `to."+t+"` field ["+JSON.stringify(a)+"]. Please separate it out to the `to."+r+'` field. Alternatively you may provide the full path as a string in and the router will parse it for you.'}function P(e){return e.filter(((e,t)=>0===t||e.route.path&&e.route.path.length>0))}function M(e,r,a,n){let i;void 0===n&&(n=!1),"string"==typeof e?i=c(e):(i=t({},e),o(!i.pathname||!i.pathname.includes("?"),S("?","pathname","search",i)),o(!i.pathname||!i.pathname.includes("#"),S("#","pathname","hash",i)),o(!i.search||!i.search.includes("#"),S("#","search","hash",i)));let s,l=""===e||""===i.pathname,d=l?"/":i.pathname;if(n||null==d)s=a;else{let e=r.length-1;if(d.startsWith("..")){let t=d.split("/");for(;".."===t[0];)t.shift(),e-=1;i.pathname=t.join("/")}s=e>=0?r[e]:"/"}let u=E(i,s),h=d&&"/"!==d&&d.endsWith("/"),f=(l||"."===d)&&a.endsWith("/");return u.pathname.endsWith("/")||!h&&!f||(u.pathname+="/"),u}const L=e=>e.join("/").replace(/\/\/+/g,"/"),k=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),x=e=>e&&"?"!==e?e.startsWith("?")?e:"?"+e:"",C=e=>e&&"#"!==e?e.startsWith("#")?e:"#"+e:"";class U extends Error{}class j{constructor(e,t){let r;this.pendingKeysSet=new Set,this.subscribers=new Set,this.deferredKeys=[],o(e&&"object"==typeof e&&!Array.isArray(e),"defer() only accepts plain objects"),this.abortPromise=new Promise(((e,t)=>r=t)),this.controller=new AbortController;let a=()=>r(new U("Deferred data aborted"));this.unlistenAbortSignal=()=>this.controller.signal.removeEventListener("abort",a),this.controller.signal.addEventListener("abort",a),this.data=Object.entries(e).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:this.trackPromise(r,a)})}),{}),this.done&&this.unlistenAbortSignal(),this.init=t}trackPromise(e,t){if(!(t instanceof Promise))return t;this.deferredKeys.push(e),this.pendingKeysSet.add(e);let r=Promise.race([t,this.abortPromise]).then((t=>this.onSettle(r,e,null,t)),(t=>this.onSettle(r,e,t)));return r.catch((()=>{})),Object.defineProperty(r,"_tracked",{get:()=>!0}),r}onSettle(e,t,r,a){return this.controller.signal.aborted&&r instanceof U?(this.unlistenAbortSignal(),Object.defineProperty(e,"_error",{get:()=>r}),Promise.reject(r)):(this.pendingKeysSet.delete(t),this.done&&this.unlistenAbortSignal(),r?(Object.defineProperty(e,"_error",{get:()=>r}),this.emit(!1,t),Promise.reject(r)):(Object.defineProperty(e,"_data",{get:()=>a}),this.emit(!1,t),a))}emit(e,t){this.subscribers.forEach((r=>r(e,t)))}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}cancel(){this.controller.abort(),this.pendingKeysSet.forEach(((e,t)=>this.pendingKeysSet.delete(t))),this.emit(!0)}async resolveData(e){let t=!1;if(!this.done){let r=()=>this.cancel();e.addEventListener("abort",r),t=await new Promise((t=>{this.subscribe((a=>{e.removeEventListener("abort",r),(a||this.done)&&t(a)}))}))}return t}get done(){return 0===this.pendingKeysSet.size}get unwrappedData(){return o(null!==this.data&&this.done,"Can only unwrap data on initialized and settled deferreds"),Object.entries(this.data).reduce(((e,t)=>{let[r,a]=t;return Object.assign(e,{[r]:T(a)})}),{})}get pendingKeys(){return Array.from(this.pendingKeysSet)}}function T(e){if(!function(e){return e instanceof Promise&&!0===e._tracked}(e))return e;if(e._error)throw e._error;return e._data}class O{constructor(e,t,r,a){void 0===a&&(a=!1),this.status=e,this.statusText=t||"",this.internal=a,r instanceof Error?(this.data=r.toString(),this.error=r):this.data=r}}function _(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"boolean"==typeof e.internal&&"data"in e}const F=["post","put","patch","delete"],H=new Set(F),z=["get",...F],I=new Set(z),B=new Set([301,302,303,307,308]),q=new Set([307,308]),N={state:"idle",location:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},$={state:"idle",data:void 0,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},W={state:"unblocked",proceed:void 0,reset:void 0,location:void 0},K=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Y="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,J=!Y,V=e=>Boolean(e.hasErrorBoundary);const G=Symbol("deferred");function X(e,t,r,a){void 0===a&&(a=!1);let o,n="string"==typeof e?e:l(e);if(!r||!function(e){return null!=e&&"formData"in e}(r))return{path:n};if(r.formMethod&&!we(r.formMethod))return{path:n,error:ue(405,{method:r.formMethod})};if(r.formData){let e=r.formMethod||"get";if(o={formMethod:t.v7_normalizeFormMethod?e.toUpperCase():e.toLowerCase(),formAction:fe(n),formEncType:r&&r.formEncType||"application/x-www-form-urlencoded",formData:r.formData},De(o.formMethod))return{path:n,submission:o}}let i=c(n),s=ne(r.formData);return a&&i.search&&Ee(i.search)&&s.append("index",""),i.search="?"+s,{path:l(i),submission:o}}function Q(e,t){let r=e;if(t){let a=e.findIndex((e=>e.route.id===t));a>=0&&(r=e.slice(0,a))}return r}function Z(e,r,a,o,n,i,s,l,c,d,u,h,f){let m=f?Object.values(f)[0]:h?Object.values(h)[0]:void 0,y=e.createURL(r.location),v=e.createURL(n),g=i||y.toString()===v.toString()||y.search!==v.search,b=f?Object.keys(f)[0]:void 0,w=Q(a,b).filter(((e,a)=>{if(e.route.lazy)return!0;if(null==e.route.loader)return!1;if(function(e,t,r){let a=!t||r.route.id!==t.route.id,o=void 0===e[r.route.id];return a||o}(r.loaderData,r.matches[a],e)||s.some((t=>t===e.route.id)))return!0;let n=r.matches[a],i=e;return te(e,t({currentUrl:y,currentParams:n.params,nextUrl:v,nextParams:i.params},o,{actionResult:m,defaultShouldRevalidate:g||ee(n,i)}))})),D=[];return c.forEach(((e,n)=>{if(!a.some((t=>t.route.id===e.routeId)))return;let i=p(d,e.path,u);if(!i)return void D.push(t({key:n},e,{matches:null,match:null}));let s=Pe(i,e.path);(l.includes(n)||te(s,t({currentUrl:y,currentParams:r.matches[r.matches.length-1].params,nextUrl:v,nextParams:a[a.length-1].params},o,{actionResult:m,defaultShouldRevalidate:g})))&&D.push(t({key:n,matches:i,match:s},e))})),[w,D]}function ee(e,t){let r=e.route.path;return e.pathname!==t.pathname||null!=r&&r.endsWith("*")&&e.params["*"]!==t.params["*"]}function te(e,t){if(e.route.shouldRevalidate){let r=e.route.shouldRevalidate(t);if("boolean"==typeof r)return r}return t.defaultShouldRevalidate}async function re(e,r,a){if(!e.lazy)return;let i=await e.lazy();if(!e.lazy)return;let s=a[e.id];o(s,"No route found in manifest");let l={};for(let e in i){let t=void 0!==s[e]&&"hasErrorBoundary"!==e;n(!t,'Route "'+s.id+'" has a static property "'+e+'" defined but its lazy function is also returning a value for this property. The lazy route property "'+e+'" will be ignored.'),t||h.has(e)||(l[e]=i[e])}Object.assign(s,l),Object.assign(s,{hasErrorBoundary:r(t({},s)),lazy:void 0})}async function ae(e,t,r,a,n,i,s,c,d,h){let f,p,m;void 0===s&&(s="/"),void 0===c&&(c=!1),void 0===d&&(d=!1);let y=e=>{let a,o=new Promise(((e,t)=>a=t));return m=()=>a(),t.signal.addEventListener("abort",m),Promise.race([e({request:t,params:r.params,context:h}),o])};try{let a=r.route[e];if(r.route.lazy)if(a){p=(await Promise.all([y(a),re(r.route,i,n)]))[0]}else{if(await re(r.route,i,n),a=r.route[e],!a){if("action"===e)throw ue(405,{method:t.method,pathname:new URL(t.url).pathname,routeId:r.route.id});return{type:u.data,data:void 0}}p=await y(a)}else o(a,"Could not find the "+e+' to run on the "'+r.route.id+'" route'),p=await y(a);o(void 0!==p,"You defined "+("action"===e?"an action":"a loader")+' for route "'+r.route.id+"\" but didn't return anything from your `"+e+"` function. Please return a value or `null`.")}catch(e){f=u.error,p=e}finally{m&&t.signal.removeEventListener("abort",m)}if(ge(p)){let e,n=p.status;if(B.has(n)){let e=p.headers.get("Location");if(o(e,"Redirects returned/thrown from loaders/actions must have a Location header"),K.test(e)){if(!c){let r=new URL(t.url),a=e.startsWith("//")?new URL(r.protocol+e):new URL(e),o=null!=R(a.pathname,s);a.origin===r.origin&&o&&(e=a.pathname+a.search+a.hash)}}else{let n=M(e,P(a.slice(0,a.indexOf(r)+1)).map((e=>e.pathnameBase)),new URL(t.url).pathname);if(o(l(n),"Unable to resolve redirect location: "+e),s){let e=n.pathname;n.pathname="/"===e?s:L([s,e])}e=l(n)}if(c)throw p.headers.set("Location",e),p;return{type:u.redirect,status:n,location:e,revalidate:null!==p.headers.get("X-Remix-Revalidate")}}if(d)throw{type:f||u.data,response:p};let i=p.headers.get("Content-Type");return e=i&&/\bapplication\/json\b/.test(i)?await p.json():await p.text(),f===u.error?{type:f,error:new O(n,p.statusText,e),headers:p.headers}:{type:u.data,data:e,statusCode:p.status,headers:p.headers}}return f===u.error?{type:f,error:p}:ve(p)?{type:u.deferred,deferredData:p,statusCode:null==(v=p.init)?void 0:v.status,headers:(null==(g=p.init)?void 0:g.headers)&&new Headers(p.init.headers)}:{type:u.data,data:p};var v,g}function oe(e,t,r,a){let o=e.createURL(fe(t)).toString(),n={signal:r};if(a&&De(a.formMethod)){let{formMethod:e,formEncType:t,formData:r}=a;n.method=e.toUpperCase(),n.body="application/x-www-form-urlencoded"===t?ne(r):r}return new Request(o,n)}function ne(e){let t=new URLSearchParams;for(let[r,a]of e.entries())t.append(r,a instanceof File?a.name:a);return t}function ie(e,t,r,a,n){let i,s={},l=null,c=!1,d={};return r.forEach(((r,u)=>{let h=t[u].route.id;if(o(!ye(r),"Cannot handle redirect results in processLoaderData"),me(r)){let t=ce(e,h),o=r.error;a&&(o=Object.values(a)[0],a=void 0),l=l||{},null==l[t.route.id]&&(l[t.route.id]=o),s[h]=void 0,c||(c=!0,i=_(r.error)?r.error.status:500),r.headers&&(d[h]=r.headers)}else pe(r)?(n.set(h,r.deferredData),s[h]=r.deferredData.data):s[h]=r.data,null==r.statusCode||200===r.statusCode||c||(i=r.statusCode),r.headers&&(d[h]=r.headers)})),a&&(l=a,s[Object.keys(a)[0]]=void 0),{loaderData:s,errors:l,statusCode:i||200,loaderHeaders:d}}function se(e,r,a,n,i,s,l,c){let{loaderData:d,errors:u}=ie(r,a,n,i,c);for(let r=0;re.route.id===t))+1):[...e]).reverse().find((e=>!0===e.route.hasErrorBoundary))||e[0]}function de(e){let t=e.find((e=>e.index||!e.path||"/"===e.path))||{id:"__shim-error-route__"};return{matches:[{params:{},pathname:"",pathnameBase:"",route:t}],route:t}}function ue(e,t){let{pathname:r,routeId:a,method:o,type:n}=void 0===t?{}:t,i="Unknown Server Error",s="Unknown @remix-run/router error";return 400===e?(i="Bad Request",o&&r&&a?s="You made a "+o+' request to "'+r+'" but did not provide a `loader` for route "'+a+'", so there is no way to handle the request.':"defer-action"===n&&(s="defer() is not supported in actions")):403===e?(i="Forbidden",s='Route "'+a+'" does not match URL "'+r+'"'):404===e?(i="Not Found",s='No route matches URL "'+r+'"'):405===e&&(i="Method Not Allowed",o&&r&&a?s="You made a "+o.toUpperCase()+' request to "'+r+'" but did not provide an `action` for route "'+a+'", so there is no way to handle the request.':o&&(s='Invalid request method "'+o.toUpperCase()+'"')),new O(e||500,i,new Error(s),!0)}function he(e){for(let t=e.length-1;t>=0;t--){let r=e[t];if(ye(r))return r}}function fe(e){return l(t({},"string"==typeof e?c(e):e,{hash:""}))}function pe(e){return e.type===u.deferred}function me(e){return e.type===u.error}function ye(e){return(e&&e.type)===u.redirect}function ve(e){let t=e;return t&&"object"==typeof t&&"object"==typeof t.data&&"function"==typeof t.subscribe&&"function"==typeof t.cancel&&"function"==typeof t.resolveData}function ge(e){return null!=e&&"number"==typeof e.status&&"string"==typeof e.statusText&&"object"==typeof e.headers&&void 0!==e.body}function be(e){if(!ge(e))return!1;let t=e.status,r=e.headers.get("Location");return t>=300&&t<=399&&null!=r}function we(e){return I.has(e.toLowerCase())}function De(e){return H.has(e.toLowerCase())}async function Ae(e,t,r,a,o,n){for(let i=0;ie.route.id===l.route.id)),d=null!=c&&!ee(c,l)&&void 0!==(n&&n[l.route.id]);pe(s)&&(o||d)&&await Re(s,a,o).then((e=>{e&&(r[i]=e||r[i])}))}}async function Re(e,t,r){if(void 0===r&&(r=!1),!await e.deferredData.resolveData(t)){if(r)try{return{type:u.data,data:e.deferredData.unwrappedData}}catch(e){return{type:u.error,error:e}}return{type:u.data,data:e.deferredData.data}}}function Ee(e){return new URLSearchParams(e).getAll("index").some((e=>""===e))}function Se(e,t){let{route:r,pathname:a,params:o}=e;return{id:r.id,pathname:a,params:o,data:t[r.id],handle:r.handle}}function Pe(e,t){let r="string"==typeof t?c(t).search:t.search;if(e[e.length-1].route.index&&Ee(r||""))return e[e.length-1];let a=P(e);return a[a.length-1]}e.AbortedDeferredError=U,e.ErrorResponse=O,e.IDLE_BLOCKER=W,e.IDLE_FETCHER=$,e.IDLE_NAVIGATION=N,e.UNSAFE_DEFERRED_SYMBOL=G,e.UNSAFE_DeferredData=j,e.UNSAFE_convertRoutesToDataRoutes=f,e.UNSAFE_getPathContributingMatches=P,e.UNSAFE_invariant=o,e.UNSAFE_warning=n,e.createBrowserHistory=function(e){return void 0===e&&(e={}),d((function(e,t){let{pathname:r,search:a,hash:o}=e.location;return s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){return"string"==typeof t?t:l(t)}),null,e)},e.createHashHistory=function(e){return void 0===e&&(e={}),d((function(e,t){let{pathname:r="/",search:a="",hash:o=""}=c(e.location.hash.substr(1));return s("",{pathname:r,search:a,hash:o},t.state&&t.state.usr||null,t.state&&t.state.key||"default")}),(function(e,t){let r=e.document.querySelector("base"),a="";if(r&&r.getAttribute("href")){let t=e.location.href,r=t.indexOf("#");a=-1===r?t:t.slice(0,r)}return a+"#"+("string"==typeof t?t:l(t))}),(function(e,t){n("/"===e.pathname.charAt(0),"relative pathnames are not supported in hash history.push("+JSON.stringify(t)+")")}),e)},e.createMemoryHistory=function(t){void 0===t&&(t={});let r,{initialEntries:a=["/"],initialIndex:o,v5Compat:i=!1}=t;r=a.map(((e,t)=>m(e,"string"==typeof e?null:e.state,0===t?"default":void 0)));let d=f(null==o?r.length-1:o),u=e.Action.Pop,h=null;function f(e){return Math.min(Math.max(e,0),r.length-1)}function p(){return r[d]}function m(e,t,a){void 0===t&&(t=null);let o=s(r?p().pathname:"/",e,t,a);return n("/"===o.pathname.charAt(0),"relative pathnames are not supported in memory history: "+JSON.stringify(e)),o}function y(e){return"string"==typeof e?e:l(e)}return{get index(){return d},get action(){return u},get location(){return p()},createHref:y,createURL:e=>new URL(y(e),"http://localhost"),encodeLocation(e){let t="string"==typeof e?c(e):e;return{pathname:t.pathname||"",search:t.search||"",hash:t.hash||""}},push(t,a){u=e.Action.Push;let o=m(t,a);d+=1,r.splice(d,r.length,o),i&&h&&h({action:u,location:o,delta:1})},replace(t,a){u=e.Action.Replace;let o=m(t,a);r[d]=o,i&&h&&h({action:u,location:o,delta:0})},go(t){u=e.Action.Pop;let a=f(d+t),o=r[a];d=a,h&&h({action:u,location:o,delta:t})},listen:e=>(h=e,()=>{h=null})}},e.createPath=l,e.createRouter=function(r){o(r.routes.length>0,"You must provide a non-empty routes array to createRouter");let a,i=r.detectErrorBoundary||V,l={},c=f(r.routes,i,void 0,l),d=t({v7_normalizeFormMethod:!1},r.future),h=null,m=new Set,y=null,v=null,g=null,b=null!=r.hydrationData,w=p(c,r.history.location,r.basename),D=null;if(null==w){let e=ue(404,{pathname:r.history.location.pathname}),{matches:t,route:a}=de(c);w=t,D={[a.id]:e}}let A,E,S=!(w.some((e=>e.route.lazy))||w.some((e=>e.route.loader))&&null==r.hydrationData),P={historyAction:r.history.action,location:r.history.location,matches:w,initialized:S,navigation:N,restoreScrollPosition:null==r.hydrationData&&null,preventScrollReset:!1,revalidation:"idle",loaderData:r.hydrationData&&r.hydrationData.loaderData||{},actionData:r.hydrationData&&r.hydrationData.actionData||null,errors:r.hydrationData&&r.hydrationData.errors||D,fetchers:new Map,blockers:new Map},M=e.Action.Pop,L=!1,k=!1,x=!1,C=[],U=[],j=new Map,T=0,O=-1,_=new Map,F=new Set,H=new Map,z=new Map,I=new Map,B=!1;function G(e){P=t({},P,e),m.forEach((e=>e(P)))}function Q(o,n){var i,s;let l,d=null!=P.actionData&&null!=P.navigation.formMethod&&De(P.navigation.formMethod)&&"loading"===P.navigation.state&&!0!==(null==(i=o.state)?void 0:i._isRedirect);l=n.actionData?Object.keys(n.actionData).length>0?n.actionData:null:d?P.actionData:null;let u=n.loaderData?le(P.loaderData,n.loaderData,n.matches||[],n.errors):P.loaderData;for(let[e]of I)Ee(e);let h=!0===L||null!=P.navigation.formMethod&&De(P.navigation.formMethod)&&!0!==(null==(s=o.state)?void 0:s._isRedirect);a&&(c=a,a=void 0),G(t({},n,{actionData:l,loaderData:u,historyAction:M,location:o,initialized:!0,navigation:N,revalidation:"idle",restoreScrollPosition:xe(o,n.matches||P.matches),preventScrollReset:h,blockers:new Map(P.blockers)})),k||M===e.Action.Pop||(M===e.Action.Push?r.history.push(o,o.state):M===e.Action.Replace&&r.history.replace(o,o.state)),M=e.Action.Pop,L=!1,k=!1,x=!1,C=[],U=[]}async function ee(n,s,d){E&&E.abort(),E=null,M=n,k=!0===(d&&d.startUninterruptedRevalidation),function(e,t){if(y&&v&&g){let r=t.map((e=>Se(e,P.loaderData))),a=v(e,r)||e.key;y[a]=g()}}(P.location,P.matches),L=!0===(d&&d.preventScrollReset);let h=a||c,f=d&&d.overrideNavigation,m=p(h,s,r.basename);if(!m){let e=ue(404,{pathname:s.pathname}),{matches:t,route:r}=de(h);return ke(),void Q(s,{matches:t,loaderData:{},errors:{[r.id]:e}})}if(!(b=P.location,w=s,b.pathname!==w.pathname||b.search!==w.search||b.hash===w.hash||d&&d.submission&&De(d.submission.formMethod)))return void Q(s,{matches:m});var b,w;E=new AbortController;let D,R,S=oe(r.history,s,E.signal,d&&d.submission);if(d&&d.pendingError)R={[ce(m).route.id]:d.pendingError};else if(d&&d.submission&&De(d.submission.formMethod)){let r=await async function(r,a,o,n,s){let c;ie(),G({navigation:t({state:"submitting",location:a},o)});let d=Pe(n,a);if(d.route.action||d.route.lazy){if(c=await ae("action",r,d,n,l,i,A.basename),r.signal.aborted)return{shortCircuited:!0}}else c={type:u.error,error:ue(405,{method:r.method,pathname:a.pathname,routeId:d.route.id})};if(ye(c)){let e;return e=s&&null!=s.replace?s.replace:c.location===P.location.pathname+P.location.search,await re(P,c,{submission:o,replace:e}),{shortCircuited:!0}}if(me(c)){let t=ce(n,d.route.id);return!0!==(s&&s.replace)&&(M=e.Action.Push),{pendingActionData:{},pendingActionError:{[t.route.id]:c.error}}}if(pe(c))throw ue(400,{type:"defer-action"});return{pendingActionData:{[d.route.id]:c.data}}}(S,s,d.submission,m,{replace:d.replace});if(r.shortCircuited)return;D=r.pendingActionData,R=r.pendingActionError,f=t({state:"loading",location:s},d.submission),S=new Request(S.url,{signal:S.signal})}let{shortCircuited:_,loaderData:I,errors:B}=await async function(e,n,i,s,l,d,u,h,f){let p=s;if(!p){p=t({state:"loading",location:n,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},l)}let m=l||d?l||d:p.formMethod&&p.formAction&&p.formData&&p.formEncType?{formMethod:p.formMethod,formAction:p.formAction,formData:p.formData,formEncType:p.formEncType}:void 0,y=a||c,[v,g]=Z(r.history,P,i,m,n,x,C,U,H,y,r.basename,h,f);if(ke((e=>!(i&&i.some((t=>t.route.id===e)))||v&&v.some((t=>t.route.id===e)))),0===v.length&&0===g.length)return Q(n,t({matches:i,loaderData:{},errors:f||null},h?{actionData:h}:{})),{shortCircuited:!0};if(!k){g.forEach((e=>{let t=P.fetchers.get(e.key),r={state:"loading",data:t&&t.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};P.fetchers.set(e.key,r)}));let e=h||P.actionData;G(t({navigation:p},e?0===Object.keys(e).length?{actionData:null}:{actionData:e}:{},g.length>0?{fetchers:new Map(P.fetchers)}:{}))}O=++T,g.forEach((e=>j.set(e.key,E)));let{results:b,loaderResults:w,fetcherResults:D}=await ne(P.matches,i,v,g,e);if(e.signal.aborted)return{shortCircuited:!0};g.forEach((e=>j.delete(e.key)));let A=he(b);if(A)return await re(P,A,{replace:u}),{shortCircuited:!0};let{loaderData:R,errors:S}=se(P,i,v,w,f,g,D,z);z.forEach(((e,t)=>{e.subscribe((r=>{(r||e.done)&&z.delete(t)}))})),function(){let e=[];for(let t of F){let r=P.fetchers.get(t);o(r,"Expected fetcher: "+t),"loading"===r.state&&(F.delete(t),e.push(t))}be(e)}();let M=we(O);return t({loaderData:R,errors:S},M||g.length>0?{fetchers:new Map(P.fetchers)}:{})}(S,s,m,f,d&&d.submission,d&&d.fetcherSubmission,d&&d.replace,D,R);_||(E=null,Q(s,t({matches:m},D?{actionData:D}:{},{loaderData:I,errors:B})))}function te(e){return P.fetchers.get(e)||$}async function re(a,n,i){var l;let{submission:c,replace:d,isFetchActionRedirect:u}=void 0===i?{}:i;n.revalidate&&(x=!0);let h=s(a.location,n.location,t({_isRedirect:!0},u?{_isFetchActionRedirect:!0}:{}));if(o(h,"Expected a location on the redirect navigation"),K.test(n.location)&&Y&&void 0!==(null==(l=window)?void 0:l.location)){let e=r.history.createURL(n.location),t=null==R(e.pathname,r.basename||"/");if(window.location.origin!==e.origin||t)return void(d?window.location.replace(n.location):window.location.assign(n.location))}E=null;let f=!0===d?e.Action.Replace:e.Action.Push,{formMethod:p,formAction:m,formEncType:y,formData:v}=a.navigation;!c&&p&&m&&v&&y&&(c={formMethod:p,formAction:m,formEncType:y,formData:v}),q.has(n.status)&&c&&De(c.formMethod)?await ee(f,h,{submission:t({},c,{formAction:n.location}),preventScrollReset:L}):u?await ee(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},fetcherSubmission:c,preventScrollReset:L}):await ee(f,h,{overrideNavigation:{state:"loading",location:h,formMethod:c?c.formMethod:void 0,formAction:c?c.formAction:void 0,formEncType:c?c.formEncType:void 0,formData:c?c.formData:void 0},preventScrollReset:L})}async function ne(e,t,a,o,n){let s=await Promise.all([...a.map((e=>ae("loader",n,e,t,l,i,A.basename))),...o.map((e=>{if(e.matches&&e.match)return ae("loader",oe(r.history,e.path,n.signal),e.match,e.matches,l,i,A.basename);return{type:u.error,error:ue(404,{pathname:e.path})}}))]),c=s.slice(0,a.length),d=s.slice(a.length);return await Promise.all([Ae(e,a,c,n.signal,!1,P.loaderData),Ae(e,o.map((e=>e.match)),d,n.signal,!0)]),{results:s,loaderResults:c,fetcherResults:d}}function ie(){x=!0,C.push(...ke()),H.forEach(((e,t)=>{j.has(t)&&(U.push(t),ge(t))}))}function fe(e,t,r){let a=ce(P.matches,t);ve(e),G({errors:{[a.route.id]:r},fetchers:new Map(P.fetchers)})}function ve(e){j.has(e)&&ge(e),H.delete(e),_.delete(e),F.delete(e),P.fetchers.delete(e)}function ge(e){let t=j.get(e);o(t,"Expected fetch controller: "+e),t.abort(),j.delete(e)}function be(e){for(let t of e){let e={state:"idle",data:te(t).data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};P.fetchers.set(t,e)}}function we(e){let t=[];for(let[r,a]of _)if(a0}function Ee(e){P.blockers.delete(e),I.delete(e)}function Me(e,t){let r=P.blockers.get(e)||W;o("unblocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"blocked"===t.state||"blocked"===r.state&&"proceeding"===t.state||"blocked"===r.state&&"unblocked"===t.state||"proceeding"===r.state&&"unblocked"===t.state,"Invalid blocker state transition: "+r.state+" -> "+t.state),P.blockers.set(e,t),G({blockers:new Map(P.blockers)})}function Le(e){let{currentLocation:t,nextLocation:r,historyAction:a}=e;if(0===I.size)return;I.size>1&&n(!1,"A router only supports one blocker at a time");let o=Array.from(I.entries()),[i,s]=o[o.length-1],l=P.blockers.get(i);return l&&"proceeding"===l.state?void 0:s({currentLocation:t,nextLocation:r,historyAction:a})?i:void 0}function ke(e){let t=[];return z.forEach(((r,a)=>{e&&!e(a)||(r.cancel(),t.push(a),z.delete(a))})),t}function xe(e,t){if(y&&v&&g){let r=t.map((e=>Se(e,P.loaderData))),a=v(e,r)||e.key,o=y[a];if("number"==typeof o)return o}return null}return A={get basename(){return r.basename},get state(){return P},get routes(){return c},initialize:function(){return h=r.history.listen((e=>{let{action:t,location:a,delta:o}=e;if(B)return void(B=!1);n(0===I.size||null!=o,"You are trying to use a blocker on a POP navigation to a location that was not created by @remix-run/router. This will fail silently in production. This can happen if you are navigating outside the router via `window.history.pushState`/`window.location.hash` instead of using router navigation APIs. This can also happen if you are using createHashRouter and the user manually changes the URL.");let i=Le({currentLocation:P.location,nextLocation:a,historyAction:t});return i&&null!=o?(B=!0,r.history.go(-1*o),void Me(i,{state:"blocked",location:a,proceed(){Me(i,{state:"proceeding",proceed:void 0,reset:void 0,location:a}),r.history.go(o)},reset(){Ee(i),G({blockers:new Map(A.state.blockers)})}})):ee(t,a)})),P.initialized||ee(e.Action.Pop,P.location),A},subscribe:function(e){return m.add(e),()=>m.delete(e)},enableScrollRestoration:function(e,t,r){if(y=e,g=t,v=r||(e=>e.key),!b&&P.navigation===N){b=!0;let e=xe(P.location,P.matches);null!=e&&G({restoreScrollPosition:e})}return()=>{y=null,g=null,v=null}},navigate:async function a(o,n){if("number"==typeof o)return void r.history.go(o);let{path:i,submission:l,error:c}=X(o,d,n),u=P.location,h=s(P.location,i,n&&n.state);h=t({},h,r.history.encodeLocation(h));let f=n&&null!=n.replace?n.replace:void 0,p=e.Action.Push;!0===f?p=e.Action.Replace:!1===f||null!=l&&De(l.formMethod)&&l.formAction===P.location.pathname+P.location.search&&(p=e.Action.Replace);let m=n&&"preventScrollReset"in n?!0===n.preventScrollReset:void 0,y=Le({currentLocation:u,nextLocation:h,historyAction:p});if(!y)return await ee(p,h,{submission:l,pendingError:c,preventScrollReset:m,replace:n&&n.replace});Me(y,{state:"blocked",location:h,proceed(){Me(y,{state:"proceeding",proceed:void 0,reset:void 0,location:h}),a(o,n)},reset(){Ee(y),G({blockers:new Map(P.blockers)})}})},fetch:function(e,n,s,u){if(J)throw new Error("router.fetch() was called during the server render, but it shouldn't be. You are likely calling a useFetcher() method in the body of your component. Try moving it to a useEffect or a callback.");j.has(e)&&ge(e);let h=p(a||c,s,r.basename);if(!h)return void fe(e,n,ue(404,{pathname:s}));let{path:f,submission:m}=X(s,d,u,!0),y=Pe(h,f);L=!0===(u&&u.preventScrollReset),m&&De(m.formMethod)?async function(e,n,s,d,u,h){if(ie(),H.delete(e),!d.route.action&&!d.route.lazy){let t=ue(405,{method:h.formMethod,pathname:s,routeId:n});return void fe(e,n,t)}let f=P.fetchers.get(e),m=t({state:"submitting"},h,{data:f&&f.data," _hasFetcherDoneAnything ":!0});P.fetchers.set(e,m),G({fetchers:new Map(P.fetchers)});let y=new AbortController,v=oe(r.history,s,y.signal,h);j.set(e,y);let g=await ae("action",v,d,u,l,i,A.basename);if(v.signal.aborted)return void(j.get(e)===y&&j.delete(e));if(ye(g)){j.delete(e),F.add(e);let r=t({state:"loading"},h,{data:void 0," _hasFetcherDoneAnything ":!0});return P.fetchers.set(e,r),G({fetchers:new Map(P.fetchers)}),re(P,g,{submission:h,isFetchActionRedirect:!0})}if(me(g))return void fe(e,n,g.error);if(pe(g))throw ue(400,{type:"defer-action"});let b=P.navigation.location||P.location,w=oe(r.history,b,y.signal),D=a||c,R="idle"!==P.navigation.state?p(D,P.navigation.location,r.basename):P.matches;o(R,"Didn't find any matches after fetcher action");let S=++T;_.set(e,S);let L=t({state:"loading",data:g.data},h,{" _hasFetcherDoneAnything ":!0});P.fetchers.set(e,L);let[k,I]=Z(r.history,P,R,h,b,x,C,U,H,D,r.basename,{[d.route.id]:g.data},void 0);I.filter((t=>t.key!==e)).forEach((e=>{let t=e.key,r=P.fetchers.get(t),a={state:"loading",data:r&&r.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};P.fetchers.set(t,a),j.set(t,y)})),G({fetchers:new Map(P.fetchers)});let{results:B,loaderResults:q,fetcherResults:N}=await ne(P.matches,R,k,I,w);if(y.signal.aborted)return;_.delete(e),j.delete(e),I.forEach((e=>j.delete(e.key)));let $=he(B);if($)return re(P,$);let{loaderData:W,errors:K}=se(P,P.matches,k,q,void 0,I,N,z),Y={state:"idle",data:g.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};P.fetchers.set(e,Y);let J=we(S);"loading"===P.navigation.state&&S>O?(o(M,"Expected pending action"),E&&E.abort(),Q(P.navigation.location,{matches:R,loaderData:W,errors:K,fetchers:new Map(P.fetchers)})):(G(t({errors:K,loaderData:le(P.loaderData,W,R,K)},J?{fetchers:new Map(P.fetchers)}:{})),x=!1)}(e,n,f,y,h,m):(H.set(e,{routeId:n,path:f}),async function(e,a,n,s,c,d){let u=P.fetchers.get(e),h=t({state:"loading",formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0},d,{data:u&&u.data," _hasFetcherDoneAnything ":!0});P.fetchers.set(e,h),G({fetchers:new Map(P.fetchers)});let f=new AbortController,p=oe(r.history,n,f.signal);j.set(e,f);let m=await ae("loader",p,s,c,l,i,A.basename);pe(m)&&(m=await Re(m,p.signal,!0)||m);j.get(e)===f&&j.delete(e);if(p.signal.aborted)return;if(ye(m))return void await re(P,m);if(me(m)){let t=ce(P.matches,a);return P.fetchers.delete(e),void G({fetchers:new Map(P.fetchers),errors:{[t.route.id]:m.error}})}o(!pe(m),"Unhandled fetcher deferred data");let y={state:"idle",data:m.data,formMethod:void 0,formAction:void 0,formEncType:void 0,formData:void 0," _hasFetcherDoneAnything ":!0};P.fetchers.set(e,y),G({fetchers:new Map(P.fetchers)})}(e,n,f,y,h,m))},revalidate:function(){ie(),G({revalidation:"loading"}),"submitting"!==P.navigation.state&&("idle"!==P.navigation.state?ee(M||P.historyAction,P.navigation.location,{overrideNavigation:P.navigation}):ee(P.historyAction,P.location,{startUninterruptedRevalidation:!0}))},createHref:e=>r.history.createHref(e),encodeLocation:e=>r.history.encodeLocation(e),getFetcher:te,deleteFetcher:ve,dispose:function(){h&&h(),m.clear(),E&&E.abort(),P.fetchers.forEach(((e,t)=>ve(t))),P.blockers.forEach(((e,t)=>Ee(t)))},getBlocker:function(e,t){let r=P.blockers.get(e)||W;return I.get(e)!==t&&I.set(e,t),r},deleteBlocker:Ee,_internalFetchControllers:j,_internalActiveDeferreds:z,_internalSetRoutes:function(e){a=e}},A},e.createStaticHandler=function(e,r){o(e.length>0,"You must provide a non-empty routes array to createStaticHandler");let a={},n=(null==r?void 0:r.detectErrorBoundary)||V,i=f(e,n,void 0,a),c=(r?r.basename:null)||"/";async function d(e,r,i,s,l){o(e.signal,"query()/queryRoute() requests must contain an AbortController signal");try{if(De(e.method.toLowerCase())){let o=await async function(e,r,o,i,s){let l;if(o.route.action||o.route.lazy){if(l=await ae("action",e,o,r,a,n,c,!0,s,i),e.signal.aborted){throw new Error((s?"queryRoute":"query")+"() call aborted")}}else{let t=ue(405,{method:e.method,pathname:new URL(e.url).pathname,routeId:o.route.id});if(s)throw t;l={type:u.error,error:t}}if(ye(l))throw new Response(null,{status:l.status,headers:{Location:l.location}});if(pe(l)){let e=ue(400,{type:"defer-action"});if(s)throw e;l={type:u.error,error:e}}if(s){if(me(l))throw l.error;return{matches:[o],loaderData:{},actionData:{[o.route.id]:l.data},errors:null,statusCode:200,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(me(l)){let a=ce(r,o.route.id);return t({},await h(e,r,i,void 0,{[a.route.id]:l.error}),{statusCode:_(l.error)?l.error.status:500,actionData:null,actionHeaders:t({},l.headers?{[o.route.id]:l.headers}:{})})}let d=new Request(e.url,{headers:e.headers,redirect:e.redirect,signal:e.signal});return t({},await h(d,r,i),l.statusCode?{statusCode:l.statusCode}:{},{actionData:{[o.route.id]:l.data},actionHeaders:t({},l.headers?{[o.route.id]:l.headers}:{})})}(e,i,l||Pe(i,r),s,null!=l);return o}let o=await h(e,i,s,l);return ge(o)?o:t({},o,{actionData:null,actionHeaders:{}})}catch(e){if((d=e)&&ge(d.response)&&(d.type===u.data||u.error)){if(e.type===u.error&&!be(e.response))throw e.response;return e.response}if(be(e))return e;throw e}var d}async function h(e,r,o,i,s){let l=null!=i;if(l&&(null==i||!i.route.loader)&&(null==i||!i.route.lazy))throw ue(400,{method:e.method,pathname:new URL(e.url).pathname,routeId:null==i?void 0:i.route.id});let d=(i?[i]:Q(r,Object.keys(s||{})[0])).filter((e=>e.route.loader||e.route.lazy));if(0===d.length)return{matches:r,loaderData:r.reduce(((e,t)=>Object.assign(e,{[t.route.id]:null})),{}),errors:s||null,statusCode:200,loaderHeaders:{},activeDeferreds:null};let u=await Promise.all([...d.map((t=>ae("loader",e,t,r,a,n,c,!0,l,o)))]);if(e.signal.aborted){throw new Error((l?"queryRoute":"query")+"() call aborted")}let h=new Map,f=ie(r,d,u,s,h),p=new Set(d.map((e=>e.route.id)));return r.forEach((e=>{p.has(e.route.id)||(f.loaderData[e.route.id]=null)})),t({},f,{matches:r,activeDeferreds:h.size>0?Object.fromEntries(h.entries()):null})}return{dataRoutes:i,query:async function(e,r){let{requestContext:a}=void 0===r?{}:r,o=new URL(e.url),n=e.method,u=s("",l(o),null,"default"),h=p(i,u,c);if(!we(n)&&"HEAD"!==n){let e=ue(405,{method:n}),{matches:t,route:r}=de(i);return{basename:c,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}if(!h){let e=ue(404,{pathname:u.pathname}),{matches:t,route:r}=de(i);return{basename:c,location:u,matches:t,loaderData:{},actionData:null,errors:{[r.id]:e},statusCode:e.status,loaderHeaders:{},actionHeaders:{},activeDeferreds:null}}let f=await d(e,u,h,a);return ge(f)?f:t({location:u,basename:c},f)},queryRoute:async function(e,t){let{routeId:r,requestContext:a}=void 0===t?{}:t,o=new URL(e.url),n=e.method,u=s("",l(o),null,"default"),h=p(i,u,c);if(!we(n)&&"HEAD"!==n&&"OPTIONS"!==n)throw ue(405,{method:n});if(!h)throw ue(404,{pathname:u.pathname});let f=r?h.find((e=>e.route.id===r)):Pe(h,u);if(r&&!f)throw ue(403,{pathname:u.pathname,routeId:r});if(!f)throw ue(404,{pathname:u.pathname});let m=await d(e,u,h,a,f);if(ge(m))return m;let y=m.errors?Object.values(m.errors)[0]:void 0;if(void 0!==y)throw y;if(m.actionData)return Object.values(m.actionData)[0];if(m.loaderData){var v;let e=Object.values(m.loaderData)[0];return null!=(v=m.activeDeferreds)&&v[f.route.id]&&(e[G]=m.activeDeferreds[f.route.id]),e}}}},e.defer=function(e,t){return void 0===t&&(t={}),new j(e,"number"==typeof t?{status:t}:t)},e.generatePath=function(e,t){void 0===t&&(t={});let r=e;return r.endsWith("*")&&"*"!==r&&!r.endsWith("/*")&&(n(!1,'Route path "'+r+'" will be treated as if it were "'+r.replace(/\*$/,"/*")+'" because the `*` character must always follow a `/` in the pattern. To get rid of this warning, please change the route path to "'+r.replace(/\*$/,"/*")+'".'),r=r.replace(/\*$/,"/*")),(r.startsWith("/")?"/":"")+r.split(/\/+/).map(((e,r,a)=>{if(r===a.length-1&&"*"===e){return t["*"]}const n=e.match(/^:(\w+)(\??)$/);if(n){const[,e,r]=n;let a=t[e];return"?"===r?null==a?"":a:(null==a&&o(!1,'Missing ":'+e+'" param'),a)}return e.replace(/\?$/g,"")})).filter((e=>!!e)).join("/")},e.getStaticContextFromError=function(e,r,a){return t({},r,{statusCode:500,errors:{[r._deepestRenderedBoundaryId||e[0].id]:a}})},e.getToPathname=function(e){return""===e||""===e.pathname?"/":"string"==typeof e?c(e).pathname:e.pathname},e.isDeferredData=ve,e.isRouteErrorResponse=_,e.joinPaths=L,e.json=function(e,r){void 0===r&&(r={});let a="number"==typeof r?{status:r}:r,o=new Headers(a.headers);return o.has("Content-Type")||o.set("Content-Type","application/json; charset=utf-8"),new Response(JSON.stringify(e),t({},a,{headers:o}))},e.matchPath=D,e.matchRoutes=p,e.normalizePathname=k,e.parsePath=c,e.redirect=function(e,r){void 0===r&&(r=302);let a=r;"number"==typeof a?a={status:a}:void 0===a.status&&(a.status=302);let o=new Headers(a.headers);return o.set("Location",e),new Response(null,t({},a,{headers:o}))},e.resolvePath=E,e.resolveTo=M,e.stripBasename=R,Object.defineProperty(e,"__esModule",{value:!0})})); +//# sourceMappingURL=router.umd.min.js.map diff --git a/node_modules/@remix-run/router/dist/router.umd.min.js.map b/node_modules/@remix-run/router/dist/router.umd.min.js.map new file mode 100644 index 00000000..159d88cd --- /dev/null +++ b/node_modules/@remix-run/router/dist/router.umd.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"router.umd.min.js","sources":["../history.ts","../utils.ts","../router.ts"],"sourcesContent":["////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Actions represent the type of change to a location value.\n */\nexport enum Action {\n /**\n * A POP indicates a change to an arbitrary index in the history stack, such\n * as a back or forward navigation. It does not describe the direction of the\n * navigation, only that the current index changed.\n *\n * Note: This is the default action for newly created history objects.\n */\n Pop = \"POP\",\n\n /**\n * A PUSH indicates a new entry being added to the history stack, such as when\n * a link is clicked and a new page loads. When this happens, all subsequent\n * entries in the stack are lost.\n */\n Push = \"PUSH\",\n\n /**\n * A REPLACE indicates the entry at the current index in the history stack\n * being replaced by a new one.\n */\n Replace = \"REPLACE\",\n}\n\n/**\n * The pathname, search, and hash values of a URL.\n */\nexport interface Path {\n /**\n * A URL pathname, beginning with a /.\n */\n pathname: string;\n\n /**\n * A URL search string, beginning with a ?.\n */\n search: string;\n\n /**\n * A URL fragment identifier, beginning with a #.\n */\n hash: string;\n}\n\n/**\n * An entry in a history stack. A location contains information about the\n * URL path, as well as possibly some arbitrary state and a key.\n */\nexport interface Location extends Path {\n /**\n * A value of arbitrary data associated with this location.\n */\n state: any;\n\n /**\n * A unique string associated with this location. May be used to safely store\n * and retrieve data in some other storage API, like `localStorage`.\n *\n * Note: This value is always \"default\" on the initial location.\n */\n key: string;\n}\n\n/**\n * A change to the current location.\n */\nexport interface Update {\n /**\n * The action that triggered the change.\n */\n action: Action;\n\n /**\n * The new location.\n */\n location: Location;\n\n /**\n * The delta between this location and the former location in the history stack\n */\n delta: number | null;\n}\n\n/**\n * A function that receives notifications about location changes.\n */\nexport interface Listener {\n (update: Update): void;\n}\n\n/**\n * Describes a location that is the destination of some navigation, either via\n * `history.push` or `history.replace`. May be either a URL or the pieces of a\n * URL path.\n */\nexport type To = string | Partial;\n\n/**\n * A history is an interface to the navigation stack. The history serves as the\n * source of truth for the current location, as well as provides a set of\n * methods that may be used to change it.\n *\n * It is similar to the DOM's `window.history` object, but with a smaller, more\n * focused API.\n */\nexport interface History {\n /**\n * The last action that modified the current location. This will always be\n * Action.Pop when a history instance is first created. This value is mutable.\n */\n readonly action: Action;\n\n /**\n * The current location. This value is mutable.\n */\n readonly location: Location;\n\n /**\n * Returns a valid href for the given `to` value that may be used as\n * the value of an attribute.\n *\n * @param to - The destination URL\n */\n createHref(to: To): string;\n\n /**\n * Returns a URL for the given `to` value\n *\n * @param to - The destination URL\n */\n createURL(to: To): URL;\n\n /**\n * Encode a location the same way window.history would do (no-op for memory\n * history) so we ensure our PUSH/REPLACE navigations for data routers\n * behave the same as POP\n *\n * @param to Unencoded path\n */\n encodeLocation(to: To): Path;\n\n /**\n * Pushes a new location onto the history stack, increasing its length by one.\n * If there were any entries in the stack after the current one, they are\n * lost.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n push(to: To, state?: any): void;\n\n /**\n * Replaces the current location in the history stack with a new one. The\n * location that was replaced will no longer be available.\n *\n * @param to - The new URL\n * @param state - Data to associate with the new location\n */\n replace(to: To, state?: any): void;\n\n /**\n * Navigates `n` entries backward/forward in the history stack relative to the\n * current index. For example, a \"back\" navigation would use go(-1).\n *\n * @param delta - The delta in the stack index\n */\n go(delta: number): void;\n\n /**\n * Sets up a listener that will be called whenever the current location\n * changes.\n *\n * @param listener - A function that will be called when the location changes\n * @returns unlisten - A function that may be used to stop listening\n */\n listen(listener: Listener): () => void;\n}\n\ntype HistoryState = {\n usr: any;\n key?: string;\n idx: number;\n};\n\nconst PopStateEventType = \"popstate\";\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Memory History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A user-supplied object that describes a location. Used when providing\n * entries to `createMemoryHistory` via its `initialEntries` option.\n */\nexport type InitialEntry = string | Partial;\n\nexport type MemoryHistoryOptions = {\n initialEntries?: InitialEntry[];\n initialIndex?: number;\n v5Compat?: boolean;\n};\n\n/**\n * A memory history stores locations in memory. This is useful in stateful\n * environments where there is no web browser, such as node tests or React\n * Native.\n */\nexport interface MemoryHistory extends History {\n /**\n * The current index in the history stack.\n */\n readonly index: number;\n}\n\n/**\n * Memory history stores the current location in memory. It is designed for use\n * in stateful non-browser environments like tests and React Native.\n */\nexport function createMemoryHistory(\n options: MemoryHistoryOptions = {}\n): MemoryHistory {\n let { initialEntries = [\"/\"], initialIndex, v5Compat = false } = options;\n let entries: Location[]; // Declare so we can access from createMemoryLocation\n entries = initialEntries.map((entry, index) =>\n createMemoryLocation(\n entry,\n typeof entry === \"string\" ? null : entry.state,\n index === 0 ? \"default\" : undefined\n )\n );\n let index = clampIndex(\n initialIndex == null ? entries.length - 1 : initialIndex\n );\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n function clampIndex(n: number): number {\n return Math.min(Math.max(n, 0), entries.length - 1);\n }\n function getCurrentLocation(): Location {\n return entries[index];\n }\n function createMemoryLocation(\n to: To,\n state: any = null,\n key?: string\n ): Location {\n let location = createLocation(\n entries ? getCurrentLocation().pathname : \"/\",\n to,\n state,\n key\n );\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in memory history: ${JSON.stringify(\n to\n )}`\n );\n return location;\n }\n\n function createHref(to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n let history: MemoryHistory = {\n get index() {\n return index;\n },\n get action() {\n return action;\n },\n get location() {\n return getCurrentLocation();\n },\n createHref,\n createURL(to) {\n return new URL(createHref(to), \"http://localhost\");\n },\n encodeLocation(to: To) {\n let path = typeof to === \"string\" ? parsePath(to) : to;\n return {\n pathname: path.pathname || \"\",\n search: path.search || \"\",\n hash: path.hash || \"\",\n };\n },\n push(to, state) {\n action = Action.Push;\n let nextLocation = createMemoryLocation(to, state);\n index += 1;\n entries.splice(index, entries.length, nextLocation);\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 1 });\n }\n },\n replace(to, state) {\n action = Action.Replace;\n let nextLocation = createMemoryLocation(to, state);\n entries[index] = nextLocation;\n if (v5Compat && listener) {\n listener({ action, location: nextLocation, delta: 0 });\n }\n },\n go(delta) {\n action = Action.Pop;\n let nextIndex = clampIndex(index + delta);\n let nextLocation = entries[nextIndex];\n index = nextIndex;\n if (listener) {\n listener({ action, location: nextLocation, delta });\n }\n },\n listen(fn: Listener) {\n listener = fn;\n return () => {\n listener = null;\n };\n },\n };\n\n return history;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Browser History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A browser history stores the current location in regular URLs in a web\n * browser environment. This is the standard for most web apps and provides the\n * cleanest URLs the browser's address bar.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory\n */\nexport interface BrowserHistory extends UrlHistory {}\n\nexport type BrowserHistoryOptions = UrlHistoryOptions;\n\n/**\n * Browser history stores the location in regular URLs. This is the standard for\n * most web apps, but it requires some configuration on the server to ensure you\n * serve the same app at multiple URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory\n */\nexport function createBrowserHistory(\n options: BrowserHistoryOptions = {}\n): BrowserHistory {\n function createBrowserLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let { pathname, search, hash } = window.location;\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createBrowserHref(window: Window, to: To) {\n return typeof to === \"string\" ? to : createPath(to);\n }\n\n return getUrlBasedHistory(\n createBrowserLocation,\n createBrowserHref,\n null,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Hash History\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A hash history stores the current location in the fragment identifier portion\n * of the URL in a web browser environment.\n *\n * This is ideal for apps that do not control the server for some reason\n * (because the fragment identifier is never sent to the server), including some\n * shared hosting environments that do not provide fine-grained controls over\n * which pages are served at which URLs.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory\n */\nexport interface HashHistory extends UrlHistory {}\n\nexport type HashHistoryOptions = UrlHistoryOptions;\n\n/**\n * Hash history stores the location in window.location.hash. This makes it ideal\n * for situations where you don't want to send the location to the server for\n * some reason, either because you do cannot configure it or the URL space is\n * reserved for something else.\n *\n * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory\n */\nexport function createHashHistory(\n options: HashHistoryOptions = {}\n): HashHistory {\n function createHashLocation(\n window: Window,\n globalHistory: Window[\"history\"]\n ) {\n let {\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n } = parsePath(window.location.hash.substr(1));\n return createLocation(\n \"\",\n { pathname, search, hash },\n // state defaults to `null` because `window.history.state` does\n (globalHistory.state && globalHistory.state.usr) || null,\n (globalHistory.state && globalHistory.state.key) || \"default\"\n );\n }\n\n function createHashHref(window: Window, to: To) {\n let base = window.document.querySelector(\"base\");\n let href = \"\";\n\n if (base && base.getAttribute(\"href\")) {\n let url = window.location.href;\n let hashIndex = url.indexOf(\"#\");\n href = hashIndex === -1 ? url : url.slice(0, hashIndex);\n }\n\n return href + \"#\" + (typeof to === \"string\" ? to : createPath(to));\n }\n\n function validateHashLocation(location: Location, to: To) {\n warning(\n location.pathname.charAt(0) === \"/\",\n `relative pathnames are not supported in hash history.push(${JSON.stringify(\n to\n )})`\n );\n }\n\n return getUrlBasedHistory(\n createHashLocation,\n createHashHref,\n validateHashLocation,\n options\n );\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region UTILS\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * @private\n */\nexport function invariant(value: boolean, message?: string): asserts value;\nexport function invariant(\n value: T | null | undefined,\n message?: string\n): asserts value is T;\nexport function invariant(value: any, message?: string) {\n if (value === false || value === null || typeof value === \"undefined\") {\n throw new Error(message);\n }\n}\n\nexport function warning(cond: any, message: string) {\n if (!cond) {\n // eslint-disable-next-line no-console\n if (typeof console !== \"undefined\") console.warn(message);\n\n try {\n // Welcome to debugging history!\n //\n // This error is thrown as a convenience so you can more easily\n // find the source for a warning that appears in the console by\n // enabling \"pause on exceptions\" in your JavaScript debugger.\n throw new Error(message);\n // eslint-disable-next-line no-empty\n } catch (e) {}\n }\n}\n\nfunction createKey() {\n return Math.random().toString(36).substr(2, 8);\n}\n\n/**\n * For browser-based histories, we combine the state and key into an object\n */\nfunction getHistoryState(location: Location, index: number): HistoryState {\n return {\n usr: location.state,\n key: location.key,\n idx: index,\n };\n}\n\n/**\n * Creates a Location object with a unique key from the given Path\n */\nexport function createLocation(\n current: string | Location,\n to: To,\n state: any = null,\n key?: string\n): Readonly {\n let location: Readonly = {\n pathname: typeof current === \"string\" ? current : current.pathname,\n search: \"\",\n hash: \"\",\n ...(typeof to === \"string\" ? parsePath(to) : to),\n state,\n // TODO: This could be cleaned up. push/replace should probably just take\n // full Locations now and avoid the need to run through this flow at all\n // But that's a pretty big refactor to the current test suite so going to\n // keep as is for the time being and just let any incoming keys take precedence\n key: (to && (to as Location).key) || key || createKey(),\n };\n return location;\n}\n\n/**\n * Creates a string URL path from the given pathname, search, and hash components.\n */\nexport function createPath({\n pathname = \"/\",\n search = \"\",\n hash = \"\",\n}: Partial) {\n if (search && search !== \"?\")\n pathname += search.charAt(0) === \"?\" ? search : \"?\" + search;\n if (hash && hash !== \"#\")\n pathname += hash.charAt(0) === \"#\" ? hash : \"#\" + hash;\n return pathname;\n}\n\n/**\n * Parses a string URL path into its separate pathname, search, and hash components.\n */\nexport function parsePath(path: string): Partial {\n let parsedPath: Partial = {};\n\n if (path) {\n let hashIndex = path.indexOf(\"#\");\n if (hashIndex >= 0) {\n parsedPath.hash = path.substr(hashIndex);\n path = path.substr(0, hashIndex);\n }\n\n let searchIndex = path.indexOf(\"?\");\n if (searchIndex >= 0) {\n parsedPath.search = path.substr(searchIndex);\n path = path.substr(0, searchIndex);\n }\n\n if (path) {\n parsedPath.pathname = path;\n }\n }\n\n return parsedPath;\n}\n\nexport interface UrlHistory extends History {}\n\nexport type UrlHistoryOptions = {\n window?: Window;\n v5Compat?: boolean;\n};\n\nfunction getUrlBasedHistory(\n getLocation: (window: Window, globalHistory: Window[\"history\"]) => Location,\n createHref: (window: Window, to: To) => string,\n validateLocation: ((location: Location, to: To) => void) | null,\n options: UrlHistoryOptions = {}\n): UrlHistory {\n let { window = document.defaultView!, v5Compat = false } = options;\n let globalHistory = window.history;\n let action = Action.Pop;\n let listener: Listener | null = null;\n\n let index = getIndex()!;\n // Index should only be null when we initialize. If not, it's because the\n // user called history.pushState or history.replaceState directly, in which\n // case we should log a warning as it will result in bugs.\n if (index == null) {\n index = 0;\n globalHistory.replaceState({ ...globalHistory.state, idx: index }, \"\");\n }\n\n function getIndex(): number {\n let state = globalHistory.state || { idx: null };\n return state.idx;\n }\n\n function handlePop() {\n action = Action.Pop;\n let nextIndex = getIndex();\n let delta = nextIndex == null ? null : nextIndex - index;\n index = nextIndex;\n if (listener) {\n listener({ action, location: history.location, delta });\n }\n }\n\n function push(to: To, state?: any) {\n action = Action.Push;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex() + 1;\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n\n // try...catch because iOS limits us to 100 pushState calls :/\n try {\n globalHistory.pushState(historyState, \"\", url);\n } catch (error) {\n // They are going to lose state here, but there is no real\n // way to warn them about it since the page will refresh...\n window.location.assign(url);\n }\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 1 });\n }\n }\n\n function replace(to: To, state?: any) {\n action = Action.Replace;\n let location = createLocation(history.location, to, state);\n if (validateLocation) validateLocation(location, to);\n\n index = getIndex();\n let historyState = getHistoryState(location, index);\n let url = history.createHref(location);\n globalHistory.replaceState(historyState, \"\", url);\n\n if (v5Compat && listener) {\n listener({ action, location: history.location, delta: 0 });\n }\n }\n\n function createURL(to: To): URL {\n // window.location.origin is \"null\" (the literal string value) in Firefox\n // under certain conditions, notably when serving from a local HTML file\n // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297\n let base =\n window.location.origin !== \"null\"\n ? window.location.origin\n : window.location.href;\n\n let href = typeof to === \"string\" ? to : createPath(to);\n invariant(\n base,\n `No window.location.(origin|href) available to create URL for href: ${href}`\n );\n return new URL(href, base);\n }\n\n let history: History = {\n get action() {\n return action;\n },\n get location() {\n return getLocation(window, globalHistory);\n },\n listen(fn: Listener) {\n if (listener) {\n throw new Error(\"A history only accepts one active listener\");\n }\n window.addEventListener(PopStateEventType, handlePop);\n listener = fn;\n\n return () => {\n window.removeEventListener(PopStateEventType, handlePop);\n listener = null;\n };\n },\n createHref(to) {\n return createHref(window, to);\n },\n createURL,\n encodeLocation(to) {\n // Encode a Location the same way window.location would\n let url = createURL(to);\n return {\n pathname: url.pathname,\n search: url.search,\n hash: url.hash,\n };\n },\n push,\n replace,\n go(n) {\n return globalHistory.go(n);\n },\n };\n\n return history;\n}\n\n//#endregion\n","import type { Location, Path, To } from \"./history\";\nimport { warning, invariant, parsePath } from \"./history\";\n\n/**\n * Map of routeId -> data returned from a loader/action/error\n */\nexport interface RouteData {\n [routeId: string]: any;\n}\n\nexport enum ResultType {\n data = \"data\",\n deferred = \"deferred\",\n redirect = \"redirect\",\n error = \"error\",\n}\n\n/**\n * Successful result from a loader or action\n */\nexport interface SuccessResult {\n type: ResultType.data;\n data: any;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Successful defer() result from a loader or action\n */\nexport interface DeferredResult {\n type: ResultType.deferred;\n deferredData: DeferredData;\n statusCode?: number;\n headers?: Headers;\n}\n\n/**\n * Redirect result from a loader or action\n */\nexport interface RedirectResult {\n type: ResultType.redirect;\n status: number;\n location: string;\n revalidate: boolean;\n}\n\n/**\n * Unsuccessful result from a loader or action\n */\nexport interface ErrorResult {\n type: ResultType.error;\n error: any;\n headers?: Headers;\n}\n\n/**\n * Result from a loader or action - potentially successful or unsuccessful\n */\nexport type DataResult =\n | SuccessResult\n | DeferredResult\n | RedirectResult\n | ErrorResult;\n\ntype LowerCaseFormMethod = \"get\" | \"post\" | \"put\" | \"patch\" | \"delete\";\ntype UpperCaseFormMethod = Uppercase;\n\n/**\n * Users can specify either lowercase or uppercase form methods on ,\n * useSubmit(), , etc.\n */\nexport type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod;\n\n/**\n * Active navigation/fetcher form methods are exposed in lowercase on the\n * RouterState\n */\nexport type FormMethod = LowerCaseFormMethod;\nexport type MutationFormMethod = Exclude;\n\n/**\n * In v7, active navigation/fetcher form methods are exposed in uppercase on the\n * RouterState. This is to align with the normalization done via fetch().\n */\nexport type V7_FormMethod = UpperCaseFormMethod;\nexport type V7_MutationFormMethod = Exclude;\n\nexport type FormEncType =\n | \"application/x-www-form-urlencoded\"\n | \"multipart/form-data\";\n\n/**\n * @private\n * Internal interface to pass around for action submissions, not intended for\n * external consumption\n */\nexport interface Submission {\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n}\n\n/**\n * @private\n * Arguments passed to route loader/action functions. Same for now but we keep\n * this as a private implementation detail in case they diverge in the future.\n */\ninterface DataFunctionArgs {\n request: Request;\n params: Params;\n context?: any;\n}\n\n/**\n * Arguments passed to loader functions\n */\nexport interface LoaderFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Arguments passed to action functions\n */\nexport interface ActionFunctionArgs extends DataFunctionArgs {}\n\n/**\n * Route loader function signature\n */\nexport interface LoaderFunction {\n (args: LoaderFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route action function signature\n */\nexport interface ActionFunction {\n (args: ActionFunctionArgs): Promise | Response | Promise | any;\n}\n\n/**\n * Route shouldRevalidate function signature. This runs after any submission\n * (navigation or fetcher), so we flatten the navigation/fetcher submission\n * onto the arguments. It shouldn't matter whether it came from a navigation\n * or a fetcher, what really matters is the URLs and the formData since loaders\n * have to re-run based on the data models that were potentially mutated.\n */\nexport interface ShouldRevalidateFunction {\n (args: {\n currentUrl: URL;\n currentParams: AgnosticDataRouteMatch[\"params\"];\n nextUrl: URL;\n nextParams: AgnosticDataRouteMatch[\"params\"];\n formMethod?: Submission[\"formMethod\"];\n formAction?: Submission[\"formAction\"];\n formEncType?: Submission[\"formEncType\"];\n formData?: Submission[\"formData\"];\n actionResult?: DataResult;\n defaultShouldRevalidate: boolean;\n }): boolean;\n}\n\n/**\n * Function provided by the framework-aware layers to set `hasErrorBoundary`\n * from the framework-aware `errorElement` prop\n */\nexport interface DetectErrorBoundaryFunction {\n (route: AgnosticRouteObject): boolean;\n}\n\n/**\n * Keys we cannot change from within a lazy() function. We spread all other keys\n * onto the route. Either they're meaningful to the router, or they'll get\n * ignored.\n */\nexport type ImmutableRouteKey =\n | \"lazy\"\n | \"caseSensitive\"\n | \"path\"\n | \"id\"\n | \"index\"\n | \"children\";\n\nexport const immutableRouteKeys = new Set([\n \"lazy\",\n \"caseSensitive\",\n \"path\",\n \"id\",\n \"index\",\n \"children\",\n]);\n\n/**\n * lazy() function to load a route definition, which can add non-matching\n * related properties to a route\n */\nexport interface LazyRouteFunction {\n (): Promise>;\n}\n\n/**\n * Base RouteObject with common props shared by all types of routes\n */\ntype AgnosticBaseRouteObject = {\n caseSensitive?: boolean;\n path?: string;\n id?: string;\n loader?: LoaderFunction;\n action?: ActionFunction;\n hasErrorBoundary?: boolean;\n shouldRevalidate?: ShouldRevalidateFunction;\n handle?: any;\n lazy?: LazyRouteFunction;\n};\n\n/**\n * Index routes must not have children\n */\nexport type AgnosticIndexRouteObject = AgnosticBaseRouteObject & {\n children?: undefined;\n index: true;\n};\n\n/**\n * Non-index routes may have children, but cannot have index\n */\nexport type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & {\n children?: AgnosticRouteObject[];\n index?: false;\n};\n\n/**\n * A route object represents a logical route, with (optionally) its child\n * routes organized in a tree-like structure.\n */\nexport type AgnosticRouteObject =\n | AgnosticIndexRouteObject\n | AgnosticNonIndexRouteObject;\n\nexport type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & {\n id: string;\n};\n\nexport type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & {\n children?: AgnosticDataRouteObject[];\n id: string;\n};\n\n/**\n * A data route object, which is just a RouteObject with a required unique ID\n */\nexport type AgnosticDataRouteObject =\n | AgnosticDataIndexRouteObject\n | AgnosticDataNonIndexRouteObject;\n\nexport type RouteManifest = Record;\n\n// Recursive helper for finding path parameters in the absence of wildcards\ntype _PathParam =\n // split path into individual path segments\n Path extends `${infer L}/${infer R}`\n ? _PathParam | _PathParam\n : // find params after `:`\n Path extends `:${infer Param}`\n ? Param extends `${infer Optional}?`\n ? Optional\n : Param\n : // otherwise, there aren't any params present\n never;\n\n/**\n * Examples:\n * \"/a/b/*\" -> \"*\"\n * \":a\" -> \"a\"\n * \"/a/:b\" -> \"b\"\n * \"/a/blahblahblah:b\" -> \"b\"\n * \"/:a/:b\" -> \"a\" | \"b\"\n * \"/:a/b/:c/*\" -> \"a\" | \"c\" | \"*\"\n */\ntype PathParam =\n // check if path is just a wildcard\n Path extends \"*\" | \"/*\"\n ? \"*\"\n : // look for wildcard at the end of the path\n Path extends `${infer Rest}/*`\n ? \"*\" | _PathParam\n : // look for params in the absence of wildcards\n _PathParam;\n\n// Attempt to parse the given string segment. If it fails, then just return the\n// plain string type as a default fallback. Otherwise return the union of the\n// parsed string literals that were referenced as dynamic segments in the route.\nexport type ParamParseKey =\n // if could not find path params, fallback to `string`\n [PathParam] extends [never] ? string : PathParam;\n\n/**\n * The parameters that were parsed from the URL path.\n */\nexport type Params = {\n readonly [key in Key]: string | undefined;\n};\n\n/**\n * A RouteMatch contains info about how a route matched a URL.\n */\nexport interface AgnosticRouteMatch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The route object that was used to match.\n */\n route: RouteObjectType;\n}\n\nexport interface AgnosticDataRouteMatch\n extends AgnosticRouteMatch {}\n\nfunction isIndexRoute(\n route: AgnosticRouteObject\n): route is AgnosticIndexRouteObject {\n return route.index === true;\n}\n\n// Walk the route tree generating unique IDs where necessary so we are working\n// solely with AgnosticDataRouteObject's within the Router\nexport function convertRoutesToDataRoutes(\n routes: AgnosticRouteObject[],\n detectErrorBoundary: DetectErrorBoundaryFunction,\n parentPath: number[] = [],\n manifest: RouteManifest = {}\n): AgnosticDataRouteObject[] {\n return routes.map((route, index) => {\n let treePath = [...parentPath, index];\n let id = typeof route.id === \"string\" ? route.id : treePath.join(\"-\");\n invariant(\n route.index !== true || !route.children,\n `Cannot specify children on an index route`\n );\n invariant(\n !manifest[id],\n `Found a route id collision on id \"${id}\". Route ` +\n \"id's must be globally unique within Data Router usages\"\n );\n\n if (isIndexRoute(route)) {\n let indexRoute: AgnosticDataIndexRouteObject = {\n ...route,\n hasErrorBoundary: detectErrorBoundary(route),\n id,\n };\n manifest[id] = indexRoute;\n return indexRoute;\n } else {\n let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = {\n ...route,\n id,\n hasErrorBoundary: detectErrorBoundary(route),\n children: undefined,\n };\n manifest[id] = pathOrLayoutRoute;\n\n if (route.children) {\n pathOrLayoutRoute.children = convertRoutesToDataRoutes(\n route.children,\n detectErrorBoundary,\n treePath,\n manifest\n );\n }\n\n return pathOrLayoutRoute;\n }\n });\n}\n\n/**\n * Matches the given routes to a location and returns the match data.\n *\n * @see https://reactrouter.com/utils/match-routes\n */\nexport function matchRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n locationArg: Partial | string,\n basename = \"/\"\n): AgnosticRouteMatch[] | null {\n let location =\n typeof locationArg === \"string\" ? parsePath(locationArg) : locationArg;\n\n let pathname = stripBasename(location.pathname || \"/\", basename);\n\n if (pathname == null) {\n return null;\n }\n\n let branches = flattenRoutes(routes);\n rankRouteBranches(branches);\n\n let matches = null;\n for (let i = 0; matches == null && i < branches.length; ++i) {\n matches = matchRouteBranch(\n branches[i],\n // Incoming pathnames are generally encoded from either window.location\n // or from router.navigate, but we want to match against the unencoded\n // paths in the route definitions. Memory router locations won't be\n // encoded here but there also shouldn't be anything to decode so this\n // should be a safe operation. This avoids needing matchRoutes to be\n // history-aware.\n safelyDecodeURI(pathname)\n );\n }\n\n return matches;\n}\n\ninterface RouteMeta<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n relativePath: string;\n caseSensitive: boolean;\n childrenIndex: number;\n route: RouteObjectType;\n}\n\ninterface RouteBranch<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n> {\n path: string;\n score: number;\n routesMeta: RouteMeta[];\n}\n\nfunction flattenRoutes<\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n routes: RouteObjectType[],\n branches: RouteBranch[] = [],\n parentsMeta: RouteMeta[] = [],\n parentPath = \"\"\n): RouteBranch[] {\n let flattenRoute = (\n route: RouteObjectType,\n index: number,\n relativePath?: string\n ) => {\n let meta: RouteMeta = {\n relativePath:\n relativePath === undefined ? route.path || \"\" : relativePath,\n caseSensitive: route.caseSensitive === true,\n childrenIndex: index,\n route,\n };\n\n if (meta.relativePath.startsWith(\"/\")) {\n invariant(\n meta.relativePath.startsWith(parentPath),\n `Absolute route path \"${meta.relativePath}\" nested under path ` +\n `\"${parentPath}\" is not valid. An absolute child route path ` +\n `must start with the combined path of all its parent routes.`\n );\n\n meta.relativePath = meta.relativePath.slice(parentPath.length);\n }\n\n let path = joinPaths([parentPath, meta.relativePath]);\n let routesMeta = parentsMeta.concat(meta);\n\n // Add the children before adding this route to the array so we traverse the\n // route tree depth-first and child routes appear before their parents in\n // the \"flattened\" version.\n if (route.children && route.children.length > 0) {\n invariant(\n // Our types know better, but runtime JS may not!\n // @ts-expect-error\n route.index !== true,\n `Index routes must not have child routes. Please remove ` +\n `all child routes from route path \"${path}\".`\n );\n\n flattenRoutes(route.children, branches, routesMeta, path);\n }\n\n // Routes without a path shouldn't ever match by themselves unless they are\n // index routes, so don't add them to the list of possible branches.\n if (route.path == null && !route.index) {\n return;\n }\n\n branches.push({\n path,\n score: computeScore(path, route.index),\n routesMeta,\n });\n };\n routes.forEach((route, index) => {\n // coarse-grain check for optional params\n if (route.path === \"\" || !route.path?.includes(\"?\")) {\n flattenRoute(route, index);\n } else {\n for (let exploded of explodeOptionalSegments(route.path)) {\n flattenRoute(route, index, exploded);\n }\n }\n });\n\n return branches;\n}\n\n/**\n * Computes all combinations of optional path segments for a given path,\n * excluding combinations that are ambiguous and of lower priority.\n *\n * For example, `/one/:two?/three/:four?/:five?` explodes to:\n * - `/one/three`\n * - `/one/:two/three`\n * - `/one/three/:four`\n * - `/one/three/:five`\n * - `/one/:two/three/:four`\n * - `/one/:two/three/:five`\n * - `/one/three/:four/:five`\n * - `/one/:two/three/:four/:five`\n */\nfunction explodeOptionalSegments(path: string): string[] {\n let segments = path.split(\"/\");\n if (segments.length === 0) return [];\n\n let [first, ...rest] = segments;\n\n // Optional path segments are denoted by a trailing `?`\n let isOptional = first.endsWith(\"?\");\n // Compute the corresponding required segment: `foo?` -> `foo`\n let required = first.replace(/\\?$/, \"\");\n\n if (rest.length === 0) {\n // Intepret empty string as omitting an optional segment\n // `[\"one\", \"\", \"three\"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`\n return isOptional ? [required, \"\"] : [required];\n }\n\n let restExploded = explodeOptionalSegments(rest.join(\"/\"));\n\n let result: string[] = [];\n\n // All child paths with the prefix. Do this for all children before the\n // optional version for all children so we get consistent ordering where the\n // parent optional aspect is preferred as required. Otherwise, we can get\n // child sections interspersed where deeper optional segments are higher than\n // parent optional segments, where for example, /:two would explodes _earlier_\n // then /:one. By always including the parent as required _for all children_\n // first, we avoid this issue\n result.push(\n ...restExploded.map((subpath) =>\n subpath === \"\" ? required : [required, subpath].join(\"/\")\n )\n );\n\n // Then if this is an optional value, add all child versions without\n if (isOptional) {\n result.push(...restExploded);\n }\n\n // for absolute paths, ensure `/` instead of empty segment\n return result.map((exploded) =>\n path.startsWith(\"/\") && exploded === \"\" ? \"/\" : exploded\n );\n}\n\nfunction rankRouteBranches(branches: RouteBranch[]): void {\n branches.sort((a, b) =>\n a.score !== b.score\n ? b.score - a.score // Higher score first\n : compareIndexes(\n a.routesMeta.map((meta) => meta.childrenIndex),\n b.routesMeta.map((meta) => meta.childrenIndex)\n )\n );\n}\n\nconst paramRe = /^:\\w+$/;\nconst dynamicSegmentValue = 3;\nconst indexRouteValue = 2;\nconst emptySegmentValue = 1;\nconst staticSegmentValue = 10;\nconst splatPenalty = -2;\nconst isSplat = (s: string) => s === \"*\";\n\nfunction computeScore(path: string, index: boolean | undefined): number {\n let segments = path.split(\"/\");\n let initialScore = segments.length;\n if (segments.some(isSplat)) {\n initialScore += splatPenalty;\n }\n\n if (index) {\n initialScore += indexRouteValue;\n }\n\n return segments\n .filter((s) => !isSplat(s))\n .reduce(\n (score, segment) =>\n score +\n (paramRe.test(segment)\n ? dynamicSegmentValue\n : segment === \"\"\n ? emptySegmentValue\n : staticSegmentValue),\n initialScore\n );\n}\n\nfunction compareIndexes(a: number[], b: number[]): number {\n let siblings =\n a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);\n\n return siblings\n ? // If two routes are siblings, we should try to match the earlier sibling\n // first. This allows people to have fine-grained control over the matching\n // behavior by simply putting routes with identical paths in the order they\n // want them tried.\n a[a.length - 1] - b[b.length - 1]\n : // Otherwise, it doesn't really make sense to rank non-siblings by index,\n // so they sort equally.\n 0;\n}\n\nfunction matchRouteBranch<\n ParamKey extends string = string,\n RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject\n>(\n branch: RouteBranch,\n pathname: string\n): AgnosticRouteMatch[] | null {\n let { routesMeta } = branch;\n\n let matchedParams = {};\n let matchedPathname = \"/\";\n let matches: AgnosticRouteMatch[] = [];\n for (let i = 0; i < routesMeta.length; ++i) {\n let meta = routesMeta[i];\n let end = i === routesMeta.length - 1;\n let remainingPathname =\n matchedPathname === \"/\"\n ? pathname\n : pathname.slice(matchedPathname.length) || \"/\";\n let match = matchPath(\n { path: meta.relativePath, caseSensitive: meta.caseSensitive, end },\n remainingPathname\n );\n\n if (!match) return null;\n\n Object.assign(matchedParams, match.params);\n\n let route = meta.route;\n\n matches.push({\n // TODO: Can this as be avoided?\n params: matchedParams as Params,\n pathname: joinPaths([matchedPathname, match.pathname]),\n pathnameBase: normalizePathname(\n joinPaths([matchedPathname, match.pathnameBase])\n ),\n route,\n });\n\n if (match.pathnameBase !== \"/\") {\n matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);\n }\n }\n\n return matches;\n}\n\n/**\n * Returns a path with params interpolated.\n *\n * @see https://reactrouter.com/utils/generate-path\n */\nexport function generatePath(\n originalPath: Path,\n params: {\n [key in PathParam]: string | null;\n } = {} as any\n): string {\n let path: string = originalPath;\n if (path.endsWith(\"*\") && path !== \"*\" && !path.endsWith(\"/*\")) {\n warning(\n false,\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n path = path.replace(/\\*$/, \"/*\") as Path;\n }\n\n // ensure `/` is added at the beginning if the path is absolute\n const prefix = path.startsWith(\"/\") ? \"/\" : \"\";\n\n const segments = path\n .split(/\\/+/)\n .map((segment, index, array) => {\n const isLastSegment = index === array.length - 1;\n\n // only apply the splat if it's the last segment\n if (isLastSegment && segment === \"*\") {\n const star = \"*\" as PathParam;\n const starParam = params[star];\n\n // Apply the splat\n return starParam;\n }\n\n const keyMatch = segment.match(/^:(\\w+)(\\??)$/);\n if (keyMatch) {\n const [, key, optional] = keyMatch;\n let param = params[key as PathParam];\n\n if (optional === \"?\") {\n return param == null ? \"\" : param;\n }\n\n if (param == null) {\n invariant(false, `Missing \":${key}\" param`);\n }\n\n return param;\n }\n\n // Remove any optional markers from optional static segments\n return segment.replace(/\\?$/g, \"\");\n })\n // Remove empty segments\n .filter((segment) => !!segment);\n\n return prefix + segments.join(\"/\");\n}\n\n/**\n * A PathPattern is used to match on some portion of a URL pathname.\n */\nexport interface PathPattern {\n /**\n * A string to match against a URL pathname. May contain `:id`-style segments\n * to indicate placeholders for dynamic parameters. May also end with `/*` to\n * indicate matching the rest of the URL pathname.\n */\n path: Path;\n /**\n * Should be `true` if the static portions of the `path` should be matched in\n * the same case.\n */\n caseSensitive?: boolean;\n /**\n * Should be `true` if this pattern should match the entire URL pathname.\n */\n end?: boolean;\n}\n\n/**\n * A PathMatch contains info about how a PathPattern matched on a URL pathname.\n */\nexport interface PathMatch {\n /**\n * The names and values of dynamic parameters in the URL.\n */\n params: Params;\n /**\n * The portion of the URL pathname that was matched.\n */\n pathname: string;\n /**\n * The portion of the URL pathname that was matched before child routes.\n */\n pathnameBase: string;\n /**\n * The pattern that was used to match.\n */\n pattern: PathPattern;\n}\n\ntype Mutable = {\n -readonly [P in keyof T]: T[P];\n};\n\n/**\n * Performs pattern matching on a URL pathname and returns information about\n * the match.\n *\n * @see https://reactrouter.com/utils/match-path\n */\nexport function matchPath<\n ParamKey extends ParamParseKey,\n Path extends string\n>(\n pattern: PathPattern | Path,\n pathname: string\n): PathMatch | null {\n if (typeof pattern === \"string\") {\n pattern = { path: pattern, caseSensitive: false, end: true };\n }\n\n let [matcher, paramNames] = compilePath(\n pattern.path,\n pattern.caseSensitive,\n pattern.end\n );\n\n let match = pathname.match(matcher);\n if (!match) return null;\n\n let matchedPathname = match[0];\n let pathnameBase = matchedPathname.replace(/(.)\\/+$/, \"$1\");\n let captureGroups = match.slice(1);\n let params: Params = paramNames.reduce>(\n (memo, paramName, index) => {\n // We need to compute the pathnameBase here using the raw splat value\n // instead of using params[\"*\"] later because it will be decoded then\n if (paramName === \"*\") {\n let splatValue = captureGroups[index] || \"\";\n pathnameBase = matchedPathname\n .slice(0, matchedPathname.length - splatValue.length)\n .replace(/(.)\\/+$/, \"$1\");\n }\n\n memo[paramName] = safelyDecodeURIComponent(\n captureGroups[index] || \"\",\n paramName\n );\n return memo;\n },\n {}\n );\n\n return {\n params,\n pathname: matchedPathname,\n pathnameBase,\n pattern,\n };\n}\n\nfunction compilePath(\n path: string,\n caseSensitive = false,\n end = true\n): [RegExp, string[]] {\n warning(\n path === \"*\" || !path.endsWith(\"*\") || path.endsWith(\"/*\"),\n `Route path \"${path}\" will be treated as if it were ` +\n `\"${path.replace(/\\*$/, \"/*\")}\" because the \\`*\\` character must ` +\n `always follow a \\`/\\` in the pattern. To get rid of this warning, ` +\n `please change the route path to \"${path.replace(/\\*$/, \"/*\")}\".`\n );\n\n let paramNames: string[] = [];\n let regexpSource =\n \"^\" +\n path\n .replace(/\\/*\\*?$/, \"\") // Ignore trailing / and /*, we'll handle it below\n .replace(/^\\/*/, \"/\") // Make sure it has a leading /\n .replace(/[\\\\.*+^$?{}|()[\\]]/g, \"\\\\$&\") // Escape special regex chars\n .replace(/\\/:(\\w+)/g, (_: string, paramName: string) => {\n paramNames.push(paramName);\n return \"/([^\\\\/]+)\";\n });\n\n if (path.endsWith(\"*\")) {\n paramNames.push(\"*\");\n regexpSource +=\n path === \"*\" || path === \"/*\"\n ? \"(.*)$\" // Already matched the initial /, just match the rest\n : \"(?:\\\\/(.+)|\\\\/*)$\"; // Don't include the / in params[\"*\"]\n } else if (end) {\n // When matching to the end, ignore trailing slashes\n regexpSource += \"\\\\/*$\";\n } else if (path !== \"\" && path !== \"/\") {\n // If our path is non-empty and contains anything beyond an initial slash,\n // then we have _some_ form of path in our regex so we should expect to\n // match only if we find the end of this path segment. Look for an optional\n // non-captured trailing slash (to match a portion of the URL) or the end\n // of the path (if we've matched to the end). We used to do this with a\n // word boundary but that gives false positives on routes like\n // /user-preferences since `-` counts as a word boundary.\n regexpSource += \"(?:(?=\\\\/|$))\";\n } else {\n // Nothing to match for \"\" or \"/\"\n }\n\n let matcher = new RegExp(regexpSource, caseSensitive ? undefined : \"i\");\n\n return [matcher, paramNames];\n}\n\nfunction safelyDecodeURI(value: string) {\n try {\n return decodeURI(value);\n } catch (error) {\n warning(\n false,\n `The URL path \"${value}\" could not be decoded because it is is a ` +\n `malformed URL segment. This is probably due to a bad percent ` +\n `encoding (${error}).`\n );\n\n return value;\n }\n}\n\nfunction safelyDecodeURIComponent(value: string, paramName: string) {\n try {\n return decodeURIComponent(value);\n } catch (error) {\n warning(\n false,\n `The value for the URL param \"${paramName}\" will not be decoded because` +\n ` the string \"${value}\" is a malformed URL segment. This is probably` +\n ` due to a bad percent encoding (${error}).`\n );\n\n return value;\n }\n}\n\n/**\n * @private\n */\nexport function stripBasename(\n pathname: string,\n basename: string\n): string | null {\n if (basename === \"/\") return pathname;\n\n if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {\n return null;\n }\n\n // We want to leave trailing slash behavior in the user's control, so if they\n // specify a basename with a trailing slash, we should support it\n let startIndex = basename.endsWith(\"/\")\n ? basename.length - 1\n : basename.length;\n let nextChar = pathname.charAt(startIndex);\n if (nextChar && nextChar !== \"/\") {\n // pathname does not start with basename/\n return null;\n }\n\n return pathname.slice(startIndex) || \"/\";\n}\n\n/**\n * Returns a resolved path object relative to the given pathname.\n *\n * @see https://reactrouter.com/utils/resolve-path\n */\nexport function resolvePath(to: To, fromPathname = \"/\"): Path {\n let {\n pathname: toPathname,\n search = \"\",\n hash = \"\",\n } = typeof to === \"string\" ? parsePath(to) : to;\n\n let pathname = toPathname\n ? toPathname.startsWith(\"/\")\n ? toPathname\n : resolvePathname(toPathname, fromPathname)\n : fromPathname;\n\n return {\n pathname,\n search: normalizeSearch(search),\n hash: normalizeHash(hash),\n };\n}\n\nfunction resolvePathname(relativePath: string, fromPathname: string): string {\n let segments = fromPathname.replace(/\\/+$/, \"\").split(\"/\");\n let relativeSegments = relativePath.split(\"/\");\n\n relativeSegments.forEach((segment) => {\n if (segment === \"..\") {\n // Keep the root \"\" segment so the pathname starts at /\n if (segments.length > 1) segments.pop();\n } else if (segment !== \".\") {\n segments.push(segment);\n }\n });\n\n return segments.length > 1 ? segments.join(\"/\") : \"/\";\n}\n\nfunction getInvalidPathError(\n char: string,\n field: string,\n dest: string,\n path: Partial\n) {\n return (\n `Cannot include a '${char}' character in a manually specified ` +\n `\\`to.${field}\\` field [${JSON.stringify(\n path\n )}]. Please separate it out to the ` +\n `\\`to.${dest}\\` field. Alternatively you may provide the full path as ` +\n `a string in and the router will parse it for you.`\n );\n}\n\n/**\n * @private\n *\n * When processing relative navigation we want to ignore ancestor routes that\n * do not contribute to the path, such that index/pathless layout routes don't\n * interfere.\n *\n * For example, when moving a route element into an index route and/or a\n * pathless layout route, relative link behavior contained within should stay\n * the same. Both of the following examples should link back to the root:\n *\n * \n * \n * \n *\n * \n * \n * }> // <-- Does not contribute\n * // <-- Does not contribute\n * \n * \n */\nexport function getPathContributingMatches<\n T extends AgnosticRouteMatch = AgnosticRouteMatch\n>(matches: T[]) {\n return matches.filter(\n (match, index) =>\n index === 0 || (match.route.path && match.route.path.length > 0)\n );\n}\n\n/**\n * @private\n */\nexport function resolveTo(\n toArg: To,\n routePathnames: string[],\n locationPathname: string,\n isPathRelative = false\n): Path {\n let to: Partial;\n if (typeof toArg === \"string\") {\n to = parsePath(toArg);\n } else {\n to = { ...toArg };\n\n invariant(\n !to.pathname || !to.pathname.includes(\"?\"),\n getInvalidPathError(\"?\", \"pathname\", \"search\", to)\n );\n invariant(\n !to.pathname || !to.pathname.includes(\"#\"),\n getInvalidPathError(\"#\", \"pathname\", \"hash\", to)\n );\n invariant(\n !to.search || !to.search.includes(\"#\"),\n getInvalidPathError(\"#\", \"search\", \"hash\", to)\n );\n }\n\n let isEmptyPath = toArg === \"\" || to.pathname === \"\";\n let toPathname = isEmptyPath ? \"/\" : to.pathname;\n\n let from: string;\n\n // Routing is relative to the current pathname if explicitly requested.\n //\n // If a pathname is explicitly provided in `to`, it should be relative to the\n // route context. This is explained in `Note on `` values` in our\n // migration guide from v5 as a means of disambiguation between `to` values\n // that begin with `/` and those that do not. However, this is problematic for\n // `to` values that do not provide a pathname. `to` can simply be a search or\n // hash string, in which case we should assume that the navigation is relative\n // to the current location's pathname and *not* the route pathname.\n if (isPathRelative || toPathname == null) {\n from = locationPathname;\n } else {\n let routePathnameIndex = routePathnames.length - 1;\n\n if (toPathname.startsWith(\"..\")) {\n let toSegments = toPathname.split(\"/\");\n\n // Each leading .. segment means \"go up one route\" instead of \"go up one\n // URL segment\". This is a key difference from how works and a\n // major reason we call this a \"to\" value instead of a \"href\".\n while (toSegments[0] === \"..\") {\n toSegments.shift();\n routePathnameIndex -= 1;\n }\n\n to.pathname = toSegments.join(\"/\");\n }\n\n // If there are more \"..\" segments than parent routes, resolve relative to\n // the root / URL.\n from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : \"/\";\n }\n\n let path = resolvePath(to, from);\n\n // Ensure the pathname has a trailing slash if the original \"to\" had one\n let hasExplicitTrailingSlash =\n toPathname && toPathname !== \"/\" && toPathname.endsWith(\"/\");\n // Or if this was a link to the current path which has a trailing slash\n let hasCurrentTrailingSlash =\n (isEmptyPath || toPathname === \".\") && locationPathname.endsWith(\"/\");\n if (\n !path.pathname.endsWith(\"/\") &&\n (hasExplicitTrailingSlash || hasCurrentTrailingSlash)\n ) {\n path.pathname += \"/\";\n }\n\n return path;\n}\n\n/**\n * @private\n */\nexport function getToPathname(to: To): string | undefined {\n // Empty strings should be treated the same as / paths\n return to === \"\" || (to as Path).pathname === \"\"\n ? \"/\"\n : typeof to === \"string\"\n ? parsePath(to).pathname\n : to.pathname;\n}\n\n/**\n * @private\n */\nexport const joinPaths = (paths: string[]): string =>\n paths.join(\"/\").replace(/\\/\\/+/g, \"/\");\n\n/**\n * @private\n */\nexport const normalizePathname = (pathname: string): string =>\n pathname.replace(/\\/+$/, \"\").replace(/^\\/*/, \"/\");\n\n/**\n * @private\n */\nexport const normalizeSearch = (search: string): string =>\n !search || search === \"?\"\n ? \"\"\n : search.startsWith(\"?\")\n ? search\n : \"?\" + search;\n\n/**\n * @private\n */\nexport const normalizeHash = (hash: string): string =>\n !hash || hash === \"#\" ? \"\" : hash.startsWith(\"#\") ? hash : \"#\" + hash;\n\nexport type JsonFunction = (\n data: Data,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * This is a shortcut for creating `application/json` responses. Converts `data`\n * to JSON and sets the `Content-Type` header.\n */\nexport const json: JsonFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n let headers = new Headers(responseInit.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json; charset=utf-8\");\n }\n\n return new Response(JSON.stringify(data), {\n ...responseInit,\n headers,\n });\n};\n\nexport interface TrackedPromise extends Promise {\n _tracked?: boolean;\n _data?: any;\n _error?: any;\n}\n\nexport class AbortedDeferredError extends Error {}\n\nexport class DeferredData {\n private pendingKeysSet: Set = new Set();\n private controller: AbortController;\n private abortPromise: Promise;\n private unlistenAbortSignal: () => void;\n private subscribers: Set<(aborted: boolean, settledKey?: string) => void> =\n new Set();\n data: Record;\n init?: ResponseInit;\n deferredKeys: string[] = [];\n\n constructor(data: Record, responseInit?: ResponseInit) {\n invariant(\n data && typeof data === \"object\" && !Array.isArray(data),\n \"defer() only accepts plain objects\"\n );\n\n // Set up an AbortController + Promise we can race against to exit early\n // cancellation\n let reject: (e: AbortedDeferredError) => void;\n this.abortPromise = new Promise((_, r) => (reject = r));\n this.controller = new AbortController();\n let onAbort = () =>\n reject(new AbortedDeferredError(\"Deferred data aborted\"));\n this.unlistenAbortSignal = () =>\n this.controller.signal.removeEventListener(\"abort\", onAbort);\n this.controller.signal.addEventListener(\"abort\", onAbort);\n\n this.data = Object.entries(data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: this.trackPromise(key, value),\n }),\n {}\n );\n\n if (this.done) {\n // All incoming values were resolved\n this.unlistenAbortSignal();\n }\n\n this.init = responseInit;\n }\n\n private trackPromise(\n key: string,\n value: Promise | unknown\n ): TrackedPromise | unknown {\n if (!(value instanceof Promise)) {\n return value;\n }\n\n this.deferredKeys.push(key);\n this.pendingKeysSet.add(key);\n\n // We store a little wrapper promise that will be extended with\n // _data/_error props upon resolve/reject\n let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then(\n (data) => this.onSettle(promise, key, null, data as unknown),\n (error) => this.onSettle(promise, key, error as unknown)\n );\n\n // Register rejection listeners to avoid uncaught promise rejections on\n // errors or aborted deferred values\n promise.catch(() => {});\n\n Object.defineProperty(promise, \"_tracked\", { get: () => true });\n return promise;\n }\n\n private onSettle(\n promise: TrackedPromise,\n key: string,\n error: unknown,\n data?: unknown\n ): unknown {\n if (\n this.controller.signal.aborted &&\n error instanceof AbortedDeferredError\n ) {\n this.unlistenAbortSignal();\n Object.defineProperty(promise, \"_error\", { get: () => error });\n return Promise.reject(error);\n }\n\n this.pendingKeysSet.delete(key);\n\n if (this.done) {\n // Nothing left to abort!\n this.unlistenAbortSignal();\n }\n\n if (error) {\n Object.defineProperty(promise, \"_error\", { get: () => error });\n this.emit(false, key);\n return Promise.reject(error);\n }\n\n Object.defineProperty(promise, \"_data\", { get: () => data });\n this.emit(false, key);\n return data;\n }\n\n private emit(aborted: boolean, settledKey?: string) {\n this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey));\n }\n\n subscribe(fn: (aborted: boolean, settledKey?: string) => void) {\n this.subscribers.add(fn);\n return () => this.subscribers.delete(fn);\n }\n\n cancel() {\n this.controller.abort();\n this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));\n this.emit(true);\n }\n\n async resolveData(signal: AbortSignal) {\n let aborted = false;\n if (!this.done) {\n let onAbort = () => this.cancel();\n signal.addEventListener(\"abort\", onAbort);\n aborted = await new Promise((resolve) => {\n this.subscribe((aborted) => {\n signal.removeEventListener(\"abort\", onAbort);\n if (aborted || this.done) {\n resolve(aborted);\n }\n });\n });\n }\n return aborted;\n }\n\n get done() {\n return this.pendingKeysSet.size === 0;\n }\n\n get unwrappedData() {\n invariant(\n this.data !== null && this.done,\n \"Can only unwrap data on initialized and settled deferreds\"\n );\n\n return Object.entries(this.data).reduce(\n (acc, [key, value]) =>\n Object.assign(acc, {\n [key]: unwrapTrackedPromise(value),\n }),\n {}\n );\n }\n\n get pendingKeys() {\n return Array.from(this.pendingKeysSet);\n }\n}\n\nfunction isTrackedPromise(value: any): value is TrackedPromise {\n return (\n value instanceof Promise && (value as TrackedPromise)._tracked === true\n );\n}\n\nfunction unwrapTrackedPromise(value: any) {\n if (!isTrackedPromise(value)) {\n return value;\n }\n\n if (value._error) {\n throw value._error;\n }\n return value._data;\n}\n\nexport type DeferFunction = (\n data: Record,\n init?: number | ResponseInit\n) => DeferredData;\n\nexport const defer: DeferFunction = (data, init = {}) => {\n let responseInit = typeof init === \"number\" ? { status: init } : init;\n\n return new DeferredData(data, responseInit);\n};\n\nexport type RedirectFunction = (\n url: string,\n init?: number | ResponseInit\n) => Response;\n\n/**\n * A redirect response. Sets the status code and the `Location` header.\n * Defaults to \"302 Found\".\n */\nexport const redirect: RedirectFunction = (url, init = 302) => {\n let responseInit = init;\n if (typeof responseInit === \"number\") {\n responseInit = { status: responseInit };\n } else if (typeof responseInit.status === \"undefined\") {\n responseInit.status = 302;\n }\n\n let headers = new Headers(responseInit.headers);\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...responseInit,\n headers,\n });\n};\n\n/**\n * @private\n * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies\n */\nexport class ErrorResponse {\n status: number;\n statusText: string;\n data: any;\n error?: Error;\n internal: boolean;\n\n constructor(\n status: number,\n statusText: string | undefined,\n data: any,\n internal = false\n ) {\n this.status = status;\n this.statusText = statusText || \"\";\n this.internal = internal;\n if (data instanceof Error) {\n this.data = data.toString();\n this.error = data;\n } else {\n this.data = data;\n }\n }\n}\n\n/**\n * Check if the given error is an ErrorResponse generated from a 4xx/5xx\n * Response thrown from an action/loader\n */\nexport function isRouteErrorResponse(error: any): error is ErrorResponse {\n return (\n error != null &&\n typeof error.status === \"number\" &&\n typeof error.statusText === \"string\" &&\n typeof error.internal === \"boolean\" &&\n \"data\" in error\n );\n}\n","import type { History, Location, Path, To } from \"./history\";\nimport {\n Action as HistoryAction,\n createLocation,\n createPath,\n invariant,\n parsePath,\n warning,\n} from \"./history\";\nimport type {\n DataResult,\n DeferredData,\n AgnosticDataRouteMatch,\n AgnosticDataRouteObject,\n DeferredResult,\n ErrorResult,\n FormEncType,\n FormMethod,\n DetectErrorBoundaryFunction,\n RedirectResult,\n RouteData,\n AgnosticRouteObject,\n Submission,\n SuccessResult,\n AgnosticRouteMatch,\n ShouldRevalidateFunction,\n RouteManifest,\n ImmutableRouteKey,\n ActionFunction,\n LoaderFunction,\n V7_MutationFormMethod,\n V7_FormMethod,\n HTMLFormMethod,\n MutationFormMethod,\n} from \"./utils\";\nimport {\n ErrorResponse,\n ResultType,\n convertRoutesToDataRoutes,\n getPathContributingMatches,\n immutableRouteKeys,\n isRouteErrorResponse,\n joinPaths,\n matchRoutes,\n resolveTo,\n stripBasename,\n} from \"./utils\";\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Types and Constants\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * A Router instance manages all navigation and data loading/mutations\n */\nexport interface Router {\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the basename for the router\n */\n get basename(): RouterInit[\"basename\"];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the current state of the router\n */\n get state(): RouterState;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Return the routes for this router instance\n */\n get routes(): AgnosticDataRouteObject[];\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Initialize the router, including adding history listeners and kicking off\n * initial data fetches. Returns a function to cleanup listeners and abort\n * any in-progress loads\n */\n initialize(): Router;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Subscribe to router.state updates\n *\n * @param fn function to call with the new state\n */\n subscribe(fn: RouterSubscriber): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Enable scroll restoration behavior in the router\n *\n * @param savedScrollPositions Object that will manage positions, in case\n * it's being restored from sessionStorage\n * @param getScrollPosition Function to get the active Y scroll position\n * @param getKey Function to get the key to use for restoration\n */\n enableScrollRestoration(\n savedScrollPositions: Record,\n getScrollPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ): () => void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Navigate forward/backward in the history stack\n * @param to Delta to move in the history stack\n */\n navigate(to: number): Promise;\n\n /**\n * Navigate to the given path\n * @param to Path to navigate to\n * @param opts Navigation options (method, submission, etc.)\n */\n navigate(to: To, opts?: RouterNavigateOptions): Promise;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a fetcher load/submission\n *\n * @param key Fetcher key\n * @param routeId Route that owns the fetcher\n * @param href href to fetch\n * @param opts Fetcher options, (method, submission, etc.)\n */\n fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterNavigateOptions\n ): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Trigger a revalidation of all current route loaders and fetcher loads\n */\n revalidate(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to create an href for the given location\n * @param location\n */\n createHref(location: Location | URL): string;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Utility function to URL encode a destination path according to the internal\n * history implementation\n * @param to\n */\n encodeLocation(to: To): Path;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get/create a fetcher for the given key\n * @param key\n */\n getFetcher(key?: string): Fetcher;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete the fetcher for a given key\n * @param key\n */\n deleteFetcher(key?: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Cleanup listeners and abort any in-progress loads\n */\n dispose(): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Get a navigation blocker\n * @param key The identifier for the blocker\n * @param fn The blocker function implementation\n */\n getBlocker(key: string, fn: BlockerFunction): Blocker;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Delete a navigation blocker\n * @param key The identifier for the blocker\n */\n deleteBlocker(key: string): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * HMR needs to pass in-flight route updates to React Router\n * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute)\n */\n _internalSetRoutes(routes: AgnosticRouteObject[]): void;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal fetch AbortControllers accessed by unit tests\n */\n _internalFetchControllers: Map;\n\n /**\n * @internal\n * PRIVATE - DO NOT USE\n *\n * Internal pending DeferredData instances accessed by unit tests\n */\n _internalActiveDeferreds: Map;\n}\n\n/**\n * State maintained internally by the router. During a navigation, all states\n * reflect the the \"old\" location unless otherwise noted.\n */\nexport interface RouterState {\n /**\n * The action of the most recent navigation\n */\n historyAction: HistoryAction;\n\n /**\n * The current location reflected by the router\n */\n location: Location;\n\n /**\n * The current set of route matches\n */\n matches: AgnosticDataRouteMatch[];\n\n /**\n * Tracks whether we've completed our initial data load\n */\n initialized: boolean;\n\n /**\n * Current scroll position we should start at for a new view\n * - number -> scroll position to restore to\n * - false -> do not restore scroll at all (used during submissions)\n * - null -> don't have a saved position, scroll to hash or top of page\n */\n restoreScrollPosition: number | false | null;\n\n /**\n * Indicate whether this navigation should skip resetting the scroll position\n * if we are unable to restore the scroll position\n */\n preventScrollReset: boolean;\n\n /**\n * Tracks the state of the current navigation\n */\n navigation: Navigation;\n\n /**\n * Tracks any in-progress revalidations\n */\n revalidation: RevalidationState;\n\n /**\n * Data from the loaders for the current matches\n */\n loaderData: RouteData;\n\n /**\n * Data from the action for the current matches\n */\n actionData: RouteData | null;\n\n /**\n * Errors caught from loaders for the current matches\n */\n errors: RouteData | null;\n\n /**\n * Map of current fetchers\n */\n fetchers: Map;\n\n /**\n * Map of current blockers\n */\n blockers: Map;\n}\n\n/**\n * Data that can be passed into hydrate a Router from SSR\n */\nexport type HydrationState = Partial<\n Pick\n>;\n\n/**\n * Future flags to toggle new feature behavior\n */\nexport interface FutureConfig {\n v7_normalizeFormMethod: boolean;\n}\n\n/**\n * Initialization options for createRouter\n */\nexport interface RouterInit {\n routes: AgnosticRouteObject[];\n history: History;\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n future?: FutureConfig;\n hydrationData?: HydrationState;\n}\n\n/**\n * State returned from a server-side query() call\n */\nexport interface StaticHandlerContext {\n basename: Router[\"basename\"];\n location: RouterState[\"location\"];\n matches: RouterState[\"matches\"];\n loaderData: RouterState[\"loaderData\"];\n actionData: RouterState[\"actionData\"];\n errors: RouterState[\"errors\"];\n statusCode: number;\n loaderHeaders: Record;\n actionHeaders: Record;\n activeDeferreds: Record | null;\n _deepestRenderedBoundaryId?: string | null;\n}\n\n/**\n * A StaticHandler instance manages a singular SSR navigation/fetch event\n */\nexport interface StaticHandler {\n dataRoutes: AgnosticDataRouteObject[];\n query(\n request: Request,\n opts?: { requestContext?: unknown }\n ): Promise;\n queryRoute(\n request: Request,\n opts?: { routeId?: string; requestContext?: unknown }\n ): Promise;\n}\n\n/**\n * Subscriber function signature for changes to router state\n */\nexport interface RouterSubscriber {\n (state: RouterState): void;\n}\n\ninterface UseMatchesMatch {\n id: string;\n pathname: string;\n params: AgnosticRouteMatch[\"params\"];\n data: unknown;\n handle: unknown;\n}\n\n/**\n * Function signature for determining the key to be used in scroll restoration\n * for a given location\n */\nexport interface GetScrollRestorationKeyFunction {\n (location: Location, matches: UseMatchesMatch[]): string | null;\n}\n\n/**\n * Function signature for determining the current scroll position\n */\nexport interface GetScrollPositionFunction {\n (): number;\n}\n\n/**\n * Options for a navigate() call for a Link navigation\n */\ntype LinkNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n};\n\n/**\n * Options for a navigate() call for a Form navigation\n */\ntype SubmissionNavigateOptions = {\n replace?: boolean;\n state?: any;\n preventScrollReset?: boolean;\n formMethod?: HTMLFormMethod;\n formEncType?: FormEncType;\n formData: FormData;\n};\n\n/**\n * Options to pass to navigate() for either a Link or Form navigation\n */\nexport type RouterNavigateOptions =\n | LinkNavigateOptions\n | SubmissionNavigateOptions;\n\n/**\n * Options to pass to fetch()\n */\nexport type RouterFetchOptions =\n | Omit\n | Omit;\n\n/**\n * Potential states for state.navigation\n */\nexport type NavigationStates = {\n Idle: {\n state: \"idle\";\n location: undefined;\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n };\n Loading: {\n state: \"loading\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n };\n Submitting: {\n state: \"submitting\";\n location: Location;\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n };\n};\n\nexport type Navigation = NavigationStates[keyof NavigationStates];\n\nexport type RevalidationState = \"idle\" | \"loading\";\n\n/**\n * Potential states for fetchers\n */\ntype FetcherStates = {\n Idle: {\n state: \"idle\";\n formMethod: undefined;\n formAction: undefined;\n formEncType: undefined;\n formData: undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Loading: {\n state: \"loading\";\n formMethod: FormMethod | V7_FormMethod | undefined;\n formAction: string | undefined;\n formEncType: FormEncType | undefined;\n formData: FormData | undefined;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n Submitting: {\n state: \"submitting\";\n formMethod: FormMethod | V7_FormMethod;\n formAction: string;\n formEncType: FormEncType;\n formData: FormData;\n data: TData | undefined;\n \" _hasFetcherDoneAnything \"?: boolean;\n };\n};\n\nexport type Fetcher =\n FetcherStates[keyof FetcherStates];\n\ninterface BlockerBlocked {\n state: \"blocked\";\n reset(): void;\n proceed(): void;\n location: Location;\n}\n\ninterface BlockerUnblocked {\n state: \"unblocked\";\n reset: undefined;\n proceed: undefined;\n location: undefined;\n}\n\ninterface BlockerProceeding {\n state: \"proceeding\";\n reset: undefined;\n proceed: undefined;\n location: Location;\n}\n\nexport type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding;\n\nexport type BlockerFunction = (args: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n}) => boolean;\n\ninterface ShortCircuitable {\n /**\n * startNavigation does not need to complete the navigation because we\n * redirected or got interrupted\n */\n shortCircuited?: boolean;\n}\n\ninterface HandleActionResult extends ShortCircuitable {\n /**\n * Error thrown from the current action, keyed by the route containing the\n * error boundary to render the error. To be committed to the state after\n * loaders have completed\n */\n pendingActionError?: RouteData;\n /**\n * Data returned from the current action, keyed by the route owning the action.\n * To be committed to the state after loaders have completed\n */\n pendingActionData?: RouteData;\n}\n\ninterface HandleLoadersResult extends ShortCircuitable {\n /**\n * loaderData returned from the current set of loaders\n */\n loaderData?: RouterState[\"loaderData\"];\n /**\n * errors thrown from the current set of loaders\n */\n errors?: RouterState[\"errors\"];\n}\n\n/**\n * Cached info for active fetcher.load() instances so they can participate\n * in revalidation\n */\ninterface FetchLoadMatch {\n routeId: string;\n path: string;\n}\n\n/**\n * Identified fetcher.load() calls that need to be revalidated\n */\ninterface RevalidatingFetcher extends FetchLoadMatch {\n key: string;\n match: AgnosticDataRouteMatch | null;\n matches: AgnosticDataRouteMatch[] | null;\n}\n\n/**\n * Wrapper object to allow us to throw any response out from callLoaderOrAction\n * for queryRouter while preserving whether or not it was thrown or returned\n * from the loader/action\n */\ninterface QueryRouteResponse {\n type: ResultType.data | ResultType.error;\n response: Response;\n}\n\nconst validMutationMethodsArr: MutationFormMethod[] = [\n \"post\",\n \"put\",\n \"patch\",\n \"delete\",\n];\nconst validMutationMethods = new Set(\n validMutationMethodsArr\n);\n\nconst validRequestMethodsArr: FormMethod[] = [\n \"get\",\n ...validMutationMethodsArr,\n];\nconst validRequestMethods = new Set(validRequestMethodsArr);\n\nconst redirectStatusCodes = new Set([301, 302, 303, 307, 308]);\nconst redirectPreserveMethodStatusCodes = new Set([307, 308]);\n\nexport const IDLE_NAVIGATION: NavigationStates[\"Idle\"] = {\n state: \"idle\",\n location: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_FETCHER: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: undefined,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n};\n\nexport const IDLE_BLOCKER: BlockerUnblocked = {\n state: \"unblocked\",\n proceed: undefined,\n reset: undefined,\n location: undefined,\n};\n\nconst ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\\/\\/)/i;\n\nconst isBrowser =\n typeof window !== \"undefined\" &&\n typeof window.document !== \"undefined\" &&\n typeof window.document.createElement !== \"undefined\";\nconst isServer = !isBrowser;\n\nconst defaultDetectErrorBoundary = (route: AgnosticRouteObject) =>\n Boolean(route.hasErrorBoundary);\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createRouter\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Create a router and listen to history POP navigations\n */\nexport function createRouter(init: RouterInit): Router {\n invariant(\n init.routes.length > 0,\n \"You must provide a non-empty routes array to createRouter\"\n );\n\n let detectErrorBoundary =\n init.detectErrorBoundary || defaultDetectErrorBoundary;\n\n // Routes keyed by ID\n let manifest: RouteManifest = {};\n // Routes in tree format for matching\n let dataRoutes = convertRoutesToDataRoutes(\n init.routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined;\n // Config driven behavior flags\n let future: FutureConfig = {\n v7_normalizeFormMethod: false,\n ...init.future,\n };\n // Cleanup function for history\n let unlistenHistory: (() => void) | null = null;\n // Externally-provided functions to call on all state changes\n let subscribers = new Set();\n // Externally-provided object to hold scroll restoration locations during routing\n let savedScrollPositions: Record | null = null;\n // Externally-provided function to get scroll restoration keys\n let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null;\n // Externally-provided function to get current scroll position\n let getScrollPosition: GetScrollPositionFunction | null = null;\n // One-time flag to control the initial hydration scroll restoration. Because\n // we don't get the saved positions from until _after_\n // the initial render, we need to manually trigger a separate updateState to\n // send along the restoreScrollPosition\n // Set to true if we have `hydrationData` since we assume we were SSR'd and that\n // SSR did the initial scroll restoration.\n let initialScrollRestored = init.hydrationData != null;\n\n let initialMatches = matchRoutes(\n dataRoutes,\n init.history.location,\n init.basename\n );\n let initialErrors: RouteData | null = null;\n\n if (initialMatches == null) {\n // If we do not match a user-provided-route, fall back to the root\n // to allow the error boundary to take over\n let error = getInternalRouterError(404, {\n pathname: init.history.location.pathname,\n });\n let { matches, route } = getShortCircuitMatches(dataRoutes);\n initialMatches = matches;\n initialErrors = { [route.id]: error };\n }\n\n let initialized =\n // All initialMatches need to be loaded before we're ready. If we have lazy\n // functions around still then we'll need to run them in initialize()\n !initialMatches.some((m) => m.route.lazy) &&\n // And we have to either have no loaders or have been provided hydrationData\n (!initialMatches.some((m) => m.route.loader) || init.hydrationData != null);\n\n let router: Router;\n let state: RouterState = {\n historyAction: init.history.action,\n location: init.history.location,\n matches: initialMatches,\n initialized,\n navigation: IDLE_NAVIGATION,\n // Don't restore on initial updateState() if we were SSR'd\n restoreScrollPosition: init.hydrationData != null ? false : null,\n preventScrollReset: false,\n revalidation: \"idle\",\n loaderData: (init.hydrationData && init.hydrationData.loaderData) || {},\n actionData: (init.hydrationData && init.hydrationData.actionData) || null,\n errors: (init.hydrationData && init.hydrationData.errors) || initialErrors,\n fetchers: new Map(),\n blockers: new Map(),\n };\n\n // -- Stateful internal variables to manage navigations --\n // Current navigation in progress (to be committed in completeNavigation)\n let pendingAction: HistoryAction = HistoryAction.Pop;\n\n // Should the current navigation prevent the scroll reset if scroll cannot\n // be restored?\n let pendingPreventScrollReset = false;\n\n // AbortController for the active navigation\n let pendingNavigationController: AbortController | null;\n\n // We use this to avoid touching history in completeNavigation if a\n // revalidation is entirely uninterrupted\n let isUninterruptedRevalidation = false;\n\n // Use this internal flag to force revalidation of all loaders:\n // - submissions (completed or interrupted)\n // - useRevalidate()\n // - X-Remix-Revalidate (from redirect)\n let isRevalidationRequired = false;\n\n // Use this internal array to capture routes that require revalidation due\n // to a cancelled deferred on action submission\n let cancelledDeferredRoutes: string[] = [];\n\n // Use this internal array to capture fetcher loads that were cancelled by an\n // action navigation and require revalidation\n let cancelledFetcherLoads: string[] = [];\n\n // AbortControllers for any in-flight fetchers\n let fetchControllers = new Map();\n\n // Track loads based on the order in which they started\n let incrementingLoadId = 0;\n\n // Track the outstanding pending navigation data load to be compared against\n // the globally incrementing load when a fetcher load lands after a completed\n // navigation\n let pendingNavigationLoadId = -1;\n\n // Fetchers that triggered data reloads as a result of their actions\n let fetchReloadIds = new Map();\n\n // Fetchers that triggered redirect navigations from their actions\n let fetchRedirectIds = new Set();\n\n // Most recent href/match for fetcher.load calls for fetchers\n let fetchLoadMatches = new Map();\n\n // Store DeferredData instances for active route matches. When a\n // route loader returns defer() we stick one in here. Then, when a nested\n // promise resolves we update loaderData. If a new navigation starts we\n // cancel active deferreds for eliminated routes.\n let activeDeferreds = new Map();\n\n // Store blocker functions in a separate Map outside of router state since\n // we don't need to update UI state if they change\n let blockerFunctions = new Map();\n\n // Flag to ignore the next history update, so we can revert the URL change on\n // a POP navigation that was blocked by the user without touching router state\n let ignoreNextHistoryUpdate = false;\n\n // Initialize the router, all side effects should be kicked off from here.\n // Implemented as a Fluent API for ease of:\n // let router = createRouter(init).initialize();\n function initialize() {\n // If history informs us of a POP navigation, start the navigation but do not update\n // state. We'll update our own state once the navigation completes\n unlistenHistory = init.history.listen(\n ({ action: historyAction, location, delta }) => {\n // Ignore this event if it was just us resetting the URL from a\n // blocked POP navigation\n if (ignoreNextHistoryUpdate) {\n ignoreNextHistoryUpdate = false;\n return;\n }\n\n warning(\n blockerFunctions.size === 0 || delta != null,\n \"You are trying to use a blocker on a POP navigation to a location \" +\n \"that was not created by @remix-run/router. This will fail silently in \" +\n \"production. This can happen if you are navigating outside the router \" +\n \"via `window.history.pushState`/`window.location.hash` instead of using \" +\n \"router navigation APIs. This can also happen if you are using \" +\n \"createHashRouter and the user manually changes the URL.\"\n );\n\n let blockerKey = shouldBlockNavigation({\n currentLocation: state.location,\n nextLocation: location,\n historyAction,\n });\n\n if (blockerKey && delta != null) {\n // Restore the URL to match the current UI, but don't update router state\n ignoreNextHistoryUpdate = true;\n init.history.go(delta * -1);\n\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location,\n });\n // Re-do the same POP navigation we just blocked\n init.history.go(delta);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(router.state.blockers) });\n },\n });\n return;\n }\n\n return startNavigation(historyAction, location);\n }\n );\n\n // Kick off initial data load if needed. Use Pop to avoid modifying history\n // Note we don't do any handling of lazy here. For SPA's it'll get handled\n // in the normal navigation flow. For SSR it's expected that lazy modules are\n // resolved prior to router creation since we can't go into a fallbackElement\n // UI for SSR'd apps\n if (!state.initialized) {\n startNavigation(HistoryAction.Pop, state.location);\n }\n\n return router;\n }\n\n // Clean up a router and it's side effects\n function dispose() {\n if (unlistenHistory) {\n unlistenHistory();\n }\n subscribers.clear();\n pendingNavigationController && pendingNavigationController.abort();\n state.fetchers.forEach((_, key) => deleteFetcher(key));\n state.blockers.forEach((_, key) => deleteBlocker(key));\n }\n\n // Subscribe to state updates for the router\n function subscribe(fn: RouterSubscriber) {\n subscribers.add(fn);\n return () => subscribers.delete(fn);\n }\n\n // Update our state and notify the calling context of the change\n function updateState(newState: Partial): void {\n state = {\n ...state,\n ...newState,\n };\n subscribers.forEach((subscriber) => subscriber(state));\n }\n\n // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION\n // and setting state.[historyAction/location/matches] to the new route.\n // - Location is a required param\n // - Navigation will always be set to IDLE_NAVIGATION\n // - Can pass any other state in newState\n function completeNavigation(\n location: Location,\n newState: Partial>\n ): void {\n // Deduce if we're in a loading/actionReload state:\n // - We have committed actionData in the store\n // - The current navigation was a mutation submission\n // - We're past the submitting state and into the loading state\n // - The location being loaded is not the result of a redirect\n let isActionReload =\n state.actionData != null &&\n state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n state.navigation.state === \"loading\" &&\n location.state?._isRedirect !== true;\n\n let actionData: RouteData | null;\n if (newState.actionData) {\n if (Object.keys(newState.actionData).length > 0) {\n actionData = newState.actionData;\n } else {\n // Empty actionData -> clear prior actionData due to an action error\n actionData = null;\n }\n } else if (isActionReload) {\n // Keep the current data if we're wrapping up the action reload\n actionData = state.actionData;\n } else {\n // Clear actionData on any other completed navigations\n actionData = null;\n }\n\n // Always preserve any existing loaderData from re-used routes\n let loaderData = newState.loaderData\n ? mergeLoaderData(\n state.loaderData,\n newState.loaderData,\n newState.matches || [],\n newState.errors\n )\n : state.loaderData;\n\n // On a successful navigation we can assume we got through all blockers\n // so we can start fresh\n for (let [key] of blockerFunctions) {\n deleteBlocker(key);\n }\n\n // Always respect the user flag. Otherwise don't reset on mutation\n // submission navigations unless they redirect\n let preventScrollReset =\n pendingPreventScrollReset === true ||\n (state.navigation.formMethod != null &&\n isMutationMethod(state.navigation.formMethod) &&\n location.state?._isRedirect !== true);\n\n if (inFlightDataRoutes) {\n dataRoutes = inFlightDataRoutes;\n inFlightDataRoutes = undefined;\n }\n\n updateState({\n ...newState, // matches, errors, fetchers go through as-is\n actionData,\n loaderData,\n historyAction: pendingAction,\n location,\n initialized: true,\n navigation: IDLE_NAVIGATION,\n revalidation: \"idle\",\n restoreScrollPosition: getSavedScrollPosition(\n location,\n newState.matches || state.matches\n ),\n preventScrollReset,\n blockers: new Map(state.blockers),\n });\n\n if (isUninterruptedRevalidation) {\n // If this was an uninterrupted revalidation then do not touch history\n } else if (pendingAction === HistoryAction.Pop) {\n // Do nothing for POP - URL has already been updated\n } else if (pendingAction === HistoryAction.Push) {\n init.history.push(location, location.state);\n } else if (pendingAction === HistoryAction.Replace) {\n init.history.replace(location, location.state);\n }\n\n // Reset stateful navigation vars\n pendingAction = HistoryAction.Pop;\n pendingPreventScrollReset = false;\n isUninterruptedRevalidation = false;\n isRevalidationRequired = false;\n cancelledDeferredRoutes = [];\n cancelledFetcherLoads = [];\n }\n\n // Trigger a navigation event, which can either be a numerical POP or a PUSH\n // replace with an optional submission\n async function navigate(\n to: number | To,\n opts?: RouterNavigateOptions\n ): Promise {\n if (typeof to === \"number\") {\n init.history.go(to);\n return;\n }\n\n let { path, submission, error } = normalizeNavigateOptions(\n to,\n future,\n opts\n );\n\n let currentLocation = state.location;\n let nextLocation = createLocation(state.location, path, opts && opts.state);\n\n // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded\n // URL from window.location, so we need to encode it here so the behavior\n // remains the same as POP and non-data-router usages. new URL() does all\n // the same encoding we'd get from a history.pushState/window.location read\n // without having to touch history\n nextLocation = {\n ...nextLocation,\n ...init.history.encodeLocation(nextLocation),\n };\n\n let userReplace = opts && opts.replace != null ? opts.replace : undefined;\n\n let historyAction = HistoryAction.Push;\n\n if (userReplace === true) {\n historyAction = HistoryAction.Replace;\n } else if (userReplace === false) {\n // no-op\n } else if (\n submission != null &&\n isMutationMethod(submission.formMethod) &&\n submission.formAction === state.location.pathname + state.location.search\n ) {\n // By default on submissions to the current location we REPLACE so that\n // users don't have to double-click the back button to get to the prior\n // location. If the user redirects to a different location from the\n // action/loader this will be ignored and the redirect will be a PUSH\n historyAction = HistoryAction.Replace;\n }\n\n let preventScrollReset =\n opts && \"preventScrollReset\" in opts\n ? opts.preventScrollReset === true\n : undefined;\n\n let blockerKey = shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n });\n if (blockerKey) {\n // Put the blocker into a blocked state\n updateBlocker(blockerKey, {\n state: \"blocked\",\n location: nextLocation,\n proceed() {\n updateBlocker(blockerKey!, {\n state: \"proceeding\",\n proceed: undefined,\n reset: undefined,\n location: nextLocation,\n });\n // Send the same navigation through\n navigate(to, opts);\n },\n reset() {\n deleteBlocker(blockerKey!);\n updateState({ blockers: new Map(state.blockers) });\n },\n });\n return;\n }\n\n return await startNavigation(historyAction, nextLocation, {\n submission,\n // Send through the formData serialization error if we have one so we can\n // render at the right error boundary after we match routes\n pendingError: error,\n preventScrollReset,\n replace: opts && opts.replace,\n });\n }\n\n // Revalidate all current loaders. If a navigation is in progress or if this\n // is interrupted by a navigation, allow this to \"succeed\" by calling all\n // loaders during the next loader round\n function revalidate() {\n interruptActiveLoads();\n updateState({ revalidation: \"loading\" });\n\n // If we're currently submitting an action, we don't need to start a new\n // navigation, we'll just let the follow up loader execution call all loaders\n if (state.navigation.state === \"submitting\") {\n return;\n }\n\n // If we're currently in an idle state, start a new navigation for the current\n // action/location and mark it as uninterrupted, which will skip the history\n // update in completeNavigation\n if (state.navigation.state === \"idle\") {\n startNavigation(state.historyAction, state.location, {\n startUninterruptedRevalidation: true,\n });\n return;\n }\n\n // Otherwise, if we're currently in a loading state, just start a new\n // navigation to the navigation.location but do not trigger an uninterrupted\n // revalidation so that history correctly updates once the navigation completes\n startNavigation(\n pendingAction || state.historyAction,\n state.navigation.location,\n { overrideNavigation: state.navigation }\n );\n }\n\n // Start a navigation to the given action/location. Can optionally provide a\n // overrideNavigation which will override the normalLoad in the case of a redirect\n // navigation\n async function startNavigation(\n historyAction: HistoryAction,\n location: Location,\n opts?: {\n submission?: Submission;\n fetcherSubmission?: Submission;\n overrideNavigation?: Navigation;\n pendingError?: ErrorResponse;\n startUninterruptedRevalidation?: boolean;\n preventScrollReset?: boolean;\n replace?: boolean;\n }\n ): Promise {\n // Abort any in-progress navigations and start a new one. Unset any ongoing\n // uninterrupted revalidations unless told otherwise, since we want this\n // new navigation to update history normally\n pendingNavigationController && pendingNavigationController.abort();\n pendingNavigationController = null;\n pendingAction = historyAction;\n isUninterruptedRevalidation =\n (opts && opts.startUninterruptedRevalidation) === true;\n\n // Save the current scroll position every time we start a new navigation,\n // and track whether we should reset scroll on completion\n saveScrollPosition(state.location, state.matches);\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let loadingNavigation = opts && opts.overrideNavigation;\n let matches = matchRoutes(routesToUse, location, init.basename);\n\n // Short circuit with a 404 on the root error boundary if we match nothing\n if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(routesToUse);\n // Cancel all pending deferred on 404s since we don't keep any routes\n cancelActiveDeferreds();\n completeNavigation(location, {\n matches: notFoundMatches,\n loaderData: {},\n errors: {\n [route.id]: error,\n },\n });\n return;\n }\n\n // Short circuit if it's only a hash change and not a mutation submission\n // For example, on /page#hash and submit a which will\n // default to a navigation to /page\n if (\n isHashChangeOnly(state.location, location) &&\n !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))\n ) {\n completeNavigation(location, { matches });\n return;\n }\n\n // Create a controller/Request for this navigation\n pendingNavigationController = new AbortController();\n let request = createClientSideRequest(\n init.history,\n location,\n pendingNavigationController.signal,\n opts && opts.submission\n );\n let pendingActionData: RouteData | undefined;\n let pendingError: RouteData | undefined;\n\n if (opts && opts.pendingError) {\n // If we have a pendingError, it means the user attempted a GET submission\n // with binary FormData so assign here and skip to handleLoaders. That\n // way we handle calling loaders above the boundary etc. It's not really\n // different from an actionError in that sense.\n pendingError = {\n [findNearestBoundary(matches).route.id]: opts.pendingError,\n };\n } else if (\n opts &&\n opts.submission &&\n isMutationMethod(opts.submission.formMethod)\n ) {\n // Call action if we received an action submission\n let actionOutput = await handleAction(\n request,\n location,\n opts.submission,\n matches,\n { replace: opts.replace }\n );\n\n if (actionOutput.shortCircuited) {\n return;\n }\n\n pendingActionData = actionOutput.pendingActionData;\n pendingError = actionOutput.pendingActionError;\n\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n ...opts.submission,\n };\n loadingNavigation = navigation;\n\n // Create a GET request for the loaders\n request = new Request(request.url, { signal: request.signal });\n }\n\n // Call loaders\n let { shortCircuited, loaderData, errors } = await handleLoaders(\n request,\n location,\n matches,\n loadingNavigation,\n opts && opts.submission,\n opts && opts.fetcherSubmission,\n opts && opts.replace,\n pendingActionData,\n pendingError\n );\n\n if (shortCircuited) {\n return;\n }\n\n // Clean up now that the action/loaders have completed. Don't clean up if\n // we short circuited because pendingNavigationController will have already\n // been assigned to a new controller for the next navigation\n pendingNavigationController = null;\n\n completeNavigation(location, {\n matches,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n loaderData,\n errors,\n });\n }\n\n // Call the action matched by the leaf route for this navigation and handle\n // redirects/errors\n async function handleAction(\n request: Request,\n location: Location,\n submission: Submission,\n matches: AgnosticDataRouteMatch[],\n opts?: { replace?: boolean }\n ): Promise {\n interruptActiveLoads();\n\n // Put us in a submitting state\n let navigation: NavigationStates[\"Submitting\"] = {\n state: \"submitting\",\n location,\n ...submission,\n };\n updateState({ navigation });\n\n // Call our action and get the result\n let result: DataResult;\n let actionMatch = getTargetMatch(matches, location);\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n result = {\n type: ResultType.error,\n error: getInternalRouterError(405, {\n method: request.method,\n pathname: location.pathname,\n routeId: actionMatch.route.id,\n }),\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n }\n\n if (isRedirectResult(result)) {\n let replace: boolean;\n if (opts && opts.replace != null) {\n replace = opts.replace;\n } else {\n // If the user didn't explicity indicate replace behavior, replace if\n // we redirected to the exact same location we're currently at to avoid\n // double back-buttons\n replace =\n result.location === state.location.pathname + state.location.search;\n }\n await startRedirectNavigation(state, result, { submission, replace });\n return { shortCircuited: true };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n\n // By default, all submissions are REPLACE navigations, but if the\n // action threw an error that'll be rendered in an errorElement, we fall\n // back to PUSH so that the user can use the back button to get back to\n // the pre-submission form location to try again\n if ((opts && opts.replace) !== true) {\n pendingAction = HistoryAction.Push;\n }\n\n return {\n // Send back an empty object we can use to clear out any prior actionData\n pendingActionData: {},\n pendingActionError: { [boundaryMatch.route.id]: result.error },\n };\n }\n\n if (isDeferredResult(result)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n return {\n pendingActionData: { [actionMatch.route.id]: result.data },\n };\n }\n\n // Call all applicable loaders for the given matches, handling redirects,\n // errors, etc.\n async function handleLoaders(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n overrideNavigation?: Navigation,\n submission?: Submission,\n fetcherSubmission?: Submission,\n replace?: boolean,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n ): Promise {\n // Figure out the right navigation we want to use for data loading\n let loadingNavigation = overrideNavigation;\n if (!loadingNavigation) {\n let navigation: NavigationStates[\"Loading\"] = {\n state: \"loading\",\n location,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n };\n loadingNavigation = navigation;\n }\n\n // If this was a redirect from an action we don't have a \"submission\" but\n // we have it on the loading navigation so use that if available\n let activeSubmission =\n submission || fetcherSubmission\n ? submission || fetcherSubmission\n : loadingNavigation.formMethod &&\n loadingNavigation.formAction &&\n loadingNavigation.formData &&\n loadingNavigation.formEncType\n ? {\n formMethod: loadingNavigation.formMethod,\n formAction: loadingNavigation.formAction,\n formData: loadingNavigation.formData,\n formEncType: loadingNavigation.formEncType,\n }\n : undefined;\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n activeSubmission,\n location,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n pendingActionData,\n pendingError\n );\n\n // Cancel pending deferreds for no-longer-matched routes or routes we're\n // about to reload. Note that if this is an action reload we would have\n // already cancelled all pending deferreds so this would be a no-op\n cancelActiveDeferreds(\n (routeId) =>\n !(matches && matches.some((m) => m.route.id === routeId)) ||\n (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId))\n );\n\n // Short circuit if we have no loaders to run\n if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {\n completeNavigation(location, {\n matches,\n loaderData: {},\n // Commit pending error if we're short circuiting\n errors: pendingError || null,\n ...(pendingActionData ? { actionData: pendingActionData } : {}),\n });\n return { shortCircuited: true };\n }\n\n // If this is an uninterrupted revalidation, we remain in our current idle\n // state. If not, we need to switch to our loading state and load data,\n // preserving any new action data or existing action data (in the case of\n // a revalidation interrupting an actionReload)\n if (!isUninterruptedRevalidation) {\n revalidatingFetchers.forEach((rf) => {\n let fetcher = state.fetchers.get(rf.key);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: fetcher && fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(rf.key, revalidatingFetcher);\n });\n let actionData = pendingActionData || state.actionData;\n updateState({\n navigation: loadingNavigation,\n ...(actionData\n ? Object.keys(actionData).length === 0\n ? { actionData: null }\n : { actionData }\n : {}),\n ...(revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n });\n }\n\n pendingNavigationLoadId = ++incrementingLoadId;\n revalidatingFetchers.forEach((rf) =>\n fetchControllers.set(rf.key, pendingNavigationController!)\n );\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n request\n );\n\n if (request.signal.aborted) {\n return { shortCircuited: true };\n }\n\n // Clean up _after_ loaders have completed. Don't clean up if we short\n // circuited because fetchControllers would have been aborted and\n // reassigned to new controllers for the next navigation\n revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key));\n\n // If any loaders returned a redirect Response, start a new REPLACE navigation\n let redirect = findRedirect(results);\n if (redirect) {\n await startRedirectNavigation(state, redirect, { replace });\n return { shortCircuited: true };\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n matches,\n matchesToLoad,\n loaderResults,\n pendingError,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n // Wire up subscribers to update loaderData as promises settle\n activeDeferreds.forEach((deferredData, routeId) => {\n deferredData.subscribe((aborted) => {\n // Note: No need to updateState here since the TrackedPromise on\n // loaderData is stable across resolve/reject\n // Remove this instance if we were aborted or if promises have settled\n if (aborted || deferredData.done) {\n activeDeferreds.delete(routeId);\n }\n });\n });\n\n markFetchRedirectsDone();\n let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);\n\n return {\n loaderData,\n errors,\n ...(didAbortFetchLoads || revalidatingFetchers.length > 0\n ? { fetchers: new Map(state.fetchers) }\n : {}),\n };\n }\n\n function getFetcher(key: string): Fetcher {\n return state.fetchers.get(key) || IDLE_FETCHER;\n }\n\n // Trigger a fetcher load/submit for the given fetcher key\n function fetch(\n key: string,\n routeId: string,\n href: string,\n opts?: RouterFetchOptions\n ) {\n if (isServer) {\n throw new Error(\n \"router.fetch() was called during the server render, but it shouldn't be. \" +\n \"You are likely calling a useFetcher() method in the body of your component. \" +\n \"Try moving it to a useEffect or a callback.\"\n );\n }\n\n if (fetchControllers.has(key)) abortFetcher(key);\n\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches = matchRoutes(routesToUse, href, init.basename);\n if (!matches) {\n setFetcherError(\n key,\n routeId,\n getInternalRouterError(404, { pathname: href })\n );\n return;\n }\n\n let { path, submission } = normalizeNavigateOptions(\n href,\n future,\n opts,\n true\n );\n let match = getTargetMatch(matches, path);\n\n pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;\n\n if (submission && isMutationMethod(submission.formMethod)) {\n handleFetcherAction(key, routeId, path, match, matches, submission);\n return;\n }\n\n // Store off the match so we can call it's shouldRevalidate on subsequent\n // revalidations\n fetchLoadMatches.set(key, { routeId, path });\n handleFetcherLoader(key, routeId, path, match, matches, submission);\n }\n\n // Call the action for the matched fetcher.submit(), and then handle redirects,\n // errors, and revalidation\n async function handleFetcherAction(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n requestMatches: AgnosticDataRouteMatch[],\n submission: Submission\n ) {\n interruptActiveLoads();\n fetchLoadMatches.delete(key);\n\n if (!match.route.action && !match.route.lazy) {\n let error = getInternalRouterError(405, {\n method: submission.formMethod,\n pathname: path,\n routeId: routeId,\n });\n setFetcherError(key, routeId, error);\n return;\n }\n\n // Put this fetcher into it's submitting state\n let existingFetcher = state.fetchers.get(key);\n let fetcher: FetcherStates[\"Submitting\"] = {\n state: \"submitting\",\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, fetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the action for the fetcher\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal,\n submission\n );\n fetchControllers.set(key, abortController);\n\n let actionResult = await callLoaderOrAction(\n \"action\",\n fetchRequest,\n match,\n requestMatches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n if (fetchRequest.signal.aborted) {\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-submit which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n return;\n }\n\n if (isRedirectResult(actionResult)) {\n fetchControllers.delete(key);\n fetchRedirectIds.add(key);\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n ...submission,\n data: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n return startRedirectNavigation(state, actionResult, {\n submission,\n isFetchActionRedirect: true,\n });\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(actionResult)) {\n setFetcherError(key, routeId, actionResult.error);\n return;\n }\n\n if (isDeferredResult(actionResult)) {\n throw getInternalRouterError(400, { type: \"defer-action\" });\n }\n\n // Start the data load for current matches, or the next location if we're\n // in the middle of a navigation\n let nextLocation = state.navigation.location || state.location;\n let revalidationRequest = createClientSideRequest(\n init.history,\n\n nextLocation,\n abortController.signal\n );\n let routesToUse = inFlightDataRoutes || dataRoutes;\n let matches =\n state.navigation.state !== \"idle\"\n ? matchRoutes(routesToUse, state.navigation.location, init.basename)\n : state.matches;\n\n invariant(matches, \"Didn't find any matches after fetcher action\");\n\n let loadId = ++incrementingLoadId;\n fetchReloadIds.set(key, loadId);\n\n let loadFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: actionResult.data,\n ...submission,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadFetcher);\n\n let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(\n init.history,\n state,\n matches,\n submission,\n nextLocation,\n isRevalidationRequired,\n cancelledDeferredRoutes,\n cancelledFetcherLoads,\n fetchLoadMatches,\n routesToUse,\n init.basename,\n { [match.route.id]: actionResult.data },\n undefined // No need to send through errors since we short circuit above\n );\n\n // Put all revalidating fetchers into the loading state, except for the\n // current fetcher which we want to keep in it's current loading state which\n // contains it's action submission info + action data\n revalidatingFetchers\n .filter((rf) => rf.key !== key)\n .forEach((rf) => {\n let staleKey = rf.key;\n let existingFetcher = state.fetchers.get(staleKey);\n let revalidatingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n data: existingFetcher && existingFetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(staleKey, revalidatingFetcher);\n fetchControllers.set(staleKey, abortController);\n });\n\n updateState({ fetchers: new Map(state.fetchers) });\n\n let { results, loaderResults, fetcherResults } =\n await callLoadersAndMaybeResolveData(\n state.matches,\n matches,\n matchesToLoad,\n revalidatingFetchers,\n revalidationRequest\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n\n fetchReloadIds.delete(key);\n fetchControllers.delete(key);\n revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key));\n\n let redirect = findRedirect(results);\n if (redirect) {\n return startRedirectNavigation(state, redirect);\n }\n\n // Process and commit output from loaders\n let { loaderData, errors } = processLoaderData(\n state,\n state.matches,\n matchesToLoad,\n loaderResults,\n undefined,\n revalidatingFetchers,\n fetcherResults,\n activeDeferreds\n );\n\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: actionResult.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n\n let didAbortFetchLoads = abortStaleFetchLoads(loadId);\n\n // If we are currently in a navigation loading state and this fetcher is\n // more recent than the navigation, we want the newer data so abort the\n // navigation and complete it with the fetcher data\n if (\n state.navigation.state === \"loading\" &&\n loadId > pendingNavigationLoadId\n ) {\n invariant(pendingAction, \"Expected pending action\");\n pendingNavigationController && pendingNavigationController.abort();\n\n completeNavigation(state.navigation.location, {\n matches,\n loaderData,\n errors,\n fetchers: new Map(state.fetchers),\n });\n } else {\n // otherwise just update with the fetcher data, preserving any existing\n // loaderData for loaders that did not need to reload. We have to\n // manually merge here since we aren't going through completeNavigation\n updateState({\n errors,\n loaderData: mergeLoaderData(\n state.loaderData,\n loaderData,\n matches,\n errors\n ),\n ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}),\n });\n isRevalidationRequired = false;\n }\n }\n\n // Call the matched loader for fetcher.load(), handling redirects, errors, etc.\n async function handleFetcherLoader(\n key: string,\n routeId: string,\n path: string,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n submission?: Submission\n ) {\n let existingFetcher = state.fetchers.get(key);\n // Put this fetcher into it's loading state\n let loadingFetcher: FetcherStates[\"Loading\"] = {\n state: \"loading\",\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n ...submission,\n data: existingFetcher && existingFetcher.data,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, loadingFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n\n // Call the loader for this fetcher route match\n let abortController = new AbortController();\n let fetchRequest = createClientSideRequest(\n init.history,\n path,\n abortController.signal\n );\n fetchControllers.set(key, abortController);\n\n let result: DataResult = await callLoaderOrAction(\n \"loader\",\n fetchRequest,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n\n // Deferred isn't supported for fetcher loads, await everything and treat it\n // as a normal load. resolveDeferredData will return undefined if this\n // fetcher gets aborted, so we just leave result untouched and short circuit\n // below if that happens\n if (isDeferredResult(result)) {\n result =\n (await resolveDeferredData(result, fetchRequest.signal, true)) ||\n result;\n }\n\n // We can delete this so long as we weren't aborted by ou our own fetcher\n // re-load which would have put _new_ controller is in fetchControllers\n if (fetchControllers.get(key) === abortController) {\n fetchControllers.delete(key);\n }\n\n if (fetchRequest.signal.aborted) {\n return;\n }\n\n // If the loader threw a redirect Response, start a new REPLACE navigation\n if (isRedirectResult(result)) {\n await startRedirectNavigation(state, result);\n return;\n }\n\n // Process any non-redirect errors thrown\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n state.fetchers.delete(key);\n // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -\n // do we need to behave any differently with our non-redirect errors?\n // What if it was a non-redirect Response?\n updateState({\n fetchers: new Map(state.fetchers),\n errors: {\n [boundaryMatch.route.id]: result.error,\n },\n });\n return;\n }\n\n invariant(!isDeferredResult(result), \"Unhandled fetcher deferred data\");\n\n // Put the fetcher back into an idle state\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n updateState({ fetchers: new Map(state.fetchers) });\n }\n\n /**\n * Utility function to handle redirects returned from an action or loader.\n * Normally, a redirect \"replaces\" the navigation that triggered it. So, for\n * example:\n *\n * - user is on /a\n * - user clicks a link to /b\n * - loader for /b redirects to /c\n *\n * In a non-JS app the browser would track the in-flight navigation to /b and\n * then replace it with /c when it encountered the redirect response. In\n * the end it would only ever update the URL bar with /c.\n *\n * In client-side routing using pushState/replaceState, we aim to emulate\n * this behavior and we also do not update history until the end of the\n * navigation (including processed redirects). This means that we never\n * actually touch history until we've processed redirects, so we just use\n * the history action from the original navigation (PUSH or REPLACE).\n */\n async function startRedirectNavigation(\n state: RouterState,\n redirect: RedirectResult,\n {\n submission,\n replace,\n isFetchActionRedirect,\n }: {\n submission?: Submission;\n replace?: boolean;\n isFetchActionRedirect?: boolean;\n } = {}\n ) {\n if (redirect.revalidate) {\n isRevalidationRequired = true;\n }\n\n let redirectLocation = createLocation(\n state.location,\n redirect.location,\n // TODO: This can be removed once we get rid of useTransition in Remix v2\n {\n _isRedirect: true,\n ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}),\n }\n );\n invariant(\n redirectLocation,\n \"Expected a location on the redirect navigation\"\n );\n // Check if this an absolute external redirect that goes to a new origin\n if (\n ABSOLUTE_URL_REGEX.test(redirect.location) &&\n isBrowser &&\n typeof window?.location !== \"undefined\"\n ) {\n let url = init.history.createURL(redirect.location);\n let isDifferentBasename =\n stripBasename(url.pathname, init.basename || \"/\") == null;\n\n if (window.location.origin !== url.origin || isDifferentBasename) {\n if (replace) {\n window.location.replace(redirect.location);\n } else {\n window.location.assign(redirect.location);\n }\n return;\n }\n }\n\n // There's no need to abort on redirects, since we don't detect the\n // redirect until the action/loaders have settled\n pendingNavigationController = null;\n\n let redirectHistoryAction =\n replace === true ? HistoryAction.Replace : HistoryAction.Push;\n\n // Use the incoming submission if provided, fallback on the active one in\n // state.navigation\n let { formMethod, formAction, formEncType, formData } = state.navigation;\n if (!submission && formMethod && formAction && formData && formEncType) {\n submission = {\n formMethod,\n formAction,\n formEncType,\n formData,\n };\n }\n\n // If this was a 307/308 submission we want to preserve the HTTP method and\n // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the\n // redirected location\n if (\n redirectPreserveMethodStatusCodes.has(redirect.status) &&\n submission &&\n isMutationMethod(submission.formMethod)\n ) {\n await startNavigation(redirectHistoryAction, redirectLocation, {\n submission: {\n ...submission,\n formAction: redirect.location,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else if (isFetchActionRedirect) {\n // For a fetch action redirect, we kick off a new loading navigation\n // without the fetcher submission, but we send it along for shouldRevalidate\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n },\n fetcherSubmission: submission,\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n } else {\n // Otherwise, we kick off a new loading navigation, preserving the\n // submission info for the duration of this navigation\n await startNavigation(redirectHistoryAction, redirectLocation, {\n overrideNavigation: {\n state: \"loading\",\n location: redirectLocation,\n formMethod: submission ? submission.formMethod : undefined,\n formAction: submission ? submission.formAction : undefined,\n formEncType: submission ? submission.formEncType : undefined,\n formData: submission ? submission.formData : undefined,\n },\n // Preserve this flag across redirects\n preventScrollReset: pendingPreventScrollReset,\n });\n }\n }\n\n async function callLoadersAndMaybeResolveData(\n currentMatches: AgnosticDataRouteMatch[],\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n fetchersToLoad: RevalidatingFetcher[],\n request: Request\n ) {\n // Call all navigation loaders and revalidating fetcher loaders in parallel,\n // then slice off the results into separate arrays so we can handle them\n // accordingly\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n router.basename\n )\n ),\n ...fetchersToLoad.map((f) => {\n if (f.matches && f.match) {\n return callLoaderOrAction(\n \"loader\",\n createClientSideRequest(init.history, f.path, request.signal),\n f.match,\n f.matches,\n manifest,\n detectErrorBoundary,\n router.basename\n );\n } else {\n let error: ErrorResult = {\n type: ResultType.error,\n error: getInternalRouterError(404, { pathname: f.path }),\n };\n return error;\n }\n }),\n ]);\n let loaderResults = results.slice(0, matchesToLoad.length);\n let fetcherResults = results.slice(matchesToLoad.length);\n\n await Promise.all([\n resolveDeferredResults(\n currentMatches,\n matchesToLoad,\n loaderResults,\n request.signal,\n false,\n state.loaderData\n ),\n resolveDeferredResults(\n currentMatches,\n fetchersToLoad.map((f) => f.match),\n fetcherResults,\n request.signal,\n true\n ),\n ]);\n\n return { results, loaderResults, fetcherResults };\n }\n\n function interruptActiveLoads() {\n // Every interruption triggers a revalidation\n isRevalidationRequired = true;\n\n // Cancel pending route-level deferreds and mark cancelled routes for\n // revalidation\n cancelledDeferredRoutes.push(...cancelActiveDeferreds());\n\n // Abort in-flight fetcher loads\n fetchLoadMatches.forEach((_, key) => {\n if (fetchControllers.has(key)) {\n cancelledFetcherLoads.push(key);\n abortFetcher(key);\n }\n });\n }\n\n function setFetcherError(key: string, routeId: string, error: any) {\n let boundaryMatch = findNearestBoundary(state.matches, routeId);\n deleteFetcher(key);\n updateState({\n errors: {\n [boundaryMatch.route.id]: error,\n },\n fetchers: new Map(state.fetchers),\n });\n }\n\n function deleteFetcher(key: string): void {\n if (fetchControllers.has(key)) abortFetcher(key);\n fetchLoadMatches.delete(key);\n fetchReloadIds.delete(key);\n fetchRedirectIds.delete(key);\n state.fetchers.delete(key);\n }\n\n function abortFetcher(key: string) {\n let controller = fetchControllers.get(key);\n invariant(controller, `Expected fetch controller: ${key}`);\n controller.abort();\n fetchControllers.delete(key);\n }\n\n function markFetchersDone(keys: string[]) {\n for (let key of keys) {\n let fetcher = getFetcher(key);\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: fetcher.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n function markFetchRedirectsDone(): void {\n let doneKeys = [];\n for (let key of fetchRedirectIds) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n fetchRedirectIds.delete(key);\n doneKeys.push(key);\n }\n }\n markFetchersDone(doneKeys);\n }\n\n function abortStaleFetchLoads(landedId: number): boolean {\n let yeetedKeys = [];\n for (let [key, id] of fetchReloadIds) {\n if (id < landedId) {\n let fetcher = state.fetchers.get(key);\n invariant(fetcher, `Expected fetcher: ${key}`);\n if (fetcher.state === \"loading\") {\n abortFetcher(key);\n fetchReloadIds.delete(key);\n yeetedKeys.push(key);\n }\n }\n }\n markFetchersDone(yeetedKeys);\n return yeetedKeys.length > 0;\n }\n\n function getBlocker(key: string, fn: BlockerFunction) {\n let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n if (blockerFunctions.get(key) !== fn) {\n blockerFunctions.set(key, fn);\n }\n\n return blocker;\n }\n\n function deleteBlocker(key: string) {\n state.blockers.delete(key);\n blockerFunctions.delete(key);\n }\n\n // Utility function to update blockers, ensuring valid state transitions\n function updateBlocker(key: string, newBlocker: Blocker) {\n let blocker = state.blockers.get(key) || IDLE_BLOCKER;\n\n // Poor mans state machine :)\n // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM\n invariant(\n (blocker.state === \"unblocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"blocked\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"proceeding\") ||\n (blocker.state === \"blocked\" && newBlocker.state === \"unblocked\") ||\n (blocker.state === \"proceeding\" && newBlocker.state === \"unblocked\"),\n `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}`\n );\n\n state.blockers.set(key, newBlocker);\n updateState({ blockers: new Map(state.blockers) });\n }\n\n function shouldBlockNavigation({\n currentLocation,\n nextLocation,\n historyAction,\n }: {\n currentLocation: Location;\n nextLocation: Location;\n historyAction: HistoryAction;\n }): string | undefined {\n if (blockerFunctions.size === 0) {\n return;\n }\n\n // We ony support a single active blocker at the moment since we don't have\n // any compelling use cases for multi-blocker yet\n if (blockerFunctions.size > 1) {\n warning(false, \"A router only supports one blocker at a time\");\n }\n\n let entries = Array.from(blockerFunctions.entries());\n let [blockerKey, blockerFunction] = entries[entries.length - 1];\n let blocker = state.blockers.get(blockerKey);\n\n if (blocker && blocker.state === \"proceeding\") {\n // If the blocker is currently proceeding, we don't need to re-check\n // it and can let this navigation continue\n return;\n }\n\n // At this point, we know we're unblocked/blocked so we need to check the\n // user-provided blocker function\n if (blockerFunction({ currentLocation, nextLocation, historyAction })) {\n return blockerKey;\n }\n }\n\n function cancelActiveDeferreds(\n predicate?: (routeId: string) => boolean\n ): string[] {\n let cancelledRouteIds: string[] = [];\n activeDeferreds.forEach((dfd, routeId) => {\n if (!predicate || predicate(routeId)) {\n // Cancel the deferred - but do not remove from activeDeferreds here -\n // we rely on the subscribers to do that so our tests can assert proper\n // cleanup via _internalActiveDeferreds\n dfd.cancel();\n cancelledRouteIds.push(routeId);\n activeDeferreds.delete(routeId);\n }\n });\n return cancelledRouteIds;\n }\n\n // Opt in to capturing and reporting scroll positions during navigations,\n // used by the component\n function enableScrollRestoration(\n positions: Record,\n getPosition: GetScrollPositionFunction,\n getKey?: GetScrollRestorationKeyFunction\n ) {\n savedScrollPositions = positions;\n getScrollPosition = getPosition;\n getScrollRestorationKey = getKey || ((location) => location.key);\n\n // Perform initial hydration scroll restoration, since we miss the boat on\n // the initial updateState() because we've not yet rendered \n // and therefore have no savedScrollPositions available\n if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {\n initialScrollRestored = true;\n let y = getSavedScrollPosition(state.location, state.matches);\n if (y != null) {\n updateState({ restoreScrollPosition: y });\n }\n }\n\n return () => {\n savedScrollPositions = null;\n getScrollPosition = null;\n getScrollRestorationKey = null;\n };\n }\n\n function saveScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): void {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n savedScrollPositions[key] = getScrollPosition();\n }\n }\n\n function getSavedScrollPosition(\n location: Location,\n matches: AgnosticDataRouteMatch[]\n ): number | null {\n if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {\n let userMatches = matches.map((m) =>\n createUseMatchesMatch(m, state.loaderData)\n );\n let key = getScrollRestorationKey(location, userMatches) || location.key;\n let y = savedScrollPositions[key];\n if (typeof y === \"number\") {\n return y;\n }\n }\n return null;\n }\n\n function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) {\n inFlightDataRoutes = newRoutes;\n }\n\n router = {\n get basename() {\n return init.basename;\n },\n get state() {\n return state;\n },\n get routes() {\n return dataRoutes;\n },\n initialize,\n subscribe,\n enableScrollRestoration,\n navigate,\n fetch,\n revalidate,\n // Passthrough to history-aware createHref used by useHref so we get proper\n // hash-aware URLs in DOM paths\n createHref: (to: To) => init.history.createHref(to),\n encodeLocation: (to: To) => init.history.encodeLocation(to),\n getFetcher,\n deleteFetcher,\n dispose,\n getBlocker,\n deleteBlocker,\n _internalFetchControllers: fetchControllers,\n _internalActiveDeferreds: activeDeferreds,\n // TODO: Remove setRoutes, it's temporary to avoid dealing with\n // updating the tree while validating the update algorithm.\n _internalSetRoutes,\n };\n\n return router;\n}\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region createStaticHandler\n////////////////////////////////////////////////////////////////////////////////\n\nexport const UNSAFE_DEFERRED_SYMBOL = Symbol(\"deferred\");\n\nexport interface CreateStaticHandlerOptions {\n basename?: string;\n detectErrorBoundary?: DetectErrorBoundaryFunction;\n}\n\nexport function createStaticHandler(\n routes: AgnosticRouteObject[],\n opts?: CreateStaticHandlerOptions\n): StaticHandler {\n invariant(\n routes.length > 0,\n \"You must provide a non-empty routes array to createStaticHandler\"\n );\n\n let manifest: RouteManifest = {};\n let detectErrorBoundary =\n opts?.detectErrorBoundary || defaultDetectErrorBoundary;\n let dataRoutes = convertRoutesToDataRoutes(\n routes,\n detectErrorBoundary,\n undefined,\n manifest\n );\n let basename = (opts ? opts.basename : null) || \"/\";\n\n /**\n * The query() method is intended for document requests, in which we want to\n * call an optional action and potentially multiple loaders for all nested\n * routes. It returns a StaticHandlerContext object, which is very similar\n * to the router state (location, loaderData, actionData, errors, etc.) and\n * also adds SSR-specific information such as the statusCode and headers\n * from action/loaders Responses.\n *\n * It _should_ never throw and should report all errors through the\n * returned context.errors object, properly associating errors to their error\n * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be\n * used to emulate React error boundaries during SSr by performing a second\n * pass only down to the boundaryId.\n *\n * The one exception where we do not return a StaticHandlerContext is when a\n * redirect response is returned or thrown from any action/loader. We\n * propagate that out and return the raw Response so the HTTP server can\n * return it directly.\n */\n async function query(\n request: Request,\n { requestContext }: { requestContext?: unknown } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\") {\n let error = getInternalRouterError(405, { method });\n let { matches: methodNotAllowedMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: methodNotAllowedMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n } else if (!matches) {\n let error = getInternalRouterError(404, { pathname: location.pathname });\n let { matches: notFoundMatches, route } =\n getShortCircuitMatches(dataRoutes);\n return {\n basename,\n location,\n matches: notFoundMatches,\n loaderData: {},\n actionData: null,\n errors: {\n [route.id]: error,\n },\n statusCode: error.status,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let result = await queryImpl(request, location, matches, requestContext);\n if (isResponse(result)) {\n return result;\n }\n\n // When returning StaticHandlerContext, we patch back in the location here\n // since we need it for React Context. But this helps keep our submit and\n // loadRouteData operating on a Request instead of a Location\n return { location, basename, ...result };\n }\n\n /**\n * The queryRoute() method is intended for targeted route requests, either\n * for fetch ?_data requests or resource route requests. In this case, we\n * are only ever calling a single action or loader, and we are returning the\n * returned value directly. In most cases, this will be a Response returned\n * from the action/loader, but it may be a primitive or other value as well -\n * and in such cases the calling context should handle that accordingly.\n *\n * We do respect the throw/return differentiation, so if an action/loader\n * throws, then this method will throw the value. This is important so we\n * can do proper boundary identification in Remix where a thrown Response\n * must go to the Catch Boundary but a returned Response is happy-path.\n *\n * One thing to note is that any Router-initiated Errors that make sense\n * to associate with a status code will be thrown as an ErrorResponse\n * instance which include the raw Error, such that the calling context can\n * serialize the error as they see fit while including the proper response\n * code. Examples here are 404 and 405 errors that occur prior to reaching\n * any user-defined loaders.\n */\n async function queryRoute(\n request: Request,\n {\n routeId,\n requestContext,\n }: { requestContext?: unknown; routeId?: string } = {}\n ): Promise {\n let url = new URL(request.url);\n let method = request.method;\n let location = createLocation(\"\", createPath(url), null, \"default\");\n let matches = matchRoutes(dataRoutes, location, basename);\n\n // SSR supports HEAD requests while SPA doesn't\n if (!isValidMethod(method) && method !== \"HEAD\" && method !== \"OPTIONS\") {\n throw getInternalRouterError(405, { method });\n } else if (!matches) {\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let match = routeId\n ? matches.find((m) => m.route.id === routeId)\n : getTargetMatch(matches, location);\n\n if (routeId && !match) {\n throw getInternalRouterError(403, {\n pathname: location.pathname,\n routeId,\n });\n } else if (!match) {\n // This should never hit I don't think?\n throw getInternalRouterError(404, { pathname: location.pathname });\n }\n\n let result = await queryImpl(\n request,\n location,\n matches,\n requestContext,\n match\n );\n if (isResponse(result)) {\n return result;\n }\n\n let error = result.errors ? Object.values(result.errors)[0] : undefined;\n if (error !== undefined) {\n // If we got back result.errors, that means the loader/action threw\n // _something_ that wasn't a Response, but it's not guaranteed/required\n // to be an `instanceof Error` either, so we have to use throw here to\n // preserve the \"error\" state outside of queryImpl.\n throw error;\n }\n\n // Pick off the right state value to return\n if (result.actionData) {\n return Object.values(result.actionData)[0];\n }\n\n if (result.loaderData) {\n let data = Object.values(result.loaderData)[0];\n if (result.activeDeferreds?.[match.route.id]) {\n data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];\n }\n return data;\n }\n\n return undefined;\n }\n\n async function queryImpl(\n request: Request,\n location: Location,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch\n ): Promise | Response> {\n invariant(\n request.signal,\n \"query()/queryRoute() requests must contain an AbortController signal\"\n );\n\n try {\n if (isMutationMethod(request.method.toLowerCase())) {\n let result = await submit(\n request,\n matches,\n routeMatch || getTargetMatch(matches, location),\n requestContext,\n routeMatch != null\n );\n return result;\n }\n\n let result = await loadRouteData(\n request,\n matches,\n requestContext,\n routeMatch\n );\n return isResponse(result)\n ? result\n : {\n ...result,\n actionData: null,\n actionHeaders: {},\n };\n } catch (e) {\n // If the user threw/returned a Response in callLoaderOrAction, we throw\n // it to bail out and then return or throw here based on whether the user\n // returned or threw\n if (isQueryRouteResponse(e)) {\n if (e.type === ResultType.error && !isRedirectResponse(e.response)) {\n throw e.response;\n }\n return e.response;\n }\n // Redirects are always returned since they don't propagate to catch\n // boundaries\n if (isRedirectResponse(e)) {\n return e;\n }\n throw e;\n }\n }\n\n async function submit(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n actionMatch: AgnosticDataRouteMatch,\n requestContext: unknown,\n isRouteRequest: boolean\n ): Promise | Response> {\n let result: DataResult;\n\n if (!actionMatch.route.action && !actionMatch.route.lazy) {\n let error = getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: actionMatch.route.id,\n });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n } else {\n result = await callLoaderOrAction(\n \"action\",\n request,\n actionMatch,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n );\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n }\n\n if (isRedirectResult(result)) {\n // Uhhhh - this should never happen, we should always throw these from\n // callLoaderOrAction, but the type narrowing here keeps TS happy and we\n // can get back on the \"throw all redirect responses\" train here should\n // this ever happen :/\n throw new Response(null, {\n status: result.status,\n headers: {\n Location: result.location,\n },\n });\n }\n\n if (isDeferredResult(result)) {\n let error = getInternalRouterError(400, { type: \"defer-action\" });\n if (isRouteRequest) {\n throw error;\n }\n result = {\n type: ResultType.error,\n error,\n };\n }\n\n if (isRouteRequest) {\n // Note: This should only be non-Response values if we get here, since\n // isRouteRequest should throw any Response received in callLoaderOrAction\n if (isErrorResult(result)) {\n throw result.error;\n }\n\n return {\n matches: [actionMatch],\n loaderData: {},\n actionData: { [actionMatch.route.id]: result.data },\n errors: null,\n // Note: statusCode + headers are unused here since queryRoute will\n // return the raw Response or value\n statusCode: 200,\n loaderHeaders: {},\n actionHeaders: {},\n activeDeferreds: null,\n };\n }\n\n if (isErrorResult(result)) {\n // Store off the pending error - we use it to determine which loaders\n // to call and will commit it when we complete the navigation\n let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);\n let context = await loadRouteData(\n request,\n matches,\n requestContext,\n undefined,\n {\n [boundaryMatch.route.id]: result.error,\n }\n );\n\n // action status codes take precedence over loader status codes\n return {\n ...context,\n statusCode: isRouteErrorResponse(result.error)\n ? result.error.status\n : 500,\n actionData: null,\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n // Create a GET request for the loaders\n let loaderRequest = new Request(request.url, {\n headers: request.headers,\n redirect: request.redirect,\n signal: request.signal,\n });\n let context = await loadRouteData(loaderRequest, matches, requestContext);\n\n return {\n ...context,\n // action status codes take precedence over loader status codes\n ...(result.statusCode ? { statusCode: result.statusCode } : {}),\n actionData: {\n [actionMatch.route.id]: result.data,\n },\n actionHeaders: {\n ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}),\n },\n };\n }\n\n async function loadRouteData(\n request: Request,\n matches: AgnosticDataRouteMatch[],\n requestContext: unknown,\n routeMatch?: AgnosticDataRouteMatch,\n pendingActionError?: RouteData\n ): Promise<\n | Omit<\n StaticHandlerContext,\n \"location\" | \"basename\" | \"actionData\" | \"actionHeaders\"\n >\n | Response\n > {\n let isRouteRequest = routeMatch != null;\n\n // Short circuit if we have no loaders to run (queryRoute())\n if (\n isRouteRequest &&\n !routeMatch?.route.loader &&\n !routeMatch?.route.lazy\n ) {\n throw getInternalRouterError(400, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: routeMatch?.route.id,\n });\n }\n\n let requestMatches = routeMatch\n ? [routeMatch]\n : getLoaderMatchesUntilBoundary(\n matches,\n Object.keys(pendingActionError || {})[0]\n );\n let matchesToLoad = requestMatches.filter(\n (m) => m.route.loader || m.route.lazy\n );\n\n // Short circuit if we have no loaders to run (query())\n if (matchesToLoad.length === 0) {\n return {\n matches,\n // Add a null for all matched routes for proper revalidation on the client\n loaderData: matches.reduce(\n (acc, m) => Object.assign(acc, { [m.route.id]: null }),\n {}\n ),\n errors: pendingActionError || null,\n statusCode: 200,\n loaderHeaders: {},\n activeDeferreds: null,\n };\n }\n\n let results = await Promise.all([\n ...matchesToLoad.map((match) =>\n callLoaderOrAction(\n \"loader\",\n request,\n match,\n matches,\n manifest,\n detectErrorBoundary,\n basename,\n true,\n isRouteRequest,\n requestContext\n )\n ),\n ]);\n\n if (request.signal.aborted) {\n let method = isRouteRequest ? \"queryRoute\" : \"query\";\n throw new Error(`${method}() call aborted`);\n }\n\n // Process and commit output from loaders\n let activeDeferreds = new Map();\n let context = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingActionError,\n activeDeferreds\n );\n\n // Add a null for any non-loader matches for proper revalidation on the client\n let executedLoaders = new Set(\n matchesToLoad.map((match) => match.route.id)\n );\n matches.forEach((match) => {\n if (!executedLoaders.has(match.route.id)) {\n context.loaderData[match.route.id] = null;\n }\n });\n\n return {\n ...context,\n matches,\n activeDeferreds:\n activeDeferreds.size > 0\n ? Object.fromEntries(activeDeferreds.entries())\n : null,\n };\n }\n\n return {\n dataRoutes,\n query,\n queryRoute,\n };\n}\n\n//#endregion\n\n////////////////////////////////////////////////////////////////////////////////\n//#region Helpers\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Given an existing StaticHandlerContext and an error thrown at render time,\n * provide an updated StaticHandlerContext suitable for a second SSR render\n */\nexport function getStaticContextFromError(\n routes: AgnosticDataRouteObject[],\n context: StaticHandlerContext,\n error: any\n) {\n let newContext: StaticHandlerContext = {\n ...context,\n statusCode: 500,\n errors: {\n [context._deepestRenderedBoundaryId || routes[0].id]: error,\n },\n };\n return newContext;\n}\n\nfunction isSubmissionNavigation(\n opts: RouterNavigateOptions\n): opts is SubmissionNavigateOptions {\n return opts != null && \"formData\" in opts;\n}\n\n// Normalize navigation options by converting formMethod=GET formData objects to\n// URLSearchParams so they behave identically to links with query params\nfunction normalizeNavigateOptions(\n to: To,\n future: FutureConfig,\n opts?: RouterNavigateOptions,\n isFetcher = false\n): {\n path: string;\n submission?: Submission;\n error?: ErrorResponse;\n} {\n let path = typeof to === \"string\" ? to : createPath(to);\n\n // Return location verbatim on non-submission navigations\n if (!opts || !isSubmissionNavigation(opts)) {\n return { path };\n }\n\n if (opts.formMethod && !isValidMethod(opts.formMethod)) {\n return {\n path,\n error: getInternalRouterError(405, { method: opts.formMethod }),\n };\n }\n\n // Create a Submission on non-GET navigations\n let submission: Submission | undefined;\n if (opts.formData) {\n let formMethod = opts.formMethod || \"get\";\n submission = {\n formMethod: future.v7_normalizeFormMethod\n ? (formMethod.toUpperCase() as V7_FormMethod)\n : (formMethod.toLowerCase() as FormMethod),\n formAction: stripHashFromPath(path),\n formEncType:\n (opts && opts.formEncType) || \"application/x-www-form-urlencoded\",\n formData: opts.formData,\n };\n\n if (isMutationMethod(submission.formMethod)) {\n return { path, submission };\n }\n }\n\n // Flatten submission onto URLSearchParams for GET submissions\n let parsedPath = parsePath(path);\n let searchParams = convertFormDataToSearchParams(opts.formData);\n // Since fetcher GET submissions only run a single loader (as opposed to\n // navigation GET submissions which run all loaders), we need to preserve\n // any incoming ?index params\n if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {\n searchParams.append(\"index\", \"\");\n }\n parsedPath.search = `?${searchParams}`;\n\n return { path: createPath(parsedPath), submission };\n}\n\n// Filter out all routes below any caught error as they aren't going to\n// render so we don't need to load them\nfunction getLoaderMatchesUntilBoundary(\n matches: AgnosticDataRouteMatch[],\n boundaryId?: string\n) {\n let boundaryMatches = matches;\n if (boundaryId) {\n let index = matches.findIndex((m) => m.route.id === boundaryId);\n if (index >= 0) {\n boundaryMatches = matches.slice(0, index);\n }\n }\n return boundaryMatches;\n}\n\nfunction getMatchesToLoad(\n history: History,\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n submission: Submission | undefined,\n location: Location,\n isRevalidationRequired: boolean,\n cancelledDeferredRoutes: string[],\n cancelledFetcherLoads: string[],\n fetchLoadMatches: Map,\n routesToUse: AgnosticDataRouteObject[],\n basename: string | undefined,\n pendingActionData?: RouteData,\n pendingError?: RouteData\n): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] {\n let actionResult = pendingError\n ? Object.values(pendingError)[0]\n : pendingActionData\n ? Object.values(pendingActionData)[0]\n : undefined;\n\n let currentUrl = history.createURL(state.location);\n let nextUrl = history.createURL(location);\n\n let defaultShouldRevalidate =\n // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate\n isRevalidationRequired ||\n // Clicked the same link, resubmitted a GET form\n currentUrl.toString() === nextUrl.toString() ||\n // Search params affect all loaders\n currentUrl.search !== nextUrl.search;\n\n // Pick navigation matches that are net-new or qualify for revalidation\n let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;\n let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);\n\n let navigationMatches = boundaryMatches.filter((match, index) => {\n if (match.route.lazy) {\n // We haven't loaded this route yet so we don't know if it's got a loader!\n return true;\n }\n if (match.route.loader == null) {\n return false;\n }\n\n // Always call the loader on new route instances and pending defer cancellations\n if (\n isNewLoader(state.loaderData, state.matches[index], match) ||\n cancelledDeferredRoutes.some((id) => id === match.route.id)\n ) {\n return true;\n }\n\n // This is the default implementation for when we revalidate. If the route\n // provides it's own implementation, then we give them full control but\n // provide this value so they can leverage it if needed after they check\n // their own specific use cases\n let currentRouteMatch = state.matches[index];\n let nextRouteMatch = match;\n\n return shouldRevalidateLoader(match, {\n currentUrl,\n currentParams: currentRouteMatch.params,\n nextUrl,\n nextParams: nextRouteMatch.params,\n ...submission,\n actionResult,\n defaultShouldRevalidate:\n defaultShouldRevalidate ||\n isNewRouteInstance(currentRouteMatch, nextRouteMatch),\n });\n });\n\n // Pick fetcher.loads that need to be revalidated\n let revalidatingFetchers: RevalidatingFetcher[] = [];\n fetchLoadMatches.forEach((f, key) => {\n // Don't revalidate if fetcher won't be present in the subsequent render\n if (!matches.some((m) => m.route.id === f.routeId)) {\n return;\n }\n\n let fetcherMatches = matchRoutes(routesToUse, f.path, basename);\n\n // If the fetcher path no longer matches, push it in with null matches so\n // we can trigger a 404 in callLoadersAndMaybeResolveData\n if (!fetcherMatches) {\n revalidatingFetchers.push({ key, ...f, matches: null, match: null });\n return;\n }\n\n let fetcherMatch = getTargetMatch(fetcherMatches, f.path);\n\n if (cancelledFetcherLoads.includes(key)) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n return;\n }\n\n // Revalidating fetchers are decoupled from the route matches since they\n // hit a static href, so they _always_ check shouldRevalidate and the\n // default is strictly if a revalidation is explicitly required (action\n // submissions, useRevalidator, X-Remix-Revalidate).\n let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, {\n currentUrl,\n currentParams: state.matches[state.matches.length - 1].params,\n nextUrl,\n nextParams: matches[matches.length - 1].params,\n ...submission,\n actionResult,\n defaultShouldRevalidate,\n });\n if (shouldRevalidate) {\n revalidatingFetchers.push({\n key,\n matches: fetcherMatches,\n match: fetcherMatch,\n ...f,\n });\n }\n });\n\n return [navigationMatches, revalidatingFetchers];\n}\n\nfunction isNewLoader(\n currentLoaderData: RouteData,\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let isNew =\n // [a] -> [a, b]\n !currentMatch ||\n // [a, b] -> [a, c]\n match.route.id !== currentMatch.route.id;\n\n // Handle the case that we don't have data for a re-used route, potentially\n // from a prior error or from a cancelled pending deferred\n let isMissingData = currentLoaderData[match.route.id] === undefined;\n\n // Always load if this is a net-new route or we don't yet have data\n return isNew || isMissingData;\n}\n\nfunction isNewRouteInstance(\n currentMatch: AgnosticDataRouteMatch,\n match: AgnosticDataRouteMatch\n) {\n let currentPath = currentMatch.route.path;\n return (\n // param change for this match, /users/123 -> /users/456\n currentMatch.pathname !== match.pathname ||\n // splat param changed, which is not present in match.path\n // e.g. /files/images/avatar.jpg -> files/finances.xls\n (currentPath != null &&\n currentPath.endsWith(\"*\") &&\n currentMatch.params[\"*\"] !== match.params[\"*\"])\n );\n}\n\nfunction shouldRevalidateLoader(\n loaderMatch: AgnosticDataRouteMatch,\n arg: Parameters[0]\n) {\n if (loaderMatch.route.shouldRevalidate) {\n let routeChoice = loaderMatch.route.shouldRevalidate(arg);\n if (typeof routeChoice === \"boolean\") {\n return routeChoice;\n }\n }\n\n return arg.defaultShouldRevalidate;\n}\n\n/**\n * Execute route.lazy() methods to lazily load route modules (loader, action,\n * shouldRevalidate) and update the routeManifest in place which shares objects\n * with dataRoutes so those get updated as well.\n */\nasync function loadLazyRouteModule(\n route: AgnosticDataRouteObject,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n manifest: RouteManifest\n) {\n if (!route.lazy) {\n return;\n }\n\n let lazyRoute = await route.lazy();\n\n // If the lazy route function was executed and removed by another parallel\n // call then we can return - first lazy() to finish wins because the return\n // value of lazy is expected to be static\n if (!route.lazy) {\n return;\n }\n\n let routeToUpdate = manifest[route.id];\n invariant(routeToUpdate, \"No route found in manifest\");\n\n // Update the route in place. This should be safe because there's no way\n // we could yet be sitting on this route as we can't get there without\n // resolving lazy() first.\n //\n // This is different than the HMR \"update\" use-case where we may actively be\n // on the route being updated. The main concern boils down to \"does this\n // mutation affect any ongoing navigations or any current state.matches\n // values?\". If not, it should be safe to update in place.\n let routeUpdates: Record = {};\n for (let lazyRouteProperty in lazyRoute) {\n let staticRouteValue =\n routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate];\n\n let isPropertyStaticallyDefined =\n staticRouteValue !== undefined &&\n // This property isn't static since it should always be updated based\n // on the route updates\n lazyRouteProperty !== \"hasErrorBoundary\";\n\n warning(\n !isPropertyStaticallyDefined,\n `Route \"${routeToUpdate.id}\" has a static property \"${lazyRouteProperty}\" ` +\n `defined but its lazy function is also returning a value for this property. ` +\n `The lazy route property \"${lazyRouteProperty}\" will be ignored.`\n );\n\n if (\n !isPropertyStaticallyDefined &&\n !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey)\n ) {\n routeUpdates[lazyRouteProperty] =\n lazyRoute[lazyRouteProperty as keyof typeof lazyRoute];\n }\n }\n\n // Mutate the route with the provided updates. Do this first so we pass\n // the updated version to detectErrorBoundary\n Object.assign(routeToUpdate, routeUpdates);\n\n // Mutate the `hasErrorBoundary` property on the route based on the route\n // updates and remove the `lazy` function so we don't resolve the lazy\n // route again.\n Object.assign(routeToUpdate, {\n // To keep things framework agnostic, we use the provided\n // `detectErrorBoundary` function to set the `hasErrorBoundary` route\n // property since the logic will differ between frameworks.\n hasErrorBoundary: detectErrorBoundary({ ...routeToUpdate }),\n lazy: undefined,\n });\n}\n\nasync function callLoaderOrAction(\n type: \"loader\" | \"action\",\n request: Request,\n match: AgnosticDataRouteMatch,\n matches: AgnosticDataRouteMatch[],\n manifest: RouteManifest,\n detectErrorBoundary: DetectErrorBoundaryFunction,\n basename = \"/\",\n isStaticRequest: boolean = false,\n isRouteRequest: boolean = false,\n requestContext?: unknown\n): Promise {\n let resultType;\n let result;\n let onReject: (() => void) | undefined;\n\n let runHandler = (handler: ActionFunction | LoaderFunction) => {\n // Setup a promise we can race against so that abort signals short circuit\n let reject: () => void;\n let abortPromise = new Promise((_, r) => (reject = r));\n onReject = () => reject();\n request.signal.addEventListener(\"abort\", onReject);\n return Promise.race([\n handler({ request, params: match.params, context: requestContext }),\n abortPromise,\n ]);\n };\n\n try {\n let handler = match.route[type];\n\n if (match.route.lazy) {\n if (handler) {\n // Run statically defined handler in parallel with lazy()\n let values = await Promise.all([\n runHandler(handler),\n loadLazyRouteModule(match.route, detectErrorBoundary, manifest),\n ]);\n result = values[0];\n } else {\n // Load lazy route module, then run any returned handler\n await loadLazyRouteModule(match.route, detectErrorBoundary, manifest);\n\n handler = match.route[type];\n if (handler) {\n // Handler still run even if we got interrupted to maintain consistency\n // with un-abortable behavior of handler execution on non-lazy or\n // previously-lazy-loaded routes\n result = await runHandler(handler);\n } else if (type === \"action\") {\n throw getInternalRouterError(405, {\n method: request.method,\n pathname: new URL(request.url).pathname,\n routeId: match.route.id,\n });\n } else {\n // lazy() route has no loader to run. Short circuit here so we don't\n // hit the invariant below that errors on returning undefined.\n return { type: ResultType.data, data: undefined };\n }\n }\n } else {\n invariant(\n handler,\n `Could not find the ${type} to run on the \"${match.route.id}\" route`\n );\n\n result = await runHandler(handler);\n }\n\n invariant(\n result !== undefined,\n `You defined ${type === \"action\" ? \"an action\" : \"a loader\"} for route ` +\n `\"${match.route.id}\" but didn't return anything from your \\`${type}\\` ` +\n `function. Please return a value or \\`null\\`.`\n );\n } catch (e) {\n resultType = ResultType.error;\n result = e;\n } finally {\n if (onReject) {\n request.signal.removeEventListener(\"abort\", onReject);\n }\n }\n\n if (isResponse(result)) {\n let status = result.status;\n\n // Process redirects\n if (redirectStatusCodes.has(status)) {\n let location = result.headers.get(\"Location\");\n invariant(\n location,\n \"Redirects returned/thrown from loaders/actions must have a Location header\"\n );\n\n // Support relative routing in internal redirects\n if (!ABSOLUTE_URL_REGEX.test(location)) {\n let activeMatches = matches.slice(0, matches.indexOf(match) + 1);\n let routePathnames = getPathContributingMatches(activeMatches).map(\n (match) => match.pathnameBase\n );\n let resolvedLocation = resolveTo(\n location,\n routePathnames,\n new URL(request.url).pathname\n );\n invariant(\n createPath(resolvedLocation),\n `Unable to resolve redirect location: ${location}`\n );\n\n // Prepend the basename to the redirect location if we have one\n if (basename) {\n let path = resolvedLocation.pathname;\n resolvedLocation.pathname =\n path === \"/\" ? basename : joinPaths([basename, path]);\n }\n\n location = createPath(resolvedLocation);\n } else if (!isStaticRequest) {\n // Strip off the protocol+origin for same-origin + same-basename absolute\n // redirects. If this is a static request, we can let it go back to the\n // browser as-is\n let currentUrl = new URL(request.url);\n let url = location.startsWith(\"//\")\n ? new URL(currentUrl.protocol + location)\n : new URL(location);\n let isSameBasename = stripBasename(url.pathname, basename) != null;\n if (url.origin === currentUrl.origin && isSameBasename) {\n location = url.pathname + url.search + url.hash;\n }\n }\n\n // Don't process redirects in the router during static requests requests.\n // Instead, throw the Response and let the server handle it with an HTTP\n // redirect. We also update the Location header in place in this flow so\n // basename and relative routing is taken into account\n if (isStaticRequest) {\n result.headers.set(\"Location\", location);\n throw result;\n }\n\n return {\n type: ResultType.redirect,\n status,\n location,\n revalidate: result.headers.get(\"X-Remix-Revalidate\") !== null,\n };\n }\n\n // For SSR single-route requests, we want to hand Responses back directly\n // without unwrapping. We do this with the QueryRouteResponse wrapper\n // interface so we can know whether it was returned or thrown\n if (isRouteRequest) {\n // eslint-disable-next-line no-throw-literal\n throw {\n type: resultType || ResultType.data,\n response: result,\n };\n }\n\n let data: any;\n let contentType = result.headers.get(\"Content-Type\");\n // Check between word boundaries instead of startsWith() due to the last\n // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type\n if (contentType && /\\bapplication\\/json\\b/.test(contentType)) {\n data = await result.json();\n } else {\n data = await result.text();\n }\n\n if (resultType === ResultType.error) {\n return {\n type: resultType,\n error: new ErrorResponse(status, result.statusText, data),\n headers: result.headers,\n };\n }\n\n return {\n type: ResultType.data,\n data,\n statusCode: result.status,\n headers: result.headers,\n };\n }\n\n if (resultType === ResultType.error) {\n return { type: resultType, error: result };\n }\n\n if (isDeferredData(result)) {\n return {\n type: ResultType.deferred,\n deferredData: result,\n statusCode: result.init?.status,\n headers: result.init?.headers && new Headers(result.init.headers),\n };\n }\n\n return { type: ResultType.data, data: result };\n}\n\n// Utility method for creating the Request instances for loaders/actions during\n// client-side navigations and fetches. During SSR we will always have a\n// Request instance from the static handler (query/queryRoute)\nfunction createClientSideRequest(\n history: History,\n location: string | Location,\n signal: AbortSignal,\n submission?: Submission\n): Request {\n let url = history.createURL(stripHashFromPath(location)).toString();\n let init: RequestInit = { signal };\n\n if (submission && isMutationMethod(submission.formMethod)) {\n let { formMethod, formEncType, formData } = submission;\n // Didn't think we needed this but it turns out unlike other methods, patch\n // won't be properly normalized to uppercase and results in a 405 error.\n // See: https://fetch.spec.whatwg.org/#concept-method\n init.method = formMethod.toUpperCase();\n init.body =\n formEncType === \"application/x-www-form-urlencoded\"\n ? convertFormDataToSearchParams(formData)\n : formData;\n }\n\n // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)\n return new Request(url, init);\n}\n\nfunction convertFormDataToSearchParams(formData: FormData): URLSearchParams {\n let searchParams = new URLSearchParams();\n\n for (let [key, value] of formData.entries()) {\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n searchParams.append(key, value instanceof File ? value.name : value);\n }\n\n return searchParams;\n}\n\nfunction processRouteLoaderData(\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors: RouterState[\"errors\"] | null;\n statusCode: number;\n loaderHeaders: Record;\n} {\n // Fill in loaderData/errors from our loaders\n let loaderData: RouterState[\"loaderData\"] = {};\n let errors: RouterState[\"errors\"] | null = null;\n let statusCode: number | undefined;\n let foundError = false;\n let loaderHeaders: Record = {};\n\n // Process loader results into state.loaderData/state.errors\n results.forEach((result, index) => {\n let id = matchesToLoad[index].route.id;\n invariant(\n !isRedirectResult(result),\n \"Cannot handle redirect results in processLoaderData\"\n );\n if (isErrorResult(result)) {\n // Look upwards from the matched route for the closest ancestor\n // error boundary, defaulting to the root match\n let boundaryMatch = findNearestBoundary(matches, id);\n let error = result.error;\n // If we have a pending action error, we report it at the highest-route\n // that throws a loader error, and then clear it out to indicate that\n // it was consumed\n if (pendingError) {\n error = Object.values(pendingError)[0];\n pendingError = undefined;\n }\n\n errors = errors || {};\n\n // Prefer higher error values if lower errors bubble to the same boundary\n if (errors[boundaryMatch.route.id] == null) {\n errors[boundaryMatch.route.id] = error;\n }\n\n // Clear our any prior loaderData for the throwing route\n loaderData[id] = undefined;\n\n // Once we find our first (highest) error, we set the status code and\n // prevent deeper status codes from overriding\n if (!foundError) {\n foundError = true;\n statusCode = isRouteErrorResponse(result.error)\n ? result.error.status\n : 500;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n } else {\n if (isDeferredResult(result)) {\n activeDeferreds.set(id, result.deferredData);\n loaderData[id] = result.deferredData.data;\n } else {\n loaderData[id] = result.data;\n }\n\n // Error status codes always override success status codes, but if all\n // loaders are successful we take the deepest status code.\n if (\n result.statusCode != null &&\n result.statusCode !== 200 &&\n !foundError\n ) {\n statusCode = result.statusCode;\n }\n if (result.headers) {\n loaderHeaders[id] = result.headers;\n }\n }\n });\n\n // If we didn't consume the pending action error (i.e., all loaders\n // resolved), then consume it here. Also clear out any loaderData for the\n // throwing route\n if (pendingError) {\n errors = pendingError;\n loaderData[Object.keys(pendingError)[0]] = undefined;\n }\n\n return {\n loaderData,\n errors,\n statusCode: statusCode || 200,\n loaderHeaders,\n };\n}\n\nfunction processLoaderData(\n state: RouterState,\n matches: AgnosticDataRouteMatch[],\n matchesToLoad: AgnosticDataRouteMatch[],\n results: DataResult[],\n pendingError: RouteData | undefined,\n revalidatingFetchers: RevalidatingFetcher[],\n fetcherResults: DataResult[],\n activeDeferreds: Map\n): {\n loaderData: RouterState[\"loaderData\"];\n errors?: RouterState[\"errors\"];\n} {\n let { loaderData, errors } = processRouteLoaderData(\n matches,\n matchesToLoad,\n results,\n pendingError,\n activeDeferreds\n );\n\n // Process results from our revalidating fetchers\n for (let index = 0; index < revalidatingFetchers.length; index++) {\n let { key, match } = revalidatingFetchers[index];\n invariant(\n fetcherResults !== undefined && fetcherResults[index] !== undefined,\n \"Did not find corresponding fetcher result\"\n );\n let result = fetcherResults[index];\n\n // Process fetcher non-redirect errors\n if (isErrorResult(result)) {\n let boundaryMatch = findNearestBoundary(state.matches, match?.route.id);\n if (!(errors && errors[boundaryMatch.route.id])) {\n errors = {\n ...errors,\n [boundaryMatch.route.id]: result.error,\n };\n }\n state.fetchers.delete(key);\n } else if (isRedirectResult(result)) {\n // Should never get here, redirects should get processed above, but we\n // keep this to type narrow to a success result in the else\n invariant(false, \"Unhandled fetcher revalidation redirect\");\n } else if (isDeferredResult(result)) {\n // Should never get here, deferred data should be awaited for fetchers\n // in resolveDeferredResults\n invariant(false, \"Unhandled fetcher deferred data\");\n } else {\n let doneFetcher: FetcherStates[\"Idle\"] = {\n state: \"idle\",\n data: result.data,\n formMethod: undefined,\n formAction: undefined,\n formEncType: undefined,\n formData: undefined,\n \" _hasFetcherDoneAnything \": true,\n };\n state.fetchers.set(key, doneFetcher);\n }\n }\n\n return { loaderData, errors };\n}\n\nfunction mergeLoaderData(\n loaderData: RouteData,\n newLoaderData: RouteData,\n matches: AgnosticDataRouteMatch[],\n errors: RouteData | null | undefined\n): RouteData {\n let mergedLoaderData = { ...newLoaderData };\n for (let match of matches) {\n let id = match.route.id;\n if (newLoaderData.hasOwnProperty(id)) {\n if (newLoaderData[id] !== undefined) {\n mergedLoaderData[id] = newLoaderData[id];\n } else {\n // No-op - this is so we ignore existing data if we have a key in the\n // incoming object with an undefined value, which is how we unset a prior\n // loaderData if we encounter a loader error\n }\n } else if (loaderData[id] !== undefined && match.route.loader) {\n // Preserve existing keys not included in newLoaderData and where a loader\n // wasn't removed by HMR\n mergedLoaderData[id] = loaderData[id];\n }\n\n if (errors && errors.hasOwnProperty(id)) {\n // Don't keep any loader data below the boundary\n break;\n }\n }\n return mergedLoaderData;\n}\n\n// Find the nearest error boundary, looking upwards from the leaf route (or the\n// route specified by routeId) for the closest ancestor error boundary,\n// defaulting to the root match\nfunction findNearestBoundary(\n matches: AgnosticDataRouteMatch[],\n routeId?: string\n): AgnosticDataRouteMatch {\n let eligibleMatches = routeId\n ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1)\n : [...matches];\n return (\n eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) ||\n matches[0]\n );\n}\n\nfunction getShortCircuitMatches(routes: AgnosticDataRouteObject[]): {\n matches: AgnosticDataRouteMatch[];\n route: AgnosticDataRouteObject;\n} {\n // Prefer a root layout route if present, otherwise shim in a route object\n let route = routes.find((r) => r.index || !r.path || r.path === \"/\") || {\n id: `__shim-error-route__`,\n };\n\n return {\n matches: [\n {\n params: {},\n pathname: \"\",\n pathnameBase: \"\",\n route,\n },\n ],\n route,\n };\n}\n\nfunction getInternalRouterError(\n status: number,\n {\n pathname,\n routeId,\n method,\n type,\n }: {\n pathname?: string;\n routeId?: string;\n method?: string;\n type?: \"defer-action\";\n } = {}\n) {\n let statusText = \"Unknown Server Error\";\n let errorMessage = \"Unknown @remix-run/router error\";\n\n if (status === 400) {\n statusText = \"Bad Request\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method} request to \"${pathname}\" but ` +\n `did not provide a \\`loader\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (type === \"defer-action\") {\n errorMessage = \"defer() is not supported in actions\";\n }\n } else if (status === 403) {\n statusText = \"Forbidden\";\n errorMessage = `Route \"${routeId}\" does not match URL \"${pathname}\"`;\n } else if (status === 404) {\n statusText = \"Not Found\";\n errorMessage = `No route matches URL \"${pathname}\"`;\n } else if (status === 405) {\n statusText = \"Method Not Allowed\";\n if (method && pathname && routeId) {\n errorMessage =\n `You made a ${method.toUpperCase()} request to \"${pathname}\" but ` +\n `did not provide an \\`action\\` for route \"${routeId}\", ` +\n `so there is no way to handle the request.`;\n } else if (method) {\n errorMessage = `Invalid request method \"${method.toUpperCase()}\"`;\n }\n }\n\n return new ErrorResponse(\n status || 500,\n statusText,\n new Error(errorMessage),\n true\n );\n}\n\n// Find any returned redirect errors, starting from the lowest match\nfunction findRedirect(results: DataResult[]): RedirectResult | undefined {\n for (let i = results.length - 1; i >= 0; i--) {\n let result = results[i];\n if (isRedirectResult(result)) {\n return result;\n }\n }\n}\n\nfunction stripHashFromPath(path: To) {\n let parsedPath = typeof path === \"string\" ? parsePath(path) : path;\n return createPath({ ...parsedPath, hash: \"\" });\n}\n\nfunction isHashChangeOnly(a: Location, b: Location): boolean {\n return (\n a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash\n );\n}\n\nfunction isDeferredResult(result: DataResult): result is DeferredResult {\n return result.type === ResultType.deferred;\n}\n\nfunction isErrorResult(result: DataResult): result is ErrorResult {\n return result.type === ResultType.error;\n}\n\nfunction isRedirectResult(result?: DataResult): result is RedirectResult {\n return (result && result.type) === ResultType.redirect;\n}\n\nexport function isDeferredData(value: any): value is DeferredData {\n let deferred: DeferredData = value;\n return (\n deferred &&\n typeof deferred === \"object\" &&\n typeof deferred.data === \"object\" &&\n typeof deferred.subscribe === \"function\" &&\n typeof deferred.cancel === \"function\" &&\n typeof deferred.resolveData === \"function\"\n );\n}\n\nfunction isResponse(value: any): value is Response {\n return (\n value != null &&\n typeof value.status === \"number\" &&\n typeof value.statusText === \"string\" &&\n typeof value.headers === \"object\" &&\n typeof value.body !== \"undefined\"\n );\n}\n\nfunction isRedirectResponse(result: any): result is Response {\n if (!isResponse(result)) {\n return false;\n }\n\n let status = result.status;\n let location = result.headers.get(\"Location\");\n return status >= 300 && status <= 399 && location != null;\n}\n\nfunction isQueryRouteResponse(obj: any): obj is QueryRouteResponse {\n return (\n obj &&\n isResponse(obj.response) &&\n (obj.type === ResultType.data || ResultType.error)\n );\n}\n\nfunction isValidMethod(method: string): method is FormMethod | V7_FormMethod {\n return validRequestMethods.has(method.toLowerCase() as FormMethod);\n}\n\nfunction isMutationMethod(\n method: string\n): method is MutationFormMethod | V7_MutationFormMethod {\n return validMutationMethods.has(method.toLowerCase() as MutationFormMethod);\n}\n\nasync function resolveDeferredResults(\n currentMatches: AgnosticDataRouteMatch[],\n matchesToLoad: (AgnosticDataRouteMatch | null)[],\n results: DataResult[],\n signal: AbortSignal,\n isFetcher: boolean,\n currentLoaderData?: RouteData\n) {\n for (let index = 0; index < results.length; index++) {\n let result = results[index];\n let match = matchesToLoad[index];\n // If we don't have a match, then we can have a deferred result to do\n // anything with. This is for revalidating fetchers where the route was\n // removed during HMR\n if (!match) {\n continue;\n }\n\n let currentMatch = currentMatches.find(\n (m) => m.route.id === match!.route.id\n );\n let isRevalidatingLoader =\n currentMatch != null &&\n !isNewRouteInstance(currentMatch, match) &&\n (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;\n\n if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {\n // Note: we do not have to touch activeDeferreds here since we race them\n // against the signal in resolveDeferredData and they'll get aborted\n // there if needed\n await resolveDeferredData(result, signal, isFetcher).then((result) => {\n if (result) {\n results[index] = result || results[index];\n }\n });\n }\n }\n}\n\nasync function resolveDeferredData(\n result: DeferredResult,\n signal: AbortSignal,\n unwrap = false\n): Promise {\n let aborted = await result.deferredData.resolveData(signal);\n if (aborted) {\n return;\n }\n\n if (unwrap) {\n try {\n return {\n type: ResultType.data,\n data: result.deferredData.unwrappedData,\n };\n } catch (e) {\n // Handle any TrackedPromise._error values encountered while unwrapping\n return {\n type: ResultType.error,\n error: e,\n };\n }\n }\n\n return {\n type: ResultType.data,\n data: result.deferredData.data,\n };\n}\n\nfunction hasNakedIndexQuery(search: string): boolean {\n return new URLSearchParams(search).getAll(\"index\").some((v) => v === \"\");\n}\n\n// Note: This should match the format exported by useMatches, so if you change\n// this please also change that :) Eventually we'll DRY this up\nfunction createUseMatchesMatch(\n match: AgnosticDataRouteMatch,\n loaderData: RouteData\n): UseMatchesMatch {\n let { route, pathname, params } = match;\n return {\n id: route.id,\n pathname,\n params,\n data: loaderData[route.id] as unknown,\n handle: route.handle as unknown,\n };\n}\n\nfunction getTargetMatch(\n matches: AgnosticDataRouteMatch[],\n location: Location | string\n) {\n let search =\n typeof location === \"string\" ? parsePath(location).search : location.search;\n if (\n matches[matches.length - 1].route.index &&\n hasNakedIndexQuery(search || \"\")\n ) {\n // Return the leaf index route when index is present\n return matches[matches.length - 1];\n }\n // Otherwise grab the deepest \"path contributing\" match (ignoring index and\n // pathless layout routes)\n let pathMatches = getPathContributingMatches(matches);\n return pathMatches[pathMatches.length - 1];\n}\n//#endregion\n"],"names":["Action","exports","PopStateEventType","invariant","value","message","Error","warning","cond","console","warn","e","getHistoryState","location","index","usr","state","key","idx","createLocation","current","to","_extends","pathname","search","hash","parsePath","Math","random","toString","substr","createPath","_ref","charAt","path","parsedPath","hashIndex","indexOf","searchIndex","getUrlBasedHistory","getLocation","createHref","validateLocation","options","window","document","defaultView","v5Compat","globalHistory","history","action","Pop","listener","getIndex","handlePop","nextIndex","delta","createURL","base","origin","href","URL","replaceState","listen","fn","addEventListener","removeEventListener","encodeLocation","url","push","Push","historyState","pushState","error","assign","replace","Replace","go","n","ResultType","immutableRouteKeys","Set","convertRoutesToDataRoutes","routes","detectErrorBoundary","parentPath","manifest","map","route","treePath","id","join","children","isIndexRoute","indexRoute","hasErrorBoundary","pathOrLayoutRoute","undefined","matchRoutes","locationArg","basename","stripBasename","branches","flattenRoutes","sort","a","b","score","length","slice","every","i","compareIndexes","routesMeta","meta","childrenIndex","rankRouteBranches","matches","matchRouteBranch","safelyDecodeURI","parentsMeta","flattenRoute","relativePath","caseSensitive","startsWith","joinPaths","concat","computeScore","forEach","_route$path","includes","exploded","explodeOptionalSegments","segments","split","first","rest","isOptional","endsWith","required","restExploded","result","subpath","paramRe","isSplat","s","initialScore","some","filter","reduce","segment","test","branch","matchedParams","matchedPathname","end","remainingPathname","match","matchPath","Object","params","pathnameBase","normalizePathname","pattern","matcher","paramNames","regexpSource","_","paramName","RegExp","compilePath","captureGroups","memo","splatValue","decodeURIComponent","safelyDecodeURIComponent","decodeURI","toLowerCase","startIndex","nextChar","resolvePath","fromPathname","toPathname","pop","resolvePathname","normalizeSearch","normalizeHash","getInvalidPathError","char","field","dest","JSON","stringify","getPathContributingMatches","resolveTo","toArg","routePathnames","locationPathname","isPathRelative","from","isEmptyPath","routePathnameIndex","toSegments","shift","hasExplicitTrailingSlash","hasCurrentTrailingSlash","paths","AbortedDeferredError","DeferredData","constructor","data","responseInit","reject","this","pendingKeysSet","subscribers","deferredKeys","Array","isArray","abortPromise","Promise","r","controller","AbortController","onAbort","unlistenAbortSignal","signal","entries","acc","trackPromise","done","init","add","promise","race","then","onSettle","catch","defineProperty","get","aborted","delete","emit","settledKey","subscriber","subscribe","cancel","abort","v","k","async","resolve","size","unwrappedData","_ref2","unwrapTrackedPromise","pendingKeys","_tracked","isTrackedPromise","_error","_data","ErrorResponse","status","statusText","internal","isRouteErrorResponse","validMutationMethodsArr","validMutationMethods","validRequestMethodsArr","validRequestMethods","redirectStatusCodes","redirectPreserveMethodStatusCodes","IDLE_NAVIGATION","formMethod","formAction","formEncType","formData","IDLE_FETCHER","IDLE_BLOCKER","proceed","reset","ABSOLUTE_URL_REGEX","isBrowser","createElement","isServer","defaultDetectErrorBoundary","Boolean","UNSAFE_DEFERRED_SYMBOL","Symbol","normalizeNavigateOptions","future","opts","isFetcher","submission","isSubmissionNavigation","isValidMethod","getInternalRouterError","method","v7_normalizeFormMethod","toUpperCase","stripHashFromPath","isMutationMethod","searchParams","convertFormDataToSearchParams","hasNakedIndexQuery","append","getLoaderMatchesUntilBoundary","boundaryId","boundaryMatches","findIndex","m","getMatchesToLoad","isRevalidationRequired","cancelledDeferredRoutes","cancelledFetcherLoads","fetchLoadMatches","routesToUse","pendingActionData","pendingError","actionResult","values","currentUrl","nextUrl","defaultShouldRevalidate","keys","navigationMatches","lazy","loader","currentLoaderData","currentMatch","isNew","isMissingData","isNewLoader","loaderData","currentRouteMatch","nextRouteMatch","shouldRevalidateLoader","currentParams","nextParams","isNewRouteInstance","revalidatingFetchers","f","routeId","fetcherMatches","fetcherMatch","getTargetMatch","currentPath","loaderMatch","arg","shouldRevalidate","routeChoice","loadLazyRouteModule","lazyRoute","routeToUpdate","routeUpdates","lazyRouteProperty","isPropertyStaticallyDefined","has","callLoaderOrAction","type","request","isStaticRequest","isRouteRequest","requestContext","resultType","onReject","runHandler","handler","context","all","isResponse","headers","protocol","isSameBasename","resolvedLocation","set","redirect","revalidate","response","contentType","json","text","statusCode","isDeferredData","deferred","deferredData","_result$init","_result$init2","Headers","createClientSideRequest","body","Request","URLSearchParams","File","name","processRouteLoaderData","matchesToLoad","results","activeDeferreds","errors","foundError","loaderHeaders","isRedirectResult","isErrorResult","boundaryMatch","findNearestBoundary","isDeferredResult","processLoaderData","fetcherResults","fetchers","doneFetcher","mergeLoaderData","newLoaderData","mergedLoaderData","hasOwnProperty","reverse","find","getShortCircuitMatches","_temp4","errorMessage","findRedirect","resolveData","isRedirectResponse","resolveDeferredResults","currentMatches","isRevalidatingLoader","resolveDeferredData","unwrap","getAll","createUseMatchesMatch","handle","pathMatches","querySelector","getAttribute","initialEntries","initialIndex","entry","createMemoryLocation","clampIndex","min","max","getCurrentLocation","nextLocation","splice","inFlightDataRoutes","dataRoutes","unlistenHistory","savedScrollPositions","getScrollRestorationKey","getScrollPosition","initialScrollRestored","hydrationData","initialMatches","initialErrors","router","pendingNavigationController","initialized","historyAction","navigation","restoreScrollPosition","preventScrollReset","revalidation","actionData","Map","blockers","pendingAction","HistoryAction","pendingPreventScrollReset","isUninterruptedRevalidation","fetchControllers","incrementingLoadId","pendingNavigationLoadId","fetchReloadIds","fetchRedirectIds","blockerFunctions","ignoreNextHistoryUpdate","updateState","newState","completeNavigation","_location$state","_location$state2","isActionReload","_isRedirect","deleteBlocker","getSavedScrollPosition","startNavigation","startUninterruptedRevalidation","userMatches","saveScrollPosition","loadingNavigation","overrideNavigation","notFoundMatches","cancelActiveDeferreds","actionOutput","interruptActiveLoads","actionMatch","shortCircuited","startRedirectNavigation","pendingActionError","handleAction","fetcherSubmission","activeSubmission","rf","fetcher","revalidatingFetcher","loaderResults","callLoadersAndMaybeResolveData","doneKeys","markFetchersDone","markFetchRedirectsDone","didAbortFetchLoads","abortStaleFetchLoads","handleLoaders","getFetcher","_temp","_window","isFetchActionRedirect","redirectLocation","_isFetchActionRedirect","isDifferentBasename","redirectHistoryAction","fetchersToLoad","abortFetcher","setFetcherError","deleteFetcher","landedId","yeetedKeys","updateBlocker","newBlocker","blocker","shouldBlockNavigation","currentLocation","blockerKey","blockerFunction","predicate","cancelledRouteIds","dfd","y","initialize","enableScrollRestoration","positions","getPosition","getKey","navigate","userReplace","fetch","requestMatches","existingFetcher","abortController","fetchRequest","loadingFetcher","revalidationRequest","loadId","loadFetcher","staleKey","handleFetcherAction","handleFetcherLoader","dispose","clear","getBlocker","_internalFetchControllers","_internalActiveDeferreds","_internalSetRoutes","newRoutes","queryImpl","routeMatch","Response","Location","actionHeaders","loadRouteData","loaderRequest","submit","obj","executedLoaders","fromEntries","query","_temp2","methodNotAllowedMatches","queryRoute","_temp3","_result$activeDeferre","originalPath","array","keyMatch","optional","param","_deepestRenderedBoundaryId"],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@remix-run/router/dist/utils.d.ts b/node_modules/@remix-run/router/dist/utils.d.ts new file mode 100644 index 00000000..5fd3af32 --- /dev/null +++ b/node_modules/@remix-run/router/dist/utils.d.ts @@ -0,0 +1,425 @@ +import type { Location, Path, To } from "./history"; +/** + * Map of routeId -> data returned from a loader/action/error + */ +export interface RouteData { + [routeId: string]: any; +} +export declare enum ResultType { + data = "data", + deferred = "deferred", + redirect = "redirect", + error = "error" +} +/** + * Successful result from a loader or action + */ +export interface SuccessResult { + type: ResultType.data; + data: any; + statusCode?: number; + headers?: Headers; +} +/** + * Successful defer() result from a loader or action + */ +export interface DeferredResult { + type: ResultType.deferred; + deferredData: DeferredData; + statusCode?: number; + headers?: Headers; +} +/** + * Redirect result from a loader or action + */ +export interface RedirectResult { + type: ResultType.redirect; + status: number; + location: string; + revalidate: boolean; +} +/** + * Unsuccessful result from a loader or action + */ +export interface ErrorResult { + type: ResultType.error; + error: any; + headers?: Headers; +} +/** + * Result from a loader or action - potentially successful or unsuccessful + */ +export declare type DataResult = SuccessResult | DeferredResult | RedirectResult | ErrorResult; +declare type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete"; +declare type UpperCaseFormMethod = Uppercase; +/** + * Users can specify either lowercase or uppercase form methods on , + * useSubmit(), , etc. + */ +export declare type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod; +/** + * Active navigation/fetcher form methods are exposed in lowercase on the + * RouterState + */ +export declare type FormMethod = LowerCaseFormMethod; +export declare type MutationFormMethod = Exclude; +/** + * In v7, active navigation/fetcher form methods are exposed in uppercase on the + * RouterState. This is to align with the normalization done via fetch(). + */ +export declare type V7_FormMethod = UpperCaseFormMethod; +export declare type V7_MutationFormMethod = Exclude; +export declare type FormEncType = "application/x-www-form-urlencoded" | "multipart/form-data"; +/** + * @private + * Internal interface to pass around for action submissions, not intended for + * external consumption + */ +export interface Submission { + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; +} +/** + * @private + * Arguments passed to route loader/action functions. Same for now but we keep + * this as a private implementation detail in case they diverge in the future. + */ +interface DataFunctionArgs { + request: Request; + params: Params; + context?: any; +} +/** + * Arguments passed to loader functions + */ +export interface LoaderFunctionArgs extends DataFunctionArgs { +} +/** + * Arguments passed to action functions + */ +export interface ActionFunctionArgs extends DataFunctionArgs { +} +/** + * Route loader function signature + */ +export interface LoaderFunction { + (args: LoaderFunctionArgs): Promise | Response | Promise | any; +} +/** + * Route action function signature + */ +export interface ActionFunction { + (args: ActionFunctionArgs): Promise | Response | Promise | any; +} +/** + * Route shouldRevalidate function signature. This runs after any submission + * (navigation or fetcher), so we flatten the navigation/fetcher submission + * onto the arguments. It shouldn't matter whether it came from a navigation + * or a fetcher, what really matters is the URLs and the formData since loaders + * have to re-run based on the data models that were potentially mutated. + */ +export interface ShouldRevalidateFunction { + (args: { + currentUrl: URL; + currentParams: AgnosticDataRouteMatch["params"]; + nextUrl: URL; + nextParams: AgnosticDataRouteMatch["params"]; + formMethod?: Submission["formMethod"]; + formAction?: Submission["formAction"]; + formEncType?: Submission["formEncType"]; + formData?: Submission["formData"]; + actionResult?: DataResult; + defaultShouldRevalidate: boolean; + }): boolean; +} +/** + * Function provided by the framework-aware layers to set `hasErrorBoundary` + * from the framework-aware `errorElement` prop + */ +export interface DetectErrorBoundaryFunction { + (route: AgnosticRouteObject): boolean; +} +/** + * Keys we cannot change from within a lazy() function. We spread all other keys + * onto the route. Either they're meaningful to the router, or they'll get + * ignored. + */ +export declare type ImmutableRouteKey = "lazy" | "caseSensitive" | "path" | "id" | "index" | "children"; +export declare const immutableRouteKeys: Set; +/** + * lazy() function to load a route definition, which can add non-matching + * related properties to a route + */ +export interface LazyRouteFunction { + (): Promise>; +} +/** + * Base RouteObject with common props shared by all types of routes + */ +declare type AgnosticBaseRouteObject = { + caseSensitive?: boolean; + path?: string; + id?: string; + loader?: LoaderFunction; + action?: ActionFunction; + hasErrorBoundary?: boolean; + shouldRevalidate?: ShouldRevalidateFunction; + handle?: any; + lazy?: LazyRouteFunction; +}; +/** + * Index routes must not have children + */ +export declare type AgnosticIndexRouteObject = AgnosticBaseRouteObject & { + children?: undefined; + index: true; +}; +/** + * Non-index routes may have children, but cannot have index + */ +export declare type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & { + children?: AgnosticRouteObject[]; + index?: false; +}; +/** + * A route object represents a logical route, with (optionally) its child + * routes organized in a tree-like structure. + */ +export declare type AgnosticRouteObject = AgnosticIndexRouteObject | AgnosticNonIndexRouteObject; +export declare type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & { + id: string; +}; +export declare type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & { + children?: AgnosticDataRouteObject[]; + id: string; +}; +/** + * A data route object, which is just a RouteObject with a required unique ID + */ +export declare type AgnosticDataRouteObject = AgnosticDataIndexRouteObject | AgnosticDataNonIndexRouteObject; +export declare type RouteManifest = Record; +declare type _PathParam = Path extends `${infer L}/${infer R}` ? _PathParam | _PathParam : Path extends `:${infer Param}` ? Param extends `${infer Optional}?` ? Optional : Param : never; +/** + * Examples: + * "/a/b/*" -> "*" + * ":a" -> "a" + * "/a/:b" -> "b" + * "/a/blahblahblah:b" -> "b" + * "/:a/:b" -> "a" | "b" + * "/:a/b/:c/*" -> "a" | "c" | "*" + */ +declare type PathParam = Path extends "*" | "/*" ? "*" : Path extends `${infer Rest}/*` ? "*" | _PathParam : _PathParam; +export declare type ParamParseKey = [ + PathParam +] extends [never] ? string : PathParam; +/** + * The parameters that were parsed from the URL path. + */ +export declare type Params = { + readonly [key in Key]: string | undefined; +}; +/** + * A RouteMatch contains info about how a route matched a URL. + */ +export interface AgnosticRouteMatch { + /** + * The names and values of dynamic parameters in the URL. + */ + params: Params; + /** + * The portion of the URL pathname that was matched. + */ + pathname: string; + /** + * The portion of the URL pathname that was matched before child routes. + */ + pathnameBase: string; + /** + * The route object that was used to match. + */ + route: RouteObjectType; +} +export interface AgnosticDataRouteMatch extends AgnosticRouteMatch { +} +export declare function convertRoutesToDataRoutes(routes: AgnosticRouteObject[], detectErrorBoundary: DetectErrorBoundaryFunction, parentPath?: number[], manifest?: RouteManifest): AgnosticDataRouteObject[]; +/** + * Matches the given routes to a location and returns the match data. + * + * @see https://reactrouter.com/utils/match-routes + */ +export declare function matchRoutes(routes: RouteObjectType[], locationArg: Partial | string, basename?: string): AgnosticRouteMatch[] | null; +/** + * Returns a path with params interpolated. + * + * @see https://reactrouter.com/utils/generate-path + */ +export declare function generatePath(originalPath: Path, params?: { + [key in PathParam]: string | null; +}): string; +/** + * A PathPattern is used to match on some portion of a URL pathname. + */ +export interface PathPattern { + /** + * A string to match against a URL pathname. May contain `:id`-style segments + * to indicate placeholders for dynamic parameters. May also end with `/*` to + * indicate matching the rest of the URL pathname. + */ + path: Path; + /** + * Should be `true` if the static portions of the `path` should be matched in + * the same case. + */ + caseSensitive?: boolean; + /** + * Should be `true` if this pattern should match the entire URL pathname. + */ + end?: boolean; +} +/** + * A PathMatch contains info about how a PathPattern matched on a URL pathname. + */ +export interface PathMatch { + /** + * The names and values of dynamic parameters in the URL. + */ + params: Params; + /** + * The portion of the URL pathname that was matched. + */ + pathname: string; + /** + * The portion of the URL pathname that was matched before child routes. + */ + pathnameBase: string; + /** + * The pattern that was used to match. + */ + pattern: PathPattern; +} +/** + * Performs pattern matching on a URL pathname and returns information about + * the match. + * + * @see https://reactrouter.com/utils/match-path + */ +export declare function matchPath, Path extends string>(pattern: PathPattern | Path, pathname: string): PathMatch | null; +/** + * @private + */ +export declare function stripBasename(pathname: string, basename: string): string | null; +/** + * Returns a resolved path object relative to the given pathname. + * + * @see https://reactrouter.com/utils/resolve-path + */ +export declare function resolvePath(to: To, fromPathname?: string): Path; +/** + * @private + * + * When processing relative navigation we want to ignore ancestor routes that + * do not contribute to the path, such that index/pathless layout routes don't + * interfere. + * + * For example, when moving a route element into an index route and/or a + * pathless layout route, relative link behavior contained within should stay + * the same. Both of the following examples should link back to the root: + * + * + * + * + * + * + * + * }> // <-- Does not contribute + * // <-- Does not contribute + * + * + */ +export declare function getPathContributingMatches(matches: T[]): T[]; +/** + * @private + */ +export declare function resolveTo(toArg: To, routePathnames: string[], locationPathname: string, isPathRelative?: boolean): Path; +/** + * @private + */ +export declare function getToPathname(to: To): string | undefined; +/** + * @private + */ +export declare const joinPaths: (paths: string[]) => string; +/** + * @private + */ +export declare const normalizePathname: (pathname: string) => string; +/** + * @private + */ +export declare const normalizeSearch: (search: string) => string; +/** + * @private + */ +export declare const normalizeHash: (hash: string) => string; +export declare type JsonFunction = (data: Data, init?: number | ResponseInit) => Response; +/** + * This is a shortcut for creating `application/json` responses. Converts `data` + * to JSON and sets the `Content-Type` header. + */ +export declare const json: JsonFunction; +export interface TrackedPromise extends Promise { + _tracked?: boolean; + _data?: any; + _error?: any; +} +export declare class AbortedDeferredError extends Error { +} +export declare class DeferredData { + private pendingKeysSet; + private controller; + private abortPromise; + private unlistenAbortSignal; + private subscribers; + data: Record; + init?: ResponseInit; + deferredKeys: string[]; + constructor(data: Record, responseInit?: ResponseInit); + private trackPromise; + private onSettle; + private emit; + subscribe(fn: (aborted: boolean, settledKey?: string) => void): () => boolean; + cancel(): void; + resolveData(signal: AbortSignal): Promise; + get done(): boolean; + get unwrappedData(): {}; + get pendingKeys(): string[]; +} +export declare type DeferFunction = (data: Record, init?: number | ResponseInit) => DeferredData; +export declare const defer: DeferFunction; +export declare type RedirectFunction = (url: string, init?: number | ResponseInit) => Response; +/** + * A redirect response. Sets the status code and the `Location` header. + * Defaults to "302 Found". + */ +export declare const redirect: RedirectFunction; +/** + * @private + * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies + */ +export declare class ErrorResponse { + status: number; + statusText: string; + data: any; + error?: Error; + internal: boolean; + constructor(status: number, statusText: string | undefined, data: any, internal?: boolean); +} +/** + * Check if the given error is an ErrorResponse generated from a 4xx/5xx + * Response thrown from an action/loader + */ +export declare function isRouteErrorResponse(error: any): error is ErrorResponse; +export {}; diff --git a/node_modules/@remix-run/router/history.ts b/node_modules/@remix-run/router/history.ts new file mode 100644 index 00000000..9b5a01b3 --- /dev/null +++ b/node_modules/@remix-run/router/history.ts @@ -0,0 +1,721 @@ +//////////////////////////////////////////////////////////////////////////////// +//#region Types and Constants +//////////////////////////////////////////////////////////////////////////////// + +/** + * Actions represent the type of change to a location value. + */ +export enum Action { + /** + * A POP indicates a change to an arbitrary index in the history stack, such + * as a back or forward navigation. It does not describe the direction of the + * navigation, only that the current index changed. + * + * Note: This is the default action for newly created history objects. + */ + Pop = "POP", + + /** + * A PUSH indicates a new entry being added to the history stack, such as when + * a link is clicked and a new page loads. When this happens, all subsequent + * entries in the stack are lost. + */ + Push = "PUSH", + + /** + * A REPLACE indicates the entry at the current index in the history stack + * being replaced by a new one. + */ + Replace = "REPLACE", +} + +/** + * The pathname, search, and hash values of a URL. + */ +export interface Path { + /** + * A URL pathname, beginning with a /. + */ + pathname: string; + + /** + * A URL search string, beginning with a ?. + */ + search: string; + + /** + * A URL fragment identifier, beginning with a #. + */ + hash: string; +} + +/** + * An entry in a history stack. A location contains information about the + * URL path, as well as possibly some arbitrary state and a key. + */ +export interface Location extends Path { + /** + * A value of arbitrary data associated with this location. + */ + state: any; + + /** + * A unique string associated with this location. May be used to safely store + * and retrieve data in some other storage API, like `localStorage`. + * + * Note: This value is always "default" on the initial location. + */ + key: string; +} + +/** + * A change to the current location. + */ +export interface Update { + /** + * The action that triggered the change. + */ + action: Action; + + /** + * The new location. + */ + location: Location; + + /** + * The delta between this location and the former location in the history stack + */ + delta: number | null; +} + +/** + * A function that receives notifications about location changes. + */ +export interface Listener { + (update: Update): void; +} + +/** + * Describes a location that is the destination of some navigation, either via + * `history.push` or `history.replace`. May be either a URL or the pieces of a + * URL path. + */ +export type To = string | Partial; + +/** + * A history is an interface to the navigation stack. The history serves as the + * source of truth for the current location, as well as provides a set of + * methods that may be used to change it. + * + * It is similar to the DOM's `window.history` object, but with a smaller, more + * focused API. + */ +export interface History { + /** + * The last action that modified the current location. This will always be + * Action.Pop when a history instance is first created. This value is mutable. + */ + readonly action: Action; + + /** + * The current location. This value is mutable. + */ + readonly location: Location; + + /** + * Returns a valid href for the given `to` value that may be used as + * the value of an attribute. + * + * @param to - The destination URL + */ + createHref(to: To): string; + + /** + * Returns a URL for the given `to` value + * + * @param to - The destination URL + */ + createURL(to: To): URL; + + /** + * Encode a location the same way window.history would do (no-op for memory + * history) so we ensure our PUSH/REPLACE navigations for data routers + * behave the same as POP + * + * @param to Unencoded path + */ + encodeLocation(to: To): Path; + + /** + * Pushes a new location onto the history stack, increasing its length by one. + * If there were any entries in the stack after the current one, they are + * lost. + * + * @param to - The new URL + * @param state - Data to associate with the new location + */ + push(to: To, state?: any): void; + + /** + * Replaces the current location in the history stack with a new one. The + * location that was replaced will no longer be available. + * + * @param to - The new URL + * @param state - Data to associate with the new location + */ + replace(to: To, state?: any): void; + + /** + * Navigates `n` entries backward/forward in the history stack relative to the + * current index. For example, a "back" navigation would use go(-1). + * + * @param delta - The delta in the stack index + */ + go(delta: number): void; + + /** + * Sets up a listener that will be called whenever the current location + * changes. + * + * @param listener - A function that will be called when the location changes + * @returns unlisten - A function that may be used to stop listening + */ + listen(listener: Listener): () => void; +} + +type HistoryState = { + usr: any; + key?: string; + idx: number; +}; + +const PopStateEventType = "popstate"; +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region Memory History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A user-supplied object that describes a location. Used when providing + * entries to `createMemoryHistory` via its `initialEntries` option. + */ +export type InitialEntry = string | Partial; + +export type MemoryHistoryOptions = { + initialEntries?: InitialEntry[]; + initialIndex?: number; + v5Compat?: boolean; +}; + +/** + * A memory history stores locations in memory. This is useful in stateful + * environments where there is no web browser, such as node tests or React + * Native. + */ +export interface MemoryHistory extends History { + /** + * The current index in the history stack. + */ + readonly index: number; +} + +/** + * Memory history stores the current location in memory. It is designed for use + * in stateful non-browser environments like tests and React Native. + */ +export function createMemoryHistory( + options: MemoryHistoryOptions = {} +): MemoryHistory { + let { initialEntries = ["/"], initialIndex, v5Compat = false } = options; + let entries: Location[]; // Declare so we can access from createMemoryLocation + entries = initialEntries.map((entry, index) => + createMemoryLocation( + entry, + typeof entry === "string" ? null : entry.state, + index === 0 ? "default" : undefined + ) + ); + let index = clampIndex( + initialIndex == null ? entries.length - 1 : initialIndex + ); + let action = Action.Pop; + let listener: Listener | null = null; + + function clampIndex(n: number): number { + return Math.min(Math.max(n, 0), entries.length - 1); + } + function getCurrentLocation(): Location { + return entries[index]; + } + function createMemoryLocation( + to: To, + state: any = null, + key?: string + ): Location { + let location = createLocation( + entries ? getCurrentLocation().pathname : "/", + to, + state, + key + ); + warning( + location.pathname.charAt(0) === "/", + `relative pathnames are not supported in memory history: ${JSON.stringify( + to + )}` + ); + return location; + } + + function createHref(to: To) { + return typeof to === "string" ? to : createPath(to); + } + + let history: MemoryHistory = { + get index() { + return index; + }, + get action() { + return action; + }, + get location() { + return getCurrentLocation(); + }, + createHref, + createURL(to) { + return new URL(createHref(to), "http://localhost"); + }, + encodeLocation(to: To) { + let path = typeof to === "string" ? parsePath(to) : to; + return { + pathname: path.pathname || "", + search: path.search || "", + hash: path.hash || "", + }; + }, + push(to, state) { + action = Action.Push; + let nextLocation = createMemoryLocation(to, state); + index += 1; + entries.splice(index, entries.length, nextLocation); + if (v5Compat && listener) { + listener({ action, location: nextLocation, delta: 1 }); + } + }, + replace(to, state) { + action = Action.Replace; + let nextLocation = createMemoryLocation(to, state); + entries[index] = nextLocation; + if (v5Compat && listener) { + listener({ action, location: nextLocation, delta: 0 }); + } + }, + go(delta) { + action = Action.Pop; + let nextIndex = clampIndex(index + delta); + let nextLocation = entries[nextIndex]; + index = nextIndex; + if (listener) { + listener({ action, location: nextLocation, delta }); + } + }, + listen(fn: Listener) { + listener = fn; + return () => { + listener = null; + }; + }, + }; + + return history; +} +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region Browser History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A browser history stores the current location in regular URLs in a web + * browser environment. This is the standard for most web apps and provides the + * cleanest URLs the browser's address bar. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#browserhistory + */ +export interface BrowserHistory extends UrlHistory {} + +export type BrowserHistoryOptions = UrlHistoryOptions; + +/** + * Browser history stores the location in regular URLs. This is the standard for + * most web apps, but it requires some configuration on the server to ensure you + * serve the same app at multiple URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory + */ +export function createBrowserHistory( + options: BrowserHistoryOptions = {} +): BrowserHistory { + function createBrowserLocation( + window: Window, + globalHistory: Window["history"] + ) { + let { pathname, search, hash } = window.location; + return createLocation( + "", + { pathname, search, hash }, + // state defaults to `null` because `window.history.state` does + (globalHistory.state && globalHistory.state.usr) || null, + (globalHistory.state && globalHistory.state.key) || "default" + ); + } + + function createBrowserHref(window: Window, to: To) { + return typeof to === "string" ? to : createPath(to); + } + + return getUrlBasedHistory( + createBrowserLocation, + createBrowserHref, + null, + options + ); +} +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region Hash History +//////////////////////////////////////////////////////////////////////////////// + +/** + * A hash history stores the current location in the fragment identifier portion + * of the URL in a web browser environment. + * + * This is ideal for apps that do not control the server for some reason + * (because the fragment identifier is never sent to the server), including some + * shared hosting environments that do not provide fine-grained controls over + * which pages are served at which URLs. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#hashhistory + */ +export interface HashHistory extends UrlHistory {} + +export type HashHistoryOptions = UrlHistoryOptions; + +/** + * Hash history stores the location in window.location.hash. This makes it ideal + * for situations where you don't want to send the location to the server for + * some reason, either because you do cannot configure it or the URL space is + * reserved for something else. + * + * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory + */ +export function createHashHistory( + options: HashHistoryOptions = {} +): HashHistory { + function createHashLocation( + window: Window, + globalHistory: Window["history"] + ) { + let { + pathname = "/", + search = "", + hash = "", + } = parsePath(window.location.hash.substr(1)); + return createLocation( + "", + { pathname, search, hash }, + // state defaults to `null` because `window.history.state` does + (globalHistory.state && globalHistory.state.usr) || null, + (globalHistory.state && globalHistory.state.key) || "default" + ); + } + + function createHashHref(window: Window, to: To) { + let base = window.document.querySelector("base"); + let href = ""; + + if (base && base.getAttribute("href")) { + let url = window.location.href; + let hashIndex = url.indexOf("#"); + href = hashIndex === -1 ? url : url.slice(0, hashIndex); + } + + return href + "#" + (typeof to === "string" ? to : createPath(to)); + } + + function validateHashLocation(location: Location, to: To) { + warning( + location.pathname.charAt(0) === "/", + `relative pathnames are not supported in hash history.push(${JSON.stringify( + to + )})` + ); + } + + return getUrlBasedHistory( + createHashLocation, + createHashHref, + validateHashLocation, + options + ); +} +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region UTILS +//////////////////////////////////////////////////////////////////////////////// + +/** + * @private + */ +export function invariant(value: boolean, message?: string): asserts value; +export function invariant( + value: T | null | undefined, + message?: string +): asserts value is T; +export function invariant(value: any, message?: string) { + if (value === false || value === null || typeof value === "undefined") { + throw new Error(message); + } +} + +export function warning(cond: any, message: string) { + if (!cond) { + // eslint-disable-next-line no-console + if (typeof console !== "undefined") console.warn(message); + + try { + // Welcome to debugging history! + // + // This error is thrown as a convenience so you can more easily + // find the source for a warning that appears in the console by + // enabling "pause on exceptions" in your JavaScript debugger. + throw new Error(message); + // eslint-disable-next-line no-empty + } catch (e) {} + } +} + +function createKey() { + return Math.random().toString(36).substr(2, 8); +} + +/** + * For browser-based histories, we combine the state and key into an object + */ +function getHistoryState(location: Location, index: number): HistoryState { + return { + usr: location.state, + key: location.key, + idx: index, + }; +} + +/** + * Creates a Location object with a unique key from the given Path + */ +export function createLocation( + current: string | Location, + to: To, + state: any = null, + key?: string +): Readonly { + let location: Readonly = { + pathname: typeof current === "string" ? current : current.pathname, + search: "", + hash: "", + ...(typeof to === "string" ? parsePath(to) : to), + state, + // TODO: This could be cleaned up. push/replace should probably just take + // full Locations now and avoid the need to run through this flow at all + // But that's a pretty big refactor to the current test suite so going to + // keep as is for the time being and just let any incoming keys take precedence + key: (to && (to as Location).key) || key || createKey(), + }; + return location; +} + +/** + * Creates a string URL path from the given pathname, search, and hash components. + */ +export function createPath({ + pathname = "/", + search = "", + hash = "", +}: Partial) { + if (search && search !== "?") + pathname += search.charAt(0) === "?" ? search : "?" + search; + if (hash && hash !== "#") + pathname += hash.charAt(0) === "#" ? hash : "#" + hash; + return pathname; +} + +/** + * Parses a string URL path into its separate pathname, search, and hash components. + */ +export function parsePath(path: string): Partial { + let parsedPath: Partial = {}; + + if (path) { + let hashIndex = path.indexOf("#"); + if (hashIndex >= 0) { + parsedPath.hash = path.substr(hashIndex); + path = path.substr(0, hashIndex); + } + + let searchIndex = path.indexOf("?"); + if (searchIndex >= 0) { + parsedPath.search = path.substr(searchIndex); + path = path.substr(0, searchIndex); + } + + if (path) { + parsedPath.pathname = path; + } + } + + return parsedPath; +} + +export interface UrlHistory extends History {} + +export type UrlHistoryOptions = { + window?: Window; + v5Compat?: boolean; +}; + +function getUrlBasedHistory( + getLocation: (window: Window, globalHistory: Window["history"]) => Location, + createHref: (window: Window, to: To) => string, + validateLocation: ((location: Location, to: To) => void) | null, + options: UrlHistoryOptions = {} +): UrlHistory { + let { window = document.defaultView!, v5Compat = false } = options; + let globalHistory = window.history; + let action = Action.Pop; + let listener: Listener | null = null; + + let index = getIndex()!; + // Index should only be null when we initialize. If not, it's because the + // user called history.pushState or history.replaceState directly, in which + // case we should log a warning as it will result in bugs. + if (index == null) { + index = 0; + globalHistory.replaceState({ ...globalHistory.state, idx: index }, ""); + } + + function getIndex(): number { + let state = globalHistory.state || { idx: null }; + return state.idx; + } + + function handlePop() { + action = Action.Pop; + let nextIndex = getIndex(); + let delta = nextIndex == null ? null : nextIndex - index; + index = nextIndex; + if (listener) { + listener({ action, location: history.location, delta }); + } + } + + function push(to: To, state?: any) { + action = Action.Push; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + + index = getIndex() + 1; + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + + // try...catch because iOS limits us to 100 pushState calls :/ + try { + globalHistory.pushState(historyState, "", url); + } catch (error) { + // They are going to lose state here, but there is no real + // way to warn them about it since the page will refresh... + window.location.assign(url); + } + + if (v5Compat && listener) { + listener({ action, location: history.location, delta: 1 }); + } + } + + function replace(to: To, state?: any) { + action = Action.Replace; + let location = createLocation(history.location, to, state); + if (validateLocation) validateLocation(location, to); + + index = getIndex(); + let historyState = getHistoryState(location, index); + let url = history.createHref(location); + globalHistory.replaceState(historyState, "", url); + + if (v5Compat && listener) { + listener({ action, location: history.location, delta: 0 }); + } + } + + function createURL(to: To): URL { + // window.location.origin is "null" (the literal string value) in Firefox + // under certain conditions, notably when serving from a local HTML file + // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297 + let base = + window.location.origin !== "null" + ? window.location.origin + : window.location.href; + + let href = typeof to === "string" ? to : createPath(to); + invariant( + base, + `No window.location.(origin|href) available to create URL for href: ${href}` + ); + return new URL(href, base); + } + + let history: History = { + get action() { + return action; + }, + get location() { + return getLocation(window, globalHistory); + }, + listen(fn: Listener) { + if (listener) { + throw new Error("A history only accepts one active listener"); + } + window.addEventListener(PopStateEventType, handlePop); + listener = fn; + + return () => { + window.removeEventListener(PopStateEventType, handlePop); + listener = null; + }; + }, + createHref(to) { + return createHref(window, to); + }, + createURL, + encodeLocation(to) { + // Encode a Location the same way window.location would + let url = createURL(to); + return { + pathname: url.pathname, + search: url.search, + hash: url.hash, + }; + }, + push, + replace, + go(n) { + return globalHistory.go(n); + }, + }; + + return history; +} + +//#endregion diff --git a/node_modules/@remix-run/router/index.ts b/node_modules/@remix-run/router/index.ts new file mode 100644 index 00000000..3d4fea96 --- /dev/null +++ b/node_modules/@remix-run/router/index.ts @@ -0,0 +1,90 @@ +export type { + ActionFunction, + ActionFunctionArgs, + AgnosticDataIndexRouteObject, + AgnosticDataNonIndexRouteObject, + AgnosticDataRouteMatch, + AgnosticDataRouteObject, + AgnosticIndexRouteObject, + AgnosticNonIndexRouteObject, + AgnosticRouteMatch, + AgnosticRouteObject, + LazyRouteFunction, + TrackedPromise, + FormEncType, + FormMethod, + HTMLFormMethod, + JsonFunction, + LoaderFunction, + LoaderFunctionArgs, + ParamParseKey, + Params, + PathMatch, + PathPattern, + RedirectFunction, + ShouldRevalidateFunction, + V7_FormMethod, +} from "./utils"; + +export { + AbortedDeferredError, + ErrorResponse, + defer, + generatePath, + getToPathname, + isRouteErrorResponse, + joinPaths, + json, + matchPath, + matchRoutes, + normalizePathname, + redirect, + resolvePath, + resolveTo, + stripBasename, +} from "./utils"; + +export type { + BrowserHistory, + BrowserHistoryOptions, + HashHistory, + HashHistoryOptions, + History, + InitialEntry, + Location, + MemoryHistory, + MemoryHistoryOptions, + Path, + To, +} from "./history"; + +export { + Action, + createBrowserHistory, + createPath, + createHashHistory, + createMemoryHistory, + parsePath, +} from "./history"; + +export * from "./router"; + +/////////////////////////////////////////////////////////////////////////////// +// DANGER! PLEASE READ ME! +// We consider these exports an implementation detail and do not guarantee +// against any breaking changes, regardless of the semver release. Use with +// extreme caution and only if you understand the consequences. Godspeed. +/////////////////////////////////////////////////////////////////////////////// + +/** @internal */ +export type { RouteManifest as UNSAFE_RouteManifest } from "./utils"; +export { + DeferredData as UNSAFE_DeferredData, + convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, + getPathContributingMatches as UNSAFE_getPathContributingMatches, +} from "./utils"; + +export { + invariant as UNSAFE_invariant, + warning as UNSAFE_warning, +} from "./history"; diff --git a/node_modules/@remix-run/router/package.json b/node_modules/@remix-run/router/package.json new file mode 100644 index 00000000..f92ebfcf --- /dev/null +++ b/node_modules/@remix-run/router/package.json @@ -0,0 +1,33 @@ +{ + "name": "@remix-run/router", + "version": "1.5.0", + "description": "Nested/Data-driven/Framework-agnostic Routing", + "keywords": [ + "remix", + "router", + "location" + ], + "repository": { + "type": "git", + "url": "https://github.com/remix-run/react-router", + "directory": "packages/router" + }, + "license": "MIT", + "author": "Remix Software ", + "sideEffects": false, + "main": "./dist/router.cjs.js", + "unpkg": "./dist/router.umd.min.js", + "module": "./dist/router.js", + "types": "./dist/index.d.ts", + "files": [ + "dist/", + "*.ts", + "CHANGELOG.md" + ], + "engines": { + "node": ">=14" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/node_modules/@remix-run/router/router.ts b/node_modules/@remix-run/router/router.ts new file mode 100644 index 00000000..9e14bd0c --- /dev/null +++ b/node_modules/@remix-run/router/router.ts @@ -0,0 +1,4017 @@ +import type { History, Location, Path, To } from "./history"; +import { + Action as HistoryAction, + createLocation, + createPath, + invariant, + parsePath, + warning, +} from "./history"; +import type { + DataResult, + DeferredData, + AgnosticDataRouteMatch, + AgnosticDataRouteObject, + DeferredResult, + ErrorResult, + FormEncType, + FormMethod, + DetectErrorBoundaryFunction, + RedirectResult, + RouteData, + AgnosticRouteObject, + Submission, + SuccessResult, + AgnosticRouteMatch, + ShouldRevalidateFunction, + RouteManifest, + ImmutableRouteKey, + ActionFunction, + LoaderFunction, + V7_MutationFormMethod, + V7_FormMethod, + HTMLFormMethod, + MutationFormMethod, +} from "./utils"; +import { + ErrorResponse, + ResultType, + convertRoutesToDataRoutes, + getPathContributingMatches, + immutableRouteKeys, + isRouteErrorResponse, + joinPaths, + matchRoutes, + resolveTo, + stripBasename, +} from "./utils"; + +//////////////////////////////////////////////////////////////////////////////// +//#region Types and Constants +//////////////////////////////////////////////////////////////////////////////// + +/** + * A Router instance manages all navigation and data loading/mutations + */ +export interface Router { + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the basename for the router + */ + get basename(): RouterInit["basename"]; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the current state of the router + */ + get state(): RouterState; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Return the routes for this router instance + */ + get routes(): AgnosticDataRouteObject[]; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Initialize the router, including adding history listeners and kicking off + * initial data fetches. Returns a function to cleanup listeners and abort + * any in-progress loads + */ + initialize(): Router; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Subscribe to router.state updates + * + * @param fn function to call with the new state + */ + subscribe(fn: RouterSubscriber): () => void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Enable scroll restoration behavior in the router + * + * @param savedScrollPositions Object that will manage positions, in case + * it's being restored from sessionStorage + * @param getScrollPosition Function to get the active Y scroll position + * @param getKey Function to get the key to use for restoration + */ + enableScrollRestoration( + savedScrollPositions: Record, + getScrollPosition: GetScrollPositionFunction, + getKey?: GetScrollRestorationKeyFunction + ): () => void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Navigate forward/backward in the history stack + * @param to Delta to move in the history stack + */ + navigate(to: number): Promise; + + /** + * Navigate to the given path + * @param to Path to navigate to + * @param opts Navigation options (method, submission, etc.) + */ + navigate(to: To, opts?: RouterNavigateOptions): Promise; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Trigger a fetcher load/submission + * + * @param key Fetcher key + * @param routeId Route that owns the fetcher + * @param href href to fetch + * @param opts Fetcher options, (method, submission, etc.) + */ + fetch( + key: string, + routeId: string, + href: string, + opts?: RouterNavigateOptions + ): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Trigger a revalidation of all current route loaders and fetcher loads + */ + revalidate(): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Utility function to create an href for the given location + * @param location + */ + createHref(location: Location | URL): string; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Utility function to URL encode a destination path according to the internal + * history implementation + * @param to + */ + encodeLocation(to: To): Path; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Get/create a fetcher for the given key + * @param key + */ + getFetcher(key?: string): Fetcher; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Delete the fetcher for a given key + * @param key + */ + deleteFetcher(key?: string): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Cleanup listeners and abort any in-progress loads + */ + dispose(): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Get a navigation blocker + * @param key The identifier for the blocker + * @param fn The blocker function implementation + */ + getBlocker(key: string, fn: BlockerFunction): Blocker; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Delete a navigation blocker + * @param key The identifier for the blocker + */ + deleteBlocker(key: string): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * HMR needs to pass in-flight route updates to React Router + * TODO: Replace this with granular route update APIs (addRoute, updateRoute, deleteRoute) + */ + _internalSetRoutes(routes: AgnosticRouteObject[]): void; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Internal fetch AbortControllers accessed by unit tests + */ + _internalFetchControllers: Map; + + /** + * @internal + * PRIVATE - DO NOT USE + * + * Internal pending DeferredData instances accessed by unit tests + */ + _internalActiveDeferreds: Map; +} + +/** + * State maintained internally by the router. During a navigation, all states + * reflect the the "old" location unless otherwise noted. + */ +export interface RouterState { + /** + * The action of the most recent navigation + */ + historyAction: HistoryAction; + + /** + * The current location reflected by the router + */ + location: Location; + + /** + * The current set of route matches + */ + matches: AgnosticDataRouteMatch[]; + + /** + * Tracks whether we've completed our initial data load + */ + initialized: boolean; + + /** + * Current scroll position we should start at for a new view + * - number -> scroll position to restore to + * - false -> do not restore scroll at all (used during submissions) + * - null -> don't have a saved position, scroll to hash or top of page + */ + restoreScrollPosition: number | false | null; + + /** + * Indicate whether this navigation should skip resetting the scroll position + * if we are unable to restore the scroll position + */ + preventScrollReset: boolean; + + /** + * Tracks the state of the current navigation + */ + navigation: Navigation; + + /** + * Tracks any in-progress revalidations + */ + revalidation: RevalidationState; + + /** + * Data from the loaders for the current matches + */ + loaderData: RouteData; + + /** + * Data from the action for the current matches + */ + actionData: RouteData | null; + + /** + * Errors caught from loaders for the current matches + */ + errors: RouteData | null; + + /** + * Map of current fetchers + */ + fetchers: Map; + + /** + * Map of current blockers + */ + blockers: Map; +} + +/** + * Data that can be passed into hydrate a Router from SSR + */ +export type HydrationState = Partial< + Pick +>; + +/** + * Future flags to toggle new feature behavior + */ +export interface FutureConfig { + v7_normalizeFormMethod: boolean; +} + +/** + * Initialization options for createRouter + */ +export interface RouterInit { + routes: AgnosticRouteObject[]; + history: History; + basename?: string; + detectErrorBoundary?: DetectErrorBoundaryFunction; + future?: FutureConfig; + hydrationData?: HydrationState; +} + +/** + * State returned from a server-side query() call + */ +export interface StaticHandlerContext { + basename: Router["basename"]; + location: RouterState["location"]; + matches: RouterState["matches"]; + loaderData: RouterState["loaderData"]; + actionData: RouterState["actionData"]; + errors: RouterState["errors"]; + statusCode: number; + loaderHeaders: Record; + actionHeaders: Record; + activeDeferreds: Record | null; + _deepestRenderedBoundaryId?: string | null; +} + +/** + * A StaticHandler instance manages a singular SSR navigation/fetch event + */ +export interface StaticHandler { + dataRoutes: AgnosticDataRouteObject[]; + query( + request: Request, + opts?: { requestContext?: unknown } + ): Promise; + queryRoute( + request: Request, + opts?: { routeId?: string; requestContext?: unknown } + ): Promise; +} + +/** + * Subscriber function signature for changes to router state + */ +export interface RouterSubscriber { + (state: RouterState): void; +} + +interface UseMatchesMatch { + id: string; + pathname: string; + params: AgnosticRouteMatch["params"]; + data: unknown; + handle: unknown; +} + +/** + * Function signature for determining the key to be used in scroll restoration + * for a given location + */ +export interface GetScrollRestorationKeyFunction { + (location: Location, matches: UseMatchesMatch[]): string | null; +} + +/** + * Function signature for determining the current scroll position + */ +export interface GetScrollPositionFunction { + (): number; +} + +/** + * Options for a navigate() call for a Link navigation + */ +type LinkNavigateOptions = { + replace?: boolean; + state?: any; + preventScrollReset?: boolean; +}; + +/** + * Options for a navigate() call for a Form navigation + */ +type SubmissionNavigateOptions = { + replace?: boolean; + state?: any; + preventScrollReset?: boolean; + formMethod?: HTMLFormMethod; + formEncType?: FormEncType; + formData: FormData; +}; + +/** + * Options to pass to navigate() for either a Link or Form navigation + */ +export type RouterNavigateOptions = + | LinkNavigateOptions + | SubmissionNavigateOptions; + +/** + * Options to pass to fetch() + */ +export type RouterFetchOptions = + | Omit + | Omit; + +/** + * Potential states for state.navigation + */ +export type NavigationStates = { + Idle: { + state: "idle"; + location: undefined; + formMethod: undefined; + formAction: undefined; + formEncType: undefined; + formData: undefined; + }; + Loading: { + state: "loading"; + location: Location; + formMethod: FormMethod | V7_FormMethod | undefined; + formAction: string | undefined; + formEncType: FormEncType | undefined; + formData: FormData | undefined; + }; + Submitting: { + state: "submitting"; + location: Location; + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; + }; +}; + +export type Navigation = NavigationStates[keyof NavigationStates]; + +export type RevalidationState = "idle" | "loading"; + +/** + * Potential states for fetchers + */ +type FetcherStates = { + Idle: { + state: "idle"; + formMethod: undefined; + formAction: undefined; + formEncType: undefined; + formData: undefined; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; + Loading: { + state: "loading"; + formMethod: FormMethod | V7_FormMethod | undefined; + formAction: string | undefined; + formEncType: FormEncType | undefined; + formData: FormData | undefined; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; + Submitting: { + state: "submitting"; + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; + data: TData | undefined; + " _hasFetcherDoneAnything "?: boolean; + }; +}; + +export type Fetcher = + FetcherStates[keyof FetcherStates]; + +interface BlockerBlocked { + state: "blocked"; + reset(): void; + proceed(): void; + location: Location; +} + +interface BlockerUnblocked { + state: "unblocked"; + reset: undefined; + proceed: undefined; + location: undefined; +} + +interface BlockerProceeding { + state: "proceeding"; + reset: undefined; + proceed: undefined; + location: Location; +} + +export type Blocker = BlockerUnblocked | BlockerBlocked | BlockerProceeding; + +export type BlockerFunction = (args: { + currentLocation: Location; + nextLocation: Location; + historyAction: HistoryAction; +}) => boolean; + +interface ShortCircuitable { + /** + * startNavigation does not need to complete the navigation because we + * redirected or got interrupted + */ + shortCircuited?: boolean; +} + +interface HandleActionResult extends ShortCircuitable { + /** + * Error thrown from the current action, keyed by the route containing the + * error boundary to render the error. To be committed to the state after + * loaders have completed + */ + pendingActionError?: RouteData; + /** + * Data returned from the current action, keyed by the route owning the action. + * To be committed to the state after loaders have completed + */ + pendingActionData?: RouteData; +} + +interface HandleLoadersResult extends ShortCircuitable { + /** + * loaderData returned from the current set of loaders + */ + loaderData?: RouterState["loaderData"]; + /** + * errors thrown from the current set of loaders + */ + errors?: RouterState["errors"]; +} + +/** + * Cached info for active fetcher.load() instances so they can participate + * in revalidation + */ +interface FetchLoadMatch { + routeId: string; + path: string; +} + +/** + * Identified fetcher.load() calls that need to be revalidated + */ +interface RevalidatingFetcher extends FetchLoadMatch { + key: string; + match: AgnosticDataRouteMatch | null; + matches: AgnosticDataRouteMatch[] | null; +} + +/** + * Wrapper object to allow us to throw any response out from callLoaderOrAction + * for queryRouter while preserving whether or not it was thrown or returned + * from the loader/action + */ +interface QueryRouteResponse { + type: ResultType.data | ResultType.error; + response: Response; +} + +const validMutationMethodsArr: MutationFormMethod[] = [ + "post", + "put", + "patch", + "delete", +]; +const validMutationMethods = new Set( + validMutationMethodsArr +); + +const validRequestMethodsArr: FormMethod[] = [ + "get", + ...validMutationMethodsArr, +]; +const validRequestMethods = new Set(validRequestMethodsArr); + +const redirectStatusCodes = new Set([301, 302, 303, 307, 308]); +const redirectPreserveMethodStatusCodes = new Set([307, 308]); + +export const IDLE_NAVIGATION: NavigationStates["Idle"] = { + state: "idle", + location: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, +}; + +export const IDLE_FETCHER: FetcherStates["Idle"] = { + state: "idle", + data: undefined, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, +}; + +export const IDLE_BLOCKER: BlockerUnblocked = { + state: "unblocked", + proceed: undefined, + reset: undefined, + location: undefined, +}; + +const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i; + +const isBrowser = + typeof window !== "undefined" && + typeof window.document !== "undefined" && + typeof window.document.createElement !== "undefined"; +const isServer = !isBrowser; + +const defaultDetectErrorBoundary = (route: AgnosticRouteObject) => + Boolean(route.hasErrorBoundary); +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region createRouter +//////////////////////////////////////////////////////////////////////////////// + +/** + * Create a router and listen to history POP navigations + */ +export function createRouter(init: RouterInit): Router { + invariant( + init.routes.length > 0, + "You must provide a non-empty routes array to createRouter" + ); + + let detectErrorBoundary = + init.detectErrorBoundary || defaultDetectErrorBoundary; + + // Routes keyed by ID + let manifest: RouteManifest = {}; + // Routes in tree format for matching + let dataRoutes = convertRoutesToDataRoutes( + init.routes, + detectErrorBoundary, + undefined, + manifest + ); + let inFlightDataRoutes: AgnosticDataRouteObject[] | undefined; + // Config driven behavior flags + let future: FutureConfig = { + v7_normalizeFormMethod: false, + ...init.future, + }; + // Cleanup function for history + let unlistenHistory: (() => void) | null = null; + // Externally-provided functions to call on all state changes + let subscribers = new Set(); + // Externally-provided object to hold scroll restoration locations during routing + let savedScrollPositions: Record | null = null; + // Externally-provided function to get scroll restoration keys + let getScrollRestorationKey: GetScrollRestorationKeyFunction | null = null; + // Externally-provided function to get current scroll position + let getScrollPosition: GetScrollPositionFunction | null = null; + // One-time flag to control the initial hydration scroll restoration. Because + // we don't get the saved positions from until _after_ + // the initial render, we need to manually trigger a separate updateState to + // send along the restoreScrollPosition + // Set to true if we have `hydrationData` since we assume we were SSR'd and that + // SSR did the initial scroll restoration. + let initialScrollRestored = init.hydrationData != null; + + let initialMatches = matchRoutes( + dataRoutes, + init.history.location, + init.basename + ); + let initialErrors: RouteData | null = null; + + if (initialMatches == null) { + // If we do not match a user-provided-route, fall back to the root + // to allow the error boundary to take over + let error = getInternalRouterError(404, { + pathname: init.history.location.pathname, + }); + let { matches, route } = getShortCircuitMatches(dataRoutes); + initialMatches = matches; + initialErrors = { [route.id]: error }; + } + + let initialized = + // All initialMatches need to be loaded before we're ready. If we have lazy + // functions around still then we'll need to run them in initialize() + !initialMatches.some((m) => m.route.lazy) && + // And we have to either have no loaders or have been provided hydrationData + (!initialMatches.some((m) => m.route.loader) || init.hydrationData != null); + + let router: Router; + let state: RouterState = { + historyAction: init.history.action, + location: init.history.location, + matches: initialMatches, + initialized, + navigation: IDLE_NAVIGATION, + // Don't restore on initial updateState() if we were SSR'd + restoreScrollPosition: init.hydrationData != null ? false : null, + preventScrollReset: false, + revalidation: "idle", + loaderData: (init.hydrationData && init.hydrationData.loaderData) || {}, + actionData: (init.hydrationData && init.hydrationData.actionData) || null, + errors: (init.hydrationData && init.hydrationData.errors) || initialErrors, + fetchers: new Map(), + blockers: new Map(), + }; + + // -- Stateful internal variables to manage navigations -- + // Current navigation in progress (to be committed in completeNavigation) + let pendingAction: HistoryAction = HistoryAction.Pop; + + // Should the current navigation prevent the scroll reset if scroll cannot + // be restored? + let pendingPreventScrollReset = false; + + // AbortController for the active navigation + let pendingNavigationController: AbortController | null; + + // We use this to avoid touching history in completeNavigation if a + // revalidation is entirely uninterrupted + let isUninterruptedRevalidation = false; + + // Use this internal flag to force revalidation of all loaders: + // - submissions (completed or interrupted) + // - useRevalidate() + // - X-Remix-Revalidate (from redirect) + let isRevalidationRequired = false; + + // Use this internal array to capture routes that require revalidation due + // to a cancelled deferred on action submission + let cancelledDeferredRoutes: string[] = []; + + // Use this internal array to capture fetcher loads that were cancelled by an + // action navigation and require revalidation + let cancelledFetcherLoads: string[] = []; + + // AbortControllers for any in-flight fetchers + let fetchControllers = new Map(); + + // Track loads based on the order in which they started + let incrementingLoadId = 0; + + // Track the outstanding pending navigation data load to be compared against + // the globally incrementing load when a fetcher load lands after a completed + // navigation + let pendingNavigationLoadId = -1; + + // Fetchers that triggered data reloads as a result of their actions + let fetchReloadIds = new Map(); + + // Fetchers that triggered redirect navigations from their actions + let fetchRedirectIds = new Set(); + + // Most recent href/match for fetcher.load calls for fetchers + let fetchLoadMatches = new Map(); + + // Store DeferredData instances for active route matches. When a + // route loader returns defer() we stick one in here. Then, when a nested + // promise resolves we update loaderData. If a new navigation starts we + // cancel active deferreds for eliminated routes. + let activeDeferreds = new Map(); + + // Store blocker functions in a separate Map outside of router state since + // we don't need to update UI state if they change + let blockerFunctions = new Map(); + + // Flag to ignore the next history update, so we can revert the URL change on + // a POP navigation that was blocked by the user without touching router state + let ignoreNextHistoryUpdate = false; + + // Initialize the router, all side effects should be kicked off from here. + // Implemented as a Fluent API for ease of: + // let router = createRouter(init).initialize(); + function initialize() { + // If history informs us of a POP navigation, start the navigation but do not update + // state. We'll update our own state once the navigation completes + unlistenHistory = init.history.listen( + ({ action: historyAction, location, delta }) => { + // Ignore this event if it was just us resetting the URL from a + // blocked POP navigation + if (ignoreNextHistoryUpdate) { + ignoreNextHistoryUpdate = false; + return; + } + + warning( + blockerFunctions.size === 0 || delta != null, + "You are trying to use a blocker on a POP navigation to a location " + + "that was not created by @remix-run/router. This will fail silently in " + + "production. This can happen if you are navigating outside the router " + + "via `window.history.pushState`/`window.location.hash` instead of using " + + "router navigation APIs. This can also happen if you are using " + + "createHashRouter and the user manually changes the URL." + ); + + let blockerKey = shouldBlockNavigation({ + currentLocation: state.location, + nextLocation: location, + historyAction, + }); + + if (blockerKey && delta != null) { + // Restore the URL to match the current UI, but don't update router state + ignoreNextHistoryUpdate = true; + init.history.go(delta * -1); + + // Put the blocker into a blocked state + updateBlocker(blockerKey, { + state: "blocked", + location, + proceed() { + updateBlocker(blockerKey!, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location, + }); + // Re-do the same POP navigation we just blocked + init.history.go(delta); + }, + reset() { + deleteBlocker(blockerKey!); + updateState({ blockers: new Map(router.state.blockers) }); + }, + }); + return; + } + + return startNavigation(historyAction, location); + } + ); + + // Kick off initial data load if needed. Use Pop to avoid modifying history + // Note we don't do any handling of lazy here. For SPA's it'll get handled + // in the normal navigation flow. For SSR it's expected that lazy modules are + // resolved prior to router creation since we can't go into a fallbackElement + // UI for SSR'd apps + if (!state.initialized) { + startNavigation(HistoryAction.Pop, state.location); + } + + return router; + } + + // Clean up a router and it's side effects + function dispose() { + if (unlistenHistory) { + unlistenHistory(); + } + subscribers.clear(); + pendingNavigationController && pendingNavigationController.abort(); + state.fetchers.forEach((_, key) => deleteFetcher(key)); + state.blockers.forEach((_, key) => deleteBlocker(key)); + } + + // Subscribe to state updates for the router + function subscribe(fn: RouterSubscriber) { + subscribers.add(fn); + return () => subscribers.delete(fn); + } + + // Update our state and notify the calling context of the change + function updateState(newState: Partial): void { + state = { + ...state, + ...newState, + }; + subscribers.forEach((subscriber) => subscriber(state)); + } + + // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION + // and setting state.[historyAction/location/matches] to the new route. + // - Location is a required param + // - Navigation will always be set to IDLE_NAVIGATION + // - Can pass any other state in newState + function completeNavigation( + location: Location, + newState: Partial> + ): void { + // Deduce if we're in a loading/actionReload state: + // - We have committed actionData in the store + // - The current navigation was a mutation submission + // - We're past the submitting state and into the loading state + // - The location being loaded is not the result of a redirect + let isActionReload = + state.actionData != null && + state.navigation.formMethod != null && + isMutationMethod(state.navigation.formMethod) && + state.navigation.state === "loading" && + location.state?._isRedirect !== true; + + let actionData: RouteData | null; + if (newState.actionData) { + if (Object.keys(newState.actionData).length > 0) { + actionData = newState.actionData; + } else { + // Empty actionData -> clear prior actionData due to an action error + actionData = null; + } + } else if (isActionReload) { + // Keep the current data if we're wrapping up the action reload + actionData = state.actionData; + } else { + // Clear actionData on any other completed navigations + actionData = null; + } + + // Always preserve any existing loaderData from re-used routes + let loaderData = newState.loaderData + ? mergeLoaderData( + state.loaderData, + newState.loaderData, + newState.matches || [], + newState.errors + ) + : state.loaderData; + + // On a successful navigation we can assume we got through all blockers + // so we can start fresh + for (let [key] of blockerFunctions) { + deleteBlocker(key); + } + + // Always respect the user flag. Otherwise don't reset on mutation + // submission navigations unless they redirect + let preventScrollReset = + pendingPreventScrollReset === true || + (state.navigation.formMethod != null && + isMutationMethod(state.navigation.formMethod) && + location.state?._isRedirect !== true); + + if (inFlightDataRoutes) { + dataRoutes = inFlightDataRoutes; + inFlightDataRoutes = undefined; + } + + updateState({ + ...newState, // matches, errors, fetchers go through as-is + actionData, + loaderData, + historyAction: pendingAction, + location, + initialized: true, + navigation: IDLE_NAVIGATION, + revalidation: "idle", + restoreScrollPosition: getSavedScrollPosition( + location, + newState.matches || state.matches + ), + preventScrollReset, + blockers: new Map(state.blockers), + }); + + if (isUninterruptedRevalidation) { + // If this was an uninterrupted revalidation then do not touch history + } else if (pendingAction === HistoryAction.Pop) { + // Do nothing for POP - URL has already been updated + } else if (pendingAction === HistoryAction.Push) { + init.history.push(location, location.state); + } else if (pendingAction === HistoryAction.Replace) { + init.history.replace(location, location.state); + } + + // Reset stateful navigation vars + pendingAction = HistoryAction.Pop; + pendingPreventScrollReset = false; + isUninterruptedRevalidation = false; + isRevalidationRequired = false; + cancelledDeferredRoutes = []; + cancelledFetcherLoads = []; + } + + // Trigger a navigation event, which can either be a numerical POP or a PUSH + // replace with an optional submission + async function navigate( + to: number | To, + opts?: RouterNavigateOptions + ): Promise { + if (typeof to === "number") { + init.history.go(to); + return; + } + + let { path, submission, error } = normalizeNavigateOptions( + to, + future, + opts + ); + + let currentLocation = state.location; + let nextLocation = createLocation(state.location, path, opts && opts.state); + + // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded + // URL from window.location, so we need to encode it here so the behavior + // remains the same as POP and non-data-router usages. new URL() does all + // the same encoding we'd get from a history.pushState/window.location read + // without having to touch history + nextLocation = { + ...nextLocation, + ...init.history.encodeLocation(nextLocation), + }; + + let userReplace = opts && opts.replace != null ? opts.replace : undefined; + + let historyAction = HistoryAction.Push; + + if (userReplace === true) { + historyAction = HistoryAction.Replace; + } else if (userReplace === false) { + // no-op + } else if ( + submission != null && + isMutationMethod(submission.formMethod) && + submission.formAction === state.location.pathname + state.location.search + ) { + // By default on submissions to the current location we REPLACE so that + // users don't have to double-click the back button to get to the prior + // location. If the user redirects to a different location from the + // action/loader this will be ignored and the redirect will be a PUSH + historyAction = HistoryAction.Replace; + } + + let preventScrollReset = + opts && "preventScrollReset" in opts + ? opts.preventScrollReset === true + : undefined; + + let blockerKey = shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction, + }); + if (blockerKey) { + // Put the blocker into a blocked state + updateBlocker(blockerKey, { + state: "blocked", + location: nextLocation, + proceed() { + updateBlocker(blockerKey!, { + state: "proceeding", + proceed: undefined, + reset: undefined, + location: nextLocation, + }); + // Send the same navigation through + navigate(to, opts); + }, + reset() { + deleteBlocker(blockerKey!); + updateState({ blockers: new Map(state.blockers) }); + }, + }); + return; + } + + return await startNavigation(historyAction, nextLocation, { + submission, + // Send through the formData serialization error if we have one so we can + // render at the right error boundary after we match routes + pendingError: error, + preventScrollReset, + replace: opts && opts.replace, + }); + } + + // Revalidate all current loaders. If a navigation is in progress or if this + // is interrupted by a navigation, allow this to "succeed" by calling all + // loaders during the next loader round + function revalidate() { + interruptActiveLoads(); + updateState({ revalidation: "loading" }); + + // If we're currently submitting an action, we don't need to start a new + // navigation, we'll just let the follow up loader execution call all loaders + if (state.navigation.state === "submitting") { + return; + } + + // If we're currently in an idle state, start a new navigation for the current + // action/location and mark it as uninterrupted, which will skip the history + // update in completeNavigation + if (state.navigation.state === "idle") { + startNavigation(state.historyAction, state.location, { + startUninterruptedRevalidation: true, + }); + return; + } + + // Otherwise, if we're currently in a loading state, just start a new + // navigation to the navigation.location but do not trigger an uninterrupted + // revalidation so that history correctly updates once the navigation completes + startNavigation( + pendingAction || state.historyAction, + state.navigation.location, + { overrideNavigation: state.navigation } + ); + } + + // Start a navigation to the given action/location. Can optionally provide a + // overrideNavigation which will override the normalLoad in the case of a redirect + // navigation + async function startNavigation( + historyAction: HistoryAction, + location: Location, + opts?: { + submission?: Submission; + fetcherSubmission?: Submission; + overrideNavigation?: Navigation; + pendingError?: ErrorResponse; + startUninterruptedRevalidation?: boolean; + preventScrollReset?: boolean; + replace?: boolean; + } + ): Promise { + // Abort any in-progress navigations and start a new one. Unset any ongoing + // uninterrupted revalidations unless told otherwise, since we want this + // new navigation to update history normally + pendingNavigationController && pendingNavigationController.abort(); + pendingNavigationController = null; + pendingAction = historyAction; + isUninterruptedRevalidation = + (opts && opts.startUninterruptedRevalidation) === true; + + // Save the current scroll position every time we start a new navigation, + // and track whether we should reset scroll on completion + saveScrollPosition(state.location, state.matches); + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + + let routesToUse = inFlightDataRoutes || dataRoutes; + let loadingNavigation = opts && opts.overrideNavigation; + let matches = matchRoutes(routesToUse, location, init.basename); + + // Short circuit with a 404 on the root error boundary if we match nothing + if (!matches) { + let error = getInternalRouterError(404, { pathname: location.pathname }); + let { matches: notFoundMatches, route } = + getShortCircuitMatches(routesToUse); + // Cancel all pending deferred on 404s since we don't keep any routes + cancelActiveDeferreds(); + completeNavigation(location, { + matches: notFoundMatches, + loaderData: {}, + errors: { + [route.id]: error, + }, + }); + return; + } + + // Short circuit if it's only a hash change and not a mutation submission + // For example, on /page#hash and submit a which will + // default to a navigation to /page + if ( + isHashChangeOnly(state.location, location) && + !(opts && opts.submission && isMutationMethod(opts.submission.formMethod)) + ) { + completeNavigation(location, { matches }); + return; + } + + // Create a controller/Request for this navigation + pendingNavigationController = new AbortController(); + let request = createClientSideRequest( + init.history, + location, + pendingNavigationController.signal, + opts && opts.submission + ); + let pendingActionData: RouteData | undefined; + let pendingError: RouteData | undefined; + + if (opts && opts.pendingError) { + // If we have a pendingError, it means the user attempted a GET submission + // with binary FormData so assign here and skip to handleLoaders. That + // way we handle calling loaders above the boundary etc. It's not really + // different from an actionError in that sense. + pendingError = { + [findNearestBoundary(matches).route.id]: opts.pendingError, + }; + } else if ( + opts && + opts.submission && + isMutationMethod(opts.submission.formMethod) + ) { + // Call action if we received an action submission + let actionOutput = await handleAction( + request, + location, + opts.submission, + matches, + { replace: opts.replace } + ); + + if (actionOutput.shortCircuited) { + return; + } + + pendingActionData = actionOutput.pendingActionData; + pendingError = actionOutput.pendingActionError; + + let navigation: NavigationStates["Loading"] = { + state: "loading", + location, + ...opts.submission, + }; + loadingNavigation = navigation; + + // Create a GET request for the loaders + request = new Request(request.url, { signal: request.signal }); + } + + // Call loaders + let { shortCircuited, loaderData, errors } = await handleLoaders( + request, + location, + matches, + loadingNavigation, + opts && opts.submission, + opts && opts.fetcherSubmission, + opts && opts.replace, + pendingActionData, + pendingError + ); + + if (shortCircuited) { + return; + } + + // Clean up now that the action/loaders have completed. Don't clean up if + // we short circuited because pendingNavigationController will have already + // been assigned to a new controller for the next navigation + pendingNavigationController = null; + + completeNavigation(location, { + matches, + ...(pendingActionData ? { actionData: pendingActionData } : {}), + loaderData, + errors, + }); + } + + // Call the action matched by the leaf route for this navigation and handle + // redirects/errors + async function handleAction( + request: Request, + location: Location, + submission: Submission, + matches: AgnosticDataRouteMatch[], + opts?: { replace?: boolean } + ): Promise { + interruptActiveLoads(); + + // Put us in a submitting state + let navigation: NavigationStates["Submitting"] = { + state: "submitting", + location, + ...submission, + }; + updateState({ navigation }); + + // Call our action and get the result + let result: DataResult; + let actionMatch = getTargetMatch(matches, location); + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + result = { + type: ResultType.error, + error: getInternalRouterError(405, { + method: request.method, + pathname: location.pathname, + routeId: actionMatch.route.id, + }), + }; + } else { + result = await callLoaderOrAction( + "action", + request, + actionMatch, + matches, + manifest, + detectErrorBoundary, + router.basename + ); + + if (request.signal.aborted) { + return { shortCircuited: true }; + } + } + + if (isRedirectResult(result)) { + let replace: boolean; + if (opts && opts.replace != null) { + replace = opts.replace; + } else { + // If the user didn't explicity indicate replace behavior, replace if + // we redirected to the exact same location we're currently at to avoid + // double back-buttons + replace = + result.location === state.location.pathname + state.location.search; + } + await startRedirectNavigation(state, result, { submission, replace }); + return { shortCircuited: true }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + + // By default, all submissions are REPLACE navigations, but if the + // action threw an error that'll be rendered in an errorElement, we fall + // back to PUSH so that the user can use the back button to get back to + // the pre-submission form location to try again + if ((opts && opts.replace) !== true) { + pendingAction = HistoryAction.Push; + } + + return { + // Send back an empty object we can use to clear out any prior actionData + pendingActionData: {}, + pendingActionError: { [boundaryMatch.route.id]: result.error }, + }; + } + + if (isDeferredResult(result)) { + throw getInternalRouterError(400, { type: "defer-action" }); + } + + return { + pendingActionData: { [actionMatch.route.id]: result.data }, + }; + } + + // Call all applicable loaders for the given matches, handling redirects, + // errors, etc. + async function handleLoaders( + request: Request, + location: Location, + matches: AgnosticDataRouteMatch[], + overrideNavigation?: Navigation, + submission?: Submission, + fetcherSubmission?: Submission, + replace?: boolean, + pendingActionData?: RouteData, + pendingError?: RouteData + ): Promise { + // Figure out the right navigation we want to use for data loading + let loadingNavigation = overrideNavigation; + if (!loadingNavigation) { + let navigation: NavigationStates["Loading"] = { + state: "loading", + location, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + ...submission, + }; + loadingNavigation = navigation; + } + + // If this was a redirect from an action we don't have a "submission" but + // we have it on the loading navigation so use that if available + let activeSubmission = + submission || fetcherSubmission + ? submission || fetcherSubmission + : loadingNavigation.formMethod && + loadingNavigation.formAction && + loadingNavigation.formData && + loadingNavigation.formEncType + ? { + formMethod: loadingNavigation.formMethod, + formAction: loadingNavigation.formAction, + formData: loadingNavigation.formData, + formEncType: loadingNavigation.formEncType, + } + : undefined; + + let routesToUse = inFlightDataRoutes || dataRoutes; + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad( + init.history, + state, + matches, + activeSubmission, + location, + isRevalidationRequired, + cancelledDeferredRoutes, + cancelledFetcherLoads, + fetchLoadMatches, + routesToUse, + init.basename, + pendingActionData, + pendingError + ); + + // Cancel pending deferreds for no-longer-matched routes or routes we're + // about to reload. Note that if this is an action reload we would have + // already cancelled all pending deferreds so this would be a no-op + cancelActiveDeferreds( + (routeId) => + !(matches && matches.some((m) => m.route.id === routeId)) || + (matchesToLoad && matchesToLoad.some((m) => m.route.id === routeId)) + ); + + // Short circuit if we have no loaders to run + if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) { + completeNavigation(location, { + matches, + loaderData: {}, + // Commit pending error if we're short circuiting + errors: pendingError || null, + ...(pendingActionData ? { actionData: pendingActionData } : {}), + }); + return { shortCircuited: true }; + } + + // If this is an uninterrupted revalidation, we remain in our current idle + // state. If not, we need to switch to our loading state and load data, + // preserving any new action data or existing action data (in the case of + // a revalidation interrupting an actionReload) + if (!isUninterruptedRevalidation) { + revalidatingFetchers.forEach((rf) => { + let fetcher = state.fetchers.get(rf.key); + let revalidatingFetcher: FetcherStates["Loading"] = { + state: "loading", + data: fetcher && fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(rf.key, revalidatingFetcher); + }); + let actionData = pendingActionData || state.actionData; + updateState({ + navigation: loadingNavigation, + ...(actionData + ? Object.keys(actionData).length === 0 + ? { actionData: null } + : { actionData } + : {}), + ...(revalidatingFetchers.length > 0 + ? { fetchers: new Map(state.fetchers) } + : {}), + }); + } + + pendingNavigationLoadId = ++incrementingLoadId; + revalidatingFetchers.forEach((rf) => + fetchControllers.set(rf.key, pendingNavigationController!) + ); + + let { results, loaderResults, fetcherResults } = + await callLoadersAndMaybeResolveData( + state.matches, + matches, + matchesToLoad, + revalidatingFetchers, + request + ); + + if (request.signal.aborted) { + return { shortCircuited: true }; + } + + // Clean up _after_ loaders have completed. Don't clean up if we short + // circuited because fetchControllers would have been aborted and + // reassigned to new controllers for the next navigation + revalidatingFetchers.forEach((rf) => fetchControllers.delete(rf.key)); + + // If any loaders returned a redirect Response, start a new REPLACE navigation + let redirect = findRedirect(results); + if (redirect) { + await startRedirectNavigation(state, redirect, { replace }); + return { shortCircuited: true }; + } + + // Process and commit output from loaders + let { loaderData, errors } = processLoaderData( + state, + matches, + matchesToLoad, + loaderResults, + pendingError, + revalidatingFetchers, + fetcherResults, + activeDeferreds + ); + + // Wire up subscribers to update loaderData as promises settle + activeDeferreds.forEach((deferredData, routeId) => { + deferredData.subscribe((aborted) => { + // Note: No need to updateState here since the TrackedPromise on + // loaderData is stable across resolve/reject + // Remove this instance if we were aborted or if promises have settled + if (aborted || deferredData.done) { + activeDeferreds.delete(routeId); + } + }); + }); + + markFetchRedirectsDone(); + let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId); + + return { + loaderData, + errors, + ...(didAbortFetchLoads || revalidatingFetchers.length > 0 + ? { fetchers: new Map(state.fetchers) } + : {}), + }; + } + + function getFetcher(key: string): Fetcher { + return state.fetchers.get(key) || IDLE_FETCHER; + } + + // Trigger a fetcher load/submit for the given fetcher key + function fetch( + key: string, + routeId: string, + href: string, + opts?: RouterFetchOptions + ) { + if (isServer) { + throw new Error( + "router.fetch() was called during the server render, but it shouldn't be. " + + "You are likely calling a useFetcher() method in the body of your component. " + + "Try moving it to a useEffect or a callback." + ); + } + + if (fetchControllers.has(key)) abortFetcher(key); + + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = matchRoutes(routesToUse, href, init.basename); + if (!matches) { + setFetcherError( + key, + routeId, + getInternalRouterError(404, { pathname: href }) + ); + return; + } + + let { path, submission } = normalizeNavigateOptions( + href, + future, + opts, + true + ); + let match = getTargetMatch(matches, path); + + pendingPreventScrollReset = (opts && opts.preventScrollReset) === true; + + if (submission && isMutationMethod(submission.formMethod)) { + handleFetcherAction(key, routeId, path, match, matches, submission); + return; + } + + // Store off the match so we can call it's shouldRevalidate on subsequent + // revalidations + fetchLoadMatches.set(key, { routeId, path }); + handleFetcherLoader(key, routeId, path, match, matches, submission); + } + + // Call the action for the matched fetcher.submit(), and then handle redirects, + // errors, and revalidation + async function handleFetcherAction( + key: string, + routeId: string, + path: string, + match: AgnosticDataRouteMatch, + requestMatches: AgnosticDataRouteMatch[], + submission: Submission + ) { + interruptActiveLoads(); + fetchLoadMatches.delete(key); + + if (!match.route.action && !match.route.lazy) { + let error = getInternalRouterError(405, { + method: submission.formMethod, + pathname: path, + routeId: routeId, + }); + setFetcherError(key, routeId, error); + return; + } + + // Put this fetcher into it's submitting state + let existingFetcher = state.fetchers.get(key); + let fetcher: FetcherStates["Submitting"] = { + state: "submitting", + ...submission, + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, fetcher); + updateState({ fetchers: new Map(state.fetchers) }); + + // Call the action for the fetcher + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest( + init.history, + path, + abortController.signal, + submission + ); + fetchControllers.set(key, abortController); + + let actionResult = await callLoaderOrAction( + "action", + fetchRequest, + match, + requestMatches, + manifest, + detectErrorBoundary, + router.basename + ); + + if (fetchRequest.signal.aborted) { + // We can delete this so long as we weren't aborted by ou our own fetcher + // re-submit which would have put _new_ controller is in fetchControllers + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + return; + } + + if (isRedirectResult(actionResult)) { + fetchControllers.delete(key); + fetchRedirectIds.add(key); + let loadingFetcher: FetcherStates["Loading"] = { + state: "loading", + ...submission, + data: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, loadingFetcher); + updateState({ fetchers: new Map(state.fetchers) }); + + return startRedirectNavigation(state, actionResult, { + submission, + isFetchActionRedirect: true, + }); + } + + // Process any non-redirect errors thrown + if (isErrorResult(actionResult)) { + setFetcherError(key, routeId, actionResult.error); + return; + } + + if (isDeferredResult(actionResult)) { + throw getInternalRouterError(400, { type: "defer-action" }); + } + + // Start the data load for current matches, or the next location if we're + // in the middle of a navigation + let nextLocation = state.navigation.location || state.location; + let revalidationRequest = createClientSideRequest( + init.history, + + nextLocation, + abortController.signal + ); + let routesToUse = inFlightDataRoutes || dataRoutes; + let matches = + state.navigation.state !== "idle" + ? matchRoutes(routesToUse, state.navigation.location, init.basename) + : state.matches; + + invariant(matches, "Didn't find any matches after fetcher action"); + + let loadId = ++incrementingLoadId; + fetchReloadIds.set(key, loadId); + + let loadFetcher: FetcherStates["Loading"] = { + state: "loading", + data: actionResult.data, + ...submission, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, loadFetcher); + + let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad( + init.history, + state, + matches, + submission, + nextLocation, + isRevalidationRequired, + cancelledDeferredRoutes, + cancelledFetcherLoads, + fetchLoadMatches, + routesToUse, + init.basename, + { [match.route.id]: actionResult.data }, + undefined // No need to send through errors since we short circuit above + ); + + // Put all revalidating fetchers into the loading state, except for the + // current fetcher which we want to keep in it's current loading state which + // contains it's action submission info + action data + revalidatingFetchers + .filter((rf) => rf.key !== key) + .forEach((rf) => { + let staleKey = rf.key; + let existingFetcher = state.fetchers.get(staleKey); + let revalidatingFetcher: FetcherStates["Loading"] = { + state: "loading", + data: existingFetcher && existingFetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(staleKey, revalidatingFetcher); + fetchControllers.set(staleKey, abortController); + }); + + updateState({ fetchers: new Map(state.fetchers) }); + + let { results, loaderResults, fetcherResults } = + await callLoadersAndMaybeResolveData( + state.matches, + matches, + matchesToLoad, + revalidatingFetchers, + revalidationRequest + ); + + if (abortController.signal.aborted) { + return; + } + + fetchReloadIds.delete(key); + fetchControllers.delete(key); + revalidatingFetchers.forEach((r) => fetchControllers.delete(r.key)); + + let redirect = findRedirect(results); + if (redirect) { + return startRedirectNavigation(state, redirect); + } + + // Process and commit output from loaders + let { loaderData, errors } = processLoaderData( + state, + state.matches, + matchesToLoad, + loaderResults, + undefined, + revalidatingFetchers, + fetcherResults, + activeDeferreds + ); + + let doneFetcher: FetcherStates["Idle"] = { + state: "idle", + data: actionResult.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, doneFetcher); + + let didAbortFetchLoads = abortStaleFetchLoads(loadId); + + // If we are currently in a navigation loading state and this fetcher is + // more recent than the navigation, we want the newer data so abort the + // navigation and complete it with the fetcher data + if ( + state.navigation.state === "loading" && + loadId > pendingNavigationLoadId + ) { + invariant(pendingAction, "Expected pending action"); + pendingNavigationController && pendingNavigationController.abort(); + + completeNavigation(state.navigation.location, { + matches, + loaderData, + errors, + fetchers: new Map(state.fetchers), + }); + } else { + // otherwise just update with the fetcher data, preserving any existing + // loaderData for loaders that did not need to reload. We have to + // manually merge here since we aren't going through completeNavigation + updateState({ + errors, + loaderData: mergeLoaderData( + state.loaderData, + loaderData, + matches, + errors + ), + ...(didAbortFetchLoads ? { fetchers: new Map(state.fetchers) } : {}), + }); + isRevalidationRequired = false; + } + } + + // Call the matched loader for fetcher.load(), handling redirects, errors, etc. + async function handleFetcherLoader( + key: string, + routeId: string, + path: string, + match: AgnosticDataRouteMatch, + matches: AgnosticDataRouteMatch[], + submission?: Submission + ) { + let existingFetcher = state.fetchers.get(key); + // Put this fetcher into it's loading state + let loadingFetcher: FetcherStates["Loading"] = { + state: "loading", + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + ...submission, + data: existingFetcher && existingFetcher.data, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, loadingFetcher); + updateState({ fetchers: new Map(state.fetchers) }); + + // Call the loader for this fetcher route match + let abortController = new AbortController(); + let fetchRequest = createClientSideRequest( + init.history, + path, + abortController.signal + ); + fetchControllers.set(key, abortController); + + let result: DataResult = await callLoaderOrAction( + "loader", + fetchRequest, + match, + matches, + manifest, + detectErrorBoundary, + router.basename + ); + + // Deferred isn't supported for fetcher loads, await everything and treat it + // as a normal load. resolveDeferredData will return undefined if this + // fetcher gets aborted, so we just leave result untouched and short circuit + // below if that happens + if (isDeferredResult(result)) { + result = + (await resolveDeferredData(result, fetchRequest.signal, true)) || + result; + } + + // We can delete this so long as we weren't aborted by ou our own fetcher + // re-load which would have put _new_ controller is in fetchControllers + if (fetchControllers.get(key) === abortController) { + fetchControllers.delete(key); + } + + if (fetchRequest.signal.aborted) { + return; + } + + // If the loader threw a redirect Response, start a new REPLACE navigation + if (isRedirectResult(result)) { + await startRedirectNavigation(state, result); + return; + } + + // Process any non-redirect errors thrown + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + state.fetchers.delete(key); + // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch - + // do we need to behave any differently with our non-redirect errors? + // What if it was a non-redirect Response? + updateState({ + fetchers: new Map(state.fetchers), + errors: { + [boundaryMatch.route.id]: result.error, + }, + }); + return; + } + + invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); + + // Put the fetcher back into an idle state + let doneFetcher: FetcherStates["Idle"] = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, doneFetcher); + updateState({ fetchers: new Map(state.fetchers) }); + } + + /** + * Utility function to handle redirects returned from an action or loader. + * Normally, a redirect "replaces" the navigation that triggered it. So, for + * example: + * + * - user is on /a + * - user clicks a link to /b + * - loader for /b redirects to /c + * + * In a non-JS app the browser would track the in-flight navigation to /b and + * then replace it with /c when it encountered the redirect response. In + * the end it would only ever update the URL bar with /c. + * + * In client-side routing using pushState/replaceState, we aim to emulate + * this behavior and we also do not update history until the end of the + * navigation (including processed redirects). This means that we never + * actually touch history until we've processed redirects, so we just use + * the history action from the original navigation (PUSH or REPLACE). + */ + async function startRedirectNavigation( + state: RouterState, + redirect: RedirectResult, + { + submission, + replace, + isFetchActionRedirect, + }: { + submission?: Submission; + replace?: boolean; + isFetchActionRedirect?: boolean; + } = {} + ) { + if (redirect.revalidate) { + isRevalidationRequired = true; + } + + let redirectLocation = createLocation( + state.location, + redirect.location, + // TODO: This can be removed once we get rid of useTransition in Remix v2 + { + _isRedirect: true, + ...(isFetchActionRedirect ? { _isFetchActionRedirect: true } : {}), + } + ); + invariant( + redirectLocation, + "Expected a location on the redirect navigation" + ); + // Check if this an absolute external redirect that goes to a new origin + if ( + ABSOLUTE_URL_REGEX.test(redirect.location) && + isBrowser && + typeof window?.location !== "undefined" + ) { + let url = init.history.createURL(redirect.location); + let isDifferentBasename = + stripBasename(url.pathname, init.basename || "/") == null; + + if (window.location.origin !== url.origin || isDifferentBasename) { + if (replace) { + window.location.replace(redirect.location); + } else { + window.location.assign(redirect.location); + } + return; + } + } + + // There's no need to abort on redirects, since we don't detect the + // redirect until the action/loaders have settled + pendingNavigationController = null; + + let redirectHistoryAction = + replace === true ? HistoryAction.Replace : HistoryAction.Push; + + // Use the incoming submission if provided, fallback on the active one in + // state.navigation + let { formMethod, formAction, formEncType, formData } = state.navigation; + if (!submission && formMethod && formAction && formData && formEncType) { + submission = { + formMethod, + formAction, + formEncType, + formData, + }; + } + + // If this was a 307/308 submission we want to preserve the HTTP method and + // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the + // redirected location + if ( + redirectPreserveMethodStatusCodes.has(redirect.status) && + submission && + isMutationMethod(submission.formMethod) + ) { + await startNavigation(redirectHistoryAction, redirectLocation, { + submission: { + ...submission, + formAction: redirect.location, + }, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset, + }); + } else if (isFetchActionRedirect) { + // For a fetch action redirect, we kick off a new loading navigation + // without the fetcher submission, but we send it along for shouldRevalidate + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + }, + fetcherSubmission: submission, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset, + }); + } else { + // Otherwise, we kick off a new loading navigation, preserving the + // submission info for the duration of this navigation + await startNavigation(redirectHistoryAction, redirectLocation, { + overrideNavigation: { + state: "loading", + location: redirectLocation, + formMethod: submission ? submission.formMethod : undefined, + formAction: submission ? submission.formAction : undefined, + formEncType: submission ? submission.formEncType : undefined, + formData: submission ? submission.formData : undefined, + }, + // Preserve this flag across redirects + preventScrollReset: pendingPreventScrollReset, + }); + } + } + + async function callLoadersAndMaybeResolveData( + currentMatches: AgnosticDataRouteMatch[], + matches: AgnosticDataRouteMatch[], + matchesToLoad: AgnosticDataRouteMatch[], + fetchersToLoad: RevalidatingFetcher[], + request: Request + ) { + // Call all navigation loaders and revalidating fetcher loaders in parallel, + // then slice off the results into separate arrays so we can handle them + // accordingly + let results = await Promise.all([ + ...matchesToLoad.map((match) => + callLoaderOrAction( + "loader", + request, + match, + matches, + manifest, + detectErrorBoundary, + router.basename + ) + ), + ...fetchersToLoad.map((f) => { + if (f.matches && f.match) { + return callLoaderOrAction( + "loader", + createClientSideRequest(init.history, f.path, request.signal), + f.match, + f.matches, + manifest, + detectErrorBoundary, + router.basename + ); + } else { + let error: ErrorResult = { + type: ResultType.error, + error: getInternalRouterError(404, { pathname: f.path }), + }; + return error; + } + }), + ]); + let loaderResults = results.slice(0, matchesToLoad.length); + let fetcherResults = results.slice(matchesToLoad.length); + + await Promise.all([ + resolveDeferredResults( + currentMatches, + matchesToLoad, + loaderResults, + request.signal, + false, + state.loaderData + ), + resolveDeferredResults( + currentMatches, + fetchersToLoad.map((f) => f.match), + fetcherResults, + request.signal, + true + ), + ]); + + return { results, loaderResults, fetcherResults }; + } + + function interruptActiveLoads() { + // Every interruption triggers a revalidation + isRevalidationRequired = true; + + // Cancel pending route-level deferreds and mark cancelled routes for + // revalidation + cancelledDeferredRoutes.push(...cancelActiveDeferreds()); + + // Abort in-flight fetcher loads + fetchLoadMatches.forEach((_, key) => { + if (fetchControllers.has(key)) { + cancelledFetcherLoads.push(key); + abortFetcher(key); + } + }); + } + + function setFetcherError(key: string, routeId: string, error: any) { + let boundaryMatch = findNearestBoundary(state.matches, routeId); + deleteFetcher(key); + updateState({ + errors: { + [boundaryMatch.route.id]: error, + }, + fetchers: new Map(state.fetchers), + }); + } + + function deleteFetcher(key: string): void { + if (fetchControllers.has(key)) abortFetcher(key); + fetchLoadMatches.delete(key); + fetchReloadIds.delete(key); + fetchRedirectIds.delete(key); + state.fetchers.delete(key); + } + + function abortFetcher(key: string) { + let controller = fetchControllers.get(key); + invariant(controller, `Expected fetch controller: ${key}`); + controller.abort(); + fetchControllers.delete(key); + } + + function markFetchersDone(keys: string[]) { + for (let key of keys) { + let fetcher = getFetcher(key); + let doneFetcher: FetcherStates["Idle"] = { + state: "idle", + data: fetcher.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, doneFetcher); + } + } + + function markFetchRedirectsDone(): void { + let doneKeys = []; + for (let key of fetchRedirectIds) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, `Expected fetcher: ${key}`); + if (fetcher.state === "loading") { + fetchRedirectIds.delete(key); + doneKeys.push(key); + } + } + markFetchersDone(doneKeys); + } + + function abortStaleFetchLoads(landedId: number): boolean { + let yeetedKeys = []; + for (let [key, id] of fetchReloadIds) { + if (id < landedId) { + let fetcher = state.fetchers.get(key); + invariant(fetcher, `Expected fetcher: ${key}`); + if (fetcher.state === "loading") { + abortFetcher(key); + fetchReloadIds.delete(key); + yeetedKeys.push(key); + } + } + } + markFetchersDone(yeetedKeys); + return yeetedKeys.length > 0; + } + + function getBlocker(key: string, fn: BlockerFunction) { + let blocker: Blocker = state.blockers.get(key) || IDLE_BLOCKER; + + if (blockerFunctions.get(key) !== fn) { + blockerFunctions.set(key, fn); + } + + return blocker; + } + + function deleteBlocker(key: string) { + state.blockers.delete(key); + blockerFunctions.delete(key); + } + + // Utility function to update blockers, ensuring valid state transitions + function updateBlocker(key: string, newBlocker: Blocker) { + let blocker = state.blockers.get(key) || IDLE_BLOCKER; + + // Poor mans state machine :) + // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM + invariant( + (blocker.state === "unblocked" && newBlocker.state === "blocked") || + (blocker.state === "blocked" && newBlocker.state === "blocked") || + (blocker.state === "blocked" && newBlocker.state === "proceeding") || + (blocker.state === "blocked" && newBlocker.state === "unblocked") || + (blocker.state === "proceeding" && newBlocker.state === "unblocked"), + `Invalid blocker state transition: ${blocker.state} -> ${newBlocker.state}` + ); + + state.blockers.set(key, newBlocker); + updateState({ blockers: new Map(state.blockers) }); + } + + function shouldBlockNavigation({ + currentLocation, + nextLocation, + historyAction, + }: { + currentLocation: Location; + nextLocation: Location; + historyAction: HistoryAction; + }): string | undefined { + if (blockerFunctions.size === 0) { + return; + } + + // We ony support a single active blocker at the moment since we don't have + // any compelling use cases for multi-blocker yet + if (blockerFunctions.size > 1) { + warning(false, "A router only supports one blocker at a time"); + } + + let entries = Array.from(blockerFunctions.entries()); + let [blockerKey, blockerFunction] = entries[entries.length - 1]; + let blocker = state.blockers.get(blockerKey); + + if (blocker && blocker.state === "proceeding") { + // If the blocker is currently proceeding, we don't need to re-check + // it and can let this navigation continue + return; + } + + // At this point, we know we're unblocked/blocked so we need to check the + // user-provided blocker function + if (blockerFunction({ currentLocation, nextLocation, historyAction })) { + return blockerKey; + } + } + + function cancelActiveDeferreds( + predicate?: (routeId: string) => boolean + ): string[] { + let cancelledRouteIds: string[] = []; + activeDeferreds.forEach((dfd, routeId) => { + if (!predicate || predicate(routeId)) { + // Cancel the deferred - but do not remove from activeDeferreds here - + // we rely on the subscribers to do that so our tests can assert proper + // cleanup via _internalActiveDeferreds + dfd.cancel(); + cancelledRouteIds.push(routeId); + activeDeferreds.delete(routeId); + } + }); + return cancelledRouteIds; + } + + // Opt in to capturing and reporting scroll positions during navigations, + // used by the component + function enableScrollRestoration( + positions: Record, + getPosition: GetScrollPositionFunction, + getKey?: GetScrollRestorationKeyFunction + ) { + savedScrollPositions = positions; + getScrollPosition = getPosition; + getScrollRestorationKey = getKey || ((location) => location.key); + + // Perform initial hydration scroll restoration, since we miss the boat on + // the initial updateState() because we've not yet rendered + // and therefore have no savedScrollPositions available + if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) { + initialScrollRestored = true; + let y = getSavedScrollPosition(state.location, state.matches); + if (y != null) { + updateState({ restoreScrollPosition: y }); + } + } + + return () => { + savedScrollPositions = null; + getScrollPosition = null; + getScrollRestorationKey = null; + }; + } + + function saveScrollPosition( + location: Location, + matches: AgnosticDataRouteMatch[] + ): void { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map((m) => + createUseMatchesMatch(m, state.loaderData) + ); + let key = getScrollRestorationKey(location, userMatches) || location.key; + savedScrollPositions[key] = getScrollPosition(); + } + } + + function getSavedScrollPosition( + location: Location, + matches: AgnosticDataRouteMatch[] + ): number | null { + if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) { + let userMatches = matches.map((m) => + createUseMatchesMatch(m, state.loaderData) + ); + let key = getScrollRestorationKey(location, userMatches) || location.key; + let y = savedScrollPositions[key]; + if (typeof y === "number") { + return y; + } + } + return null; + } + + function _internalSetRoutes(newRoutes: AgnosticDataRouteObject[]) { + inFlightDataRoutes = newRoutes; + } + + router = { + get basename() { + return init.basename; + }, + get state() { + return state; + }, + get routes() { + return dataRoutes; + }, + initialize, + subscribe, + enableScrollRestoration, + navigate, + fetch, + revalidate, + // Passthrough to history-aware createHref used by useHref so we get proper + // hash-aware URLs in DOM paths + createHref: (to: To) => init.history.createHref(to), + encodeLocation: (to: To) => init.history.encodeLocation(to), + getFetcher, + deleteFetcher, + dispose, + getBlocker, + deleteBlocker, + _internalFetchControllers: fetchControllers, + _internalActiveDeferreds: activeDeferreds, + // TODO: Remove setRoutes, it's temporary to avoid dealing with + // updating the tree while validating the update algorithm. + _internalSetRoutes, + }; + + return router; +} +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region createStaticHandler +//////////////////////////////////////////////////////////////////////////////// + +export const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred"); + +export interface CreateStaticHandlerOptions { + basename?: string; + detectErrorBoundary?: DetectErrorBoundaryFunction; +} + +export function createStaticHandler( + routes: AgnosticRouteObject[], + opts?: CreateStaticHandlerOptions +): StaticHandler { + invariant( + routes.length > 0, + "You must provide a non-empty routes array to createStaticHandler" + ); + + let manifest: RouteManifest = {}; + let detectErrorBoundary = + opts?.detectErrorBoundary || defaultDetectErrorBoundary; + let dataRoutes = convertRoutesToDataRoutes( + routes, + detectErrorBoundary, + undefined, + manifest + ); + let basename = (opts ? opts.basename : null) || "/"; + + /** + * The query() method is intended for document requests, in which we want to + * call an optional action and potentially multiple loaders for all nested + * routes. It returns a StaticHandlerContext object, which is very similar + * to the router state (location, loaderData, actionData, errors, etc.) and + * also adds SSR-specific information such as the statusCode and headers + * from action/loaders Responses. + * + * It _should_ never throw and should report all errors through the + * returned context.errors object, properly associating errors to their error + * boundary. Additionally, it tracks _deepestRenderedBoundaryId which can be + * used to emulate React error boundaries during SSr by performing a second + * pass only down to the boundaryId. + * + * The one exception where we do not return a StaticHandlerContext is when a + * redirect response is returned or thrown from any action/loader. We + * propagate that out and return the raw Response so the HTTP server can + * return it directly. + */ + async function query( + request: Request, + { requestContext }: { requestContext?: unknown } = {} + ): Promise { + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); + + // SSR supports HEAD requests while SPA doesn't + if (!isValidMethod(method) && method !== "HEAD") { + let error = getInternalRouterError(405, { method }); + let { matches: methodNotAllowedMatches, route } = + getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: methodNotAllowedMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error, + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null, + }; + } else if (!matches) { + let error = getInternalRouterError(404, { pathname: location.pathname }); + let { matches: notFoundMatches, route } = + getShortCircuitMatches(dataRoutes); + return { + basename, + location, + matches: notFoundMatches, + loaderData: {}, + actionData: null, + errors: { + [route.id]: error, + }, + statusCode: error.status, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null, + }; + } + + let result = await queryImpl(request, location, matches, requestContext); + if (isResponse(result)) { + return result; + } + + // When returning StaticHandlerContext, we patch back in the location here + // since we need it for React Context. But this helps keep our submit and + // loadRouteData operating on a Request instead of a Location + return { location, basename, ...result }; + } + + /** + * The queryRoute() method is intended for targeted route requests, either + * for fetch ?_data requests or resource route requests. In this case, we + * are only ever calling a single action or loader, and we are returning the + * returned value directly. In most cases, this will be a Response returned + * from the action/loader, but it may be a primitive or other value as well - + * and in such cases the calling context should handle that accordingly. + * + * We do respect the throw/return differentiation, so if an action/loader + * throws, then this method will throw the value. This is important so we + * can do proper boundary identification in Remix where a thrown Response + * must go to the Catch Boundary but a returned Response is happy-path. + * + * One thing to note is that any Router-initiated Errors that make sense + * to associate with a status code will be thrown as an ErrorResponse + * instance which include the raw Error, such that the calling context can + * serialize the error as they see fit while including the proper response + * code. Examples here are 404 and 405 errors that occur prior to reaching + * any user-defined loaders. + */ + async function queryRoute( + request: Request, + { + routeId, + requestContext, + }: { requestContext?: unknown; routeId?: string } = {} + ): Promise { + let url = new URL(request.url); + let method = request.method; + let location = createLocation("", createPath(url), null, "default"); + let matches = matchRoutes(dataRoutes, location, basename); + + // SSR supports HEAD requests while SPA doesn't + if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") { + throw getInternalRouterError(405, { method }); + } else if (!matches) { + throw getInternalRouterError(404, { pathname: location.pathname }); + } + + let match = routeId + ? matches.find((m) => m.route.id === routeId) + : getTargetMatch(matches, location); + + if (routeId && !match) { + throw getInternalRouterError(403, { + pathname: location.pathname, + routeId, + }); + } else if (!match) { + // This should never hit I don't think? + throw getInternalRouterError(404, { pathname: location.pathname }); + } + + let result = await queryImpl( + request, + location, + matches, + requestContext, + match + ); + if (isResponse(result)) { + return result; + } + + let error = result.errors ? Object.values(result.errors)[0] : undefined; + if (error !== undefined) { + // If we got back result.errors, that means the loader/action threw + // _something_ that wasn't a Response, but it's not guaranteed/required + // to be an `instanceof Error` either, so we have to use throw here to + // preserve the "error" state outside of queryImpl. + throw error; + } + + // Pick off the right state value to return + if (result.actionData) { + return Object.values(result.actionData)[0]; + } + + if (result.loaderData) { + let data = Object.values(result.loaderData)[0]; + if (result.activeDeferreds?.[match.route.id]) { + data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id]; + } + return data; + } + + return undefined; + } + + async function queryImpl( + request: Request, + location: Location, + matches: AgnosticDataRouteMatch[], + requestContext: unknown, + routeMatch?: AgnosticDataRouteMatch + ): Promise | Response> { + invariant( + request.signal, + "query()/queryRoute() requests must contain an AbortController signal" + ); + + try { + if (isMutationMethod(request.method.toLowerCase())) { + let result = await submit( + request, + matches, + routeMatch || getTargetMatch(matches, location), + requestContext, + routeMatch != null + ); + return result; + } + + let result = await loadRouteData( + request, + matches, + requestContext, + routeMatch + ); + return isResponse(result) + ? result + : { + ...result, + actionData: null, + actionHeaders: {}, + }; + } catch (e) { + // If the user threw/returned a Response in callLoaderOrAction, we throw + // it to bail out and then return or throw here based on whether the user + // returned or threw + if (isQueryRouteResponse(e)) { + if (e.type === ResultType.error && !isRedirectResponse(e.response)) { + throw e.response; + } + return e.response; + } + // Redirects are always returned since they don't propagate to catch + // boundaries + if (isRedirectResponse(e)) { + return e; + } + throw e; + } + } + + async function submit( + request: Request, + matches: AgnosticDataRouteMatch[], + actionMatch: AgnosticDataRouteMatch, + requestContext: unknown, + isRouteRequest: boolean + ): Promise | Response> { + let result: DataResult; + + if (!actionMatch.route.action && !actionMatch.route.lazy) { + let error = getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: actionMatch.route.id, + }); + if (isRouteRequest) { + throw error; + } + result = { + type: ResultType.error, + error, + }; + } else { + result = await callLoaderOrAction( + "action", + request, + actionMatch, + matches, + manifest, + detectErrorBoundary, + basename, + true, + isRouteRequest, + requestContext + ); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(`${method}() call aborted`); + } + } + + if (isRedirectResult(result)) { + // Uhhhh - this should never happen, we should always throw these from + // callLoaderOrAction, but the type narrowing here keeps TS happy and we + // can get back on the "throw all redirect responses" train here should + // this ever happen :/ + throw new Response(null, { + status: result.status, + headers: { + Location: result.location, + }, + }); + } + + if (isDeferredResult(result)) { + let error = getInternalRouterError(400, { type: "defer-action" }); + if (isRouteRequest) { + throw error; + } + result = { + type: ResultType.error, + error, + }; + } + + if (isRouteRequest) { + // Note: This should only be non-Response values if we get here, since + // isRouteRequest should throw any Response received in callLoaderOrAction + if (isErrorResult(result)) { + throw result.error; + } + + return { + matches: [actionMatch], + loaderData: {}, + actionData: { [actionMatch.route.id]: result.data }, + errors: null, + // Note: statusCode + headers are unused here since queryRoute will + // return the raw Response or value + statusCode: 200, + loaderHeaders: {}, + actionHeaders: {}, + activeDeferreds: null, + }; + } + + if (isErrorResult(result)) { + // Store off the pending error - we use it to determine which loaders + // to call and will commit it when we complete the navigation + let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); + let context = await loadRouteData( + request, + matches, + requestContext, + undefined, + { + [boundaryMatch.route.id]: result.error, + } + ); + + // action status codes take precedence over loader status codes + return { + ...context, + statusCode: isRouteErrorResponse(result.error) + ? result.error.status + : 500, + actionData: null, + actionHeaders: { + ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}), + }, + }; + } + + // Create a GET request for the loaders + let loaderRequest = new Request(request.url, { + headers: request.headers, + redirect: request.redirect, + signal: request.signal, + }); + let context = await loadRouteData(loaderRequest, matches, requestContext); + + return { + ...context, + // action status codes take precedence over loader status codes + ...(result.statusCode ? { statusCode: result.statusCode } : {}), + actionData: { + [actionMatch.route.id]: result.data, + }, + actionHeaders: { + ...(result.headers ? { [actionMatch.route.id]: result.headers } : {}), + }, + }; + } + + async function loadRouteData( + request: Request, + matches: AgnosticDataRouteMatch[], + requestContext: unknown, + routeMatch?: AgnosticDataRouteMatch, + pendingActionError?: RouteData + ): Promise< + | Omit< + StaticHandlerContext, + "location" | "basename" | "actionData" | "actionHeaders" + > + | Response + > { + let isRouteRequest = routeMatch != null; + + // Short circuit if we have no loaders to run (queryRoute()) + if ( + isRouteRequest && + !routeMatch?.route.loader && + !routeMatch?.route.lazy + ) { + throw getInternalRouterError(400, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: routeMatch?.route.id, + }); + } + + let requestMatches = routeMatch + ? [routeMatch] + : getLoaderMatchesUntilBoundary( + matches, + Object.keys(pendingActionError || {})[0] + ); + let matchesToLoad = requestMatches.filter( + (m) => m.route.loader || m.route.lazy + ); + + // Short circuit if we have no loaders to run (query()) + if (matchesToLoad.length === 0) { + return { + matches, + // Add a null for all matched routes for proper revalidation on the client + loaderData: matches.reduce( + (acc, m) => Object.assign(acc, { [m.route.id]: null }), + {} + ), + errors: pendingActionError || null, + statusCode: 200, + loaderHeaders: {}, + activeDeferreds: null, + }; + } + + let results = await Promise.all([ + ...matchesToLoad.map((match) => + callLoaderOrAction( + "loader", + request, + match, + matches, + manifest, + detectErrorBoundary, + basename, + true, + isRouteRequest, + requestContext + ) + ), + ]); + + if (request.signal.aborted) { + let method = isRouteRequest ? "queryRoute" : "query"; + throw new Error(`${method}() call aborted`); + } + + // Process and commit output from loaders + let activeDeferreds = new Map(); + let context = processRouteLoaderData( + matches, + matchesToLoad, + results, + pendingActionError, + activeDeferreds + ); + + // Add a null for any non-loader matches for proper revalidation on the client + let executedLoaders = new Set( + matchesToLoad.map((match) => match.route.id) + ); + matches.forEach((match) => { + if (!executedLoaders.has(match.route.id)) { + context.loaderData[match.route.id] = null; + } + }); + + return { + ...context, + matches, + activeDeferreds: + activeDeferreds.size > 0 + ? Object.fromEntries(activeDeferreds.entries()) + : null, + }; + } + + return { + dataRoutes, + query, + queryRoute, + }; +} + +//#endregion + +//////////////////////////////////////////////////////////////////////////////// +//#region Helpers +//////////////////////////////////////////////////////////////////////////////// + +/** + * Given an existing StaticHandlerContext and an error thrown at render time, + * provide an updated StaticHandlerContext suitable for a second SSR render + */ +export function getStaticContextFromError( + routes: AgnosticDataRouteObject[], + context: StaticHandlerContext, + error: any +) { + let newContext: StaticHandlerContext = { + ...context, + statusCode: 500, + errors: { + [context._deepestRenderedBoundaryId || routes[0].id]: error, + }, + }; + return newContext; +} + +function isSubmissionNavigation( + opts: RouterNavigateOptions +): opts is SubmissionNavigateOptions { + return opts != null && "formData" in opts; +} + +// Normalize navigation options by converting formMethod=GET formData objects to +// URLSearchParams so they behave identically to links with query params +function normalizeNavigateOptions( + to: To, + future: FutureConfig, + opts?: RouterNavigateOptions, + isFetcher = false +): { + path: string; + submission?: Submission; + error?: ErrorResponse; +} { + let path = typeof to === "string" ? to : createPath(to); + + // Return location verbatim on non-submission navigations + if (!opts || !isSubmissionNavigation(opts)) { + return { path }; + } + + if (opts.formMethod && !isValidMethod(opts.formMethod)) { + return { + path, + error: getInternalRouterError(405, { method: opts.formMethod }), + }; + } + + // Create a Submission on non-GET navigations + let submission: Submission | undefined; + if (opts.formData) { + let formMethod = opts.formMethod || "get"; + submission = { + formMethod: future.v7_normalizeFormMethod + ? (formMethod.toUpperCase() as V7_FormMethod) + : (formMethod.toLowerCase() as FormMethod), + formAction: stripHashFromPath(path), + formEncType: + (opts && opts.formEncType) || "application/x-www-form-urlencoded", + formData: opts.formData, + }; + + if (isMutationMethod(submission.formMethod)) { + return { path, submission }; + } + } + + // Flatten submission onto URLSearchParams for GET submissions + let parsedPath = parsePath(path); + let searchParams = convertFormDataToSearchParams(opts.formData); + // Since fetcher GET submissions only run a single loader (as opposed to + // navigation GET submissions which run all loaders), we need to preserve + // any incoming ?index params + if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) { + searchParams.append("index", ""); + } + parsedPath.search = `?${searchParams}`; + + return { path: createPath(parsedPath), submission }; +} + +// Filter out all routes below any caught error as they aren't going to +// render so we don't need to load them +function getLoaderMatchesUntilBoundary( + matches: AgnosticDataRouteMatch[], + boundaryId?: string +) { + let boundaryMatches = matches; + if (boundaryId) { + let index = matches.findIndex((m) => m.route.id === boundaryId); + if (index >= 0) { + boundaryMatches = matches.slice(0, index); + } + } + return boundaryMatches; +} + +function getMatchesToLoad( + history: History, + state: RouterState, + matches: AgnosticDataRouteMatch[], + submission: Submission | undefined, + location: Location, + isRevalidationRequired: boolean, + cancelledDeferredRoutes: string[], + cancelledFetcherLoads: string[], + fetchLoadMatches: Map, + routesToUse: AgnosticDataRouteObject[], + basename: string | undefined, + pendingActionData?: RouteData, + pendingError?: RouteData +): [AgnosticDataRouteMatch[], RevalidatingFetcher[]] { + let actionResult = pendingError + ? Object.values(pendingError)[0] + : pendingActionData + ? Object.values(pendingActionData)[0] + : undefined; + + let currentUrl = history.createURL(state.location); + let nextUrl = history.createURL(location); + + let defaultShouldRevalidate = + // Forced revalidation due to submission, useRevalidate, or X-Remix-Revalidate + isRevalidationRequired || + // Clicked the same link, resubmitted a GET form + currentUrl.toString() === nextUrl.toString() || + // Search params affect all loaders + currentUrl.search !== nextUrl.search; + + // Pick navigation matches that are net-new or qualify for revalidation + let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined; + let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId); + + let navigationMatches = boundaryMatches.filter((match, index) => { + if (match.route.lazy) { + // We haven't loaded this route yet so we don't know if it's got a loader! + return true; + } + if (match.route.loader == null) { + return false; + } + + // Always call the loader on new route instances and pending defer cancellations + if ( + isNewLoader(state.loaderData, state.matches[index], match) || + cancelledDeferredRoutes.some((id) => id === match.route.id) + ) { + return true; + } + + // This is the default implementation for when we revalidate. If the route + // provides it's own implementation, then we give them full control but + // provide this value so they can leverage it if needed after they check + // their own specific use cases + let currentRouteMatch = state.matches[index]; + let nextRouteMatch = match; + + return shouldRevalidateLoader(match, { + currentUrl, + currentParams: currentRouteMatch.params, + nextUrl, + nextParams: nextRouteMatch.params, + ...submission, + actionResult, + defaultShouldRevalidate: + defaultShouldRevalidate || + isNewRouteInstance(currentRouteMatch, nextRouteMatch), + }); + }); + + // Pick fetcher.loads that need to be revalidated + let revalidatingFetchers: RevalidatingFetcher[] = []; + fetchLoadMatches.forEach((f, key) => { + // Don't revalidate if fetcher won't be present in the subsequent render + if (!matches.some((m) => m.route.id === f.routeId)) { + return; + } + + let fetcherMatches = matchRoutes(routesToUse, f.path, basename); + + // If the fetcher path no longer matches, push it in with null matches so + // we can trigger a 404 in callLoadersAndMaybeResolveData + if (!fetcherMatches) { + revalidatingFetchers.push({ key, ...f, matches: null, match: null }); + return; + } + + let fetcherMatch = getTargetMatch(fetcherMatches, f.path); + + if (cancelledFetcherLoads.includes(key)) { + revalidatingFetchers.push({ + key, + matches: fetcherMatches, + match: fetcherMatch, + ...f, + }); + return; + } + + // Revalidating fetchers are decoupled from the route matches since they + // hit a static href, so they _always_ check shouldRevalidate and the + // default is strictly if a revalidation is explicitly required (action + // submissions, useRevalidator, X-Remix-Revalidate). + let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, { + currentUrl, + currentParams: state.matches[state.matches.length - 1].params, + nextUrl, + nextParams: matches[matches.length - 1].params, + ...submission, + actionResult, + defaultShouldRevalidate, + }); + if (shouldRevalidate) { + revalidatingFetchers.push({ + key, + matches: fetcherMatches, + match: fetcherMatch, + ...f, + }); + } + }); + + return [navigationMatches, revalidatingFetchers]; +} + +function isNewLoader( + currentLoaderData: RouteData, + currentMatch: AgnosticDataRouteMatch, + match: AgnosticDataRouteMatch +) { + let isNew = + // [a] -> [a, b] + !currentMatch || + // [a, b] -> [a, c] + match.route.id !== currentMatch.route.id; + + // Handle the case that we don't have data for a re-used route, potentially + // from a prior error or from a cancelled pending deferred + let isMissingData = currentLoaderData[match.route.id] === undefined; + + // Always load if this is a net-new route or we don't yet have data + return isNew || isMissingData; +} + +function isNewRouteInstance( + currentMatch: AgnosticDataRouteMatch, + match: AgnosticDataRouteMatch +) { + let currentPath = currentMatch.route.path; + return ( + // param change for this match, /users/123 -> /users/456 + currentMatch.pathname !== match.pathname || + // splat param changed, which is not present in match.path + // e.g. /files/images/avatar.jpg -> files/finances.xls + (currentPath != null && + currentPath.endsWith("*") && + currentMatch.params["*"] !== match.params["*"]) + ); +} + +function shouldRevalidateLoader( + loaderMatch: AgnosticDataRouteMatch, + arg: Parameters[0] +) { + if (loaderMatch.route.shouldRevalidate) { + let routeChoice = loaderMatch.route.shouldRevalidate(arg); + if (typeof routeChoice === "boolean") { + return routeChoice; + } + } + + return arg.defaultShouldRevalidate; +} + +/** + * Execute route.lazy() methods to lazily load route modules (loader, action, + * shouldRevalidate) and update the routeManifest in place which shares objects + * with dataRoutes so those get updated as well. + */ +async function loadLazyRouteModule( + route: AgnosticDataRouteObject, + detectErrorBoundary: DetectErrorBoundaryFunction, + manifest: RouteManifest +) { + if (!route.lazy) { + return; + } + + let lazyRoute = await route.lazy(); + + // If the lazy route function was executed and removed by another parallel + // call then we can return - first lazy() to finish wins because the return + // value of lazy is expected to be static + if (!route.lazy) { + return; + } + + let routeToUpdate = manifest[route.id]; + invariant(routeToUpdate, "No route found in manifest"); + + // Update the route in place. This should be safe because there's no way + // we could yet be sitting on this route as we can't get there without + // resolving lazy() first. + // + // This is different than the HMR "update" use-case where we may actively be + // on the route being updated. The main concern boils down to "does this + // mutation affect any ongoing navigations or any current state.matches + // values?". If not, it should be safe to update in place. + let routeUpdates: Record = {}; + for (let lazyRouteProperty in lazyRoute) { + let staticRouteValue = + routeToUpdate[lazyRouteProperty as keyof typeof routeToUpdate]; + + let isPropertyStaticallyDefined = + staticRouteValue !== undefined && + // This property isn't static since it should always be updated based + // on the route updates + lazyRouteProperty !== "hasErrorBoundary"; + + warning( + !isPropertyStaticallyDefined, + `Route "${routeToUpdate.id}" has a static property "${lazyRouteProperty}" ` + + `defined but its lazy function is also returning a value for this property. ` + + `The lazy route property "${lazyRouteProperty}" will be ignored.` + ); + + if ( + !isPropertyStaticallyDefined && + !immutableRouteKeys.has(lazyRouteProperty as ImmutableRouteKey) + ) { + routeUpdates[lazyRouteProperty] = + lazyRoute[lazyRouteProperty as keyof typeof lazyRoute]; + } + } + + // Mutate the route with the provided updates. Do this first so we pass + // the updated version to detectErrorBoundary + Object.assign(routeToUpdate, routeUpdates); + + // Mutate the `hasErrorBoundary` property on the route based on the route + // updates and remove the `lazy` function so we don't resolve the lazy + // route again. + Object.assign(routeToUpdate, { + // To keep things framework agnostic, we use the provided + // `detectErrorBoundary` function to set the `hasErrorBoundary` route + // property since the logic will differ between frameworks. + hasErrorBoundary: detectErrorBoundary({ ...routeToUpdate }), + lazy: undefined, + }); +} + +async function callLoaderOrAction( + type: "loader" | "action", + request: Request, + match: AgnosticDataRouteMatch, + matches: AgnosticDataRouteMatch[], + manifest: RouteManifest, + detectErrorBoundary: DetectErrorBoundaryFunction, + basename = "/", + isStaticRequest: boolean = false, + isRouteRequest: boolean = false, + requestContext?: unknown +): Promise { + let resultType; + let result; + let onReject: (() => void) | undefined; + + let runHandler = (handler: ActionFunction | LoaderFunction) => { + // Setup a promise we can race against so that abort signals short circuit + let reject: () => void; + let abortPromise = new Promise((_, r) => (reject = r)); + onReject = () => reject(); + request.signal.addEventListener("abort", onReject); + return Promise.race([ + handler({ request, params: match.params, context: requestContext }), + abortPromise, + ]); + }; + + try { + let handler = match.route[type]; + + if (match.route.lazy) { + if (handler) { + // Run statically defined handler in parallel with lazy() + let values = await Promise.all([ + runHandler(handler), + loadLazyRouteModule(match.route, detectErrorBoundary, manifest), + ]); + result = values[0]; + } else { + // Load lazy route module, then run any returned handler + await loadLazyRouteModule(match.route, detectErrorBoundary, manifest); + + handler = match.route[type]; + if (handler) { + // Handler still run even if we got interrupted to maintain consistency + // with un-abortable behavior of handler execution on non-lazy or + // previously-lazy-loaded routes + result = await runHandler(handler); + } else if (type === "action") { + throw getInternalRouterError(405, { + method: request.method, + pathname: new URL(request.url).pathname, + routeId: match.route.id, + }); + } else { + // lazy() route has no loader to run. Short circuit here so we don't + // hit the invariant below that errors on returning undefined. + return { type: ResultType.data, data: undefined }; + } + } + } else { + invariant( + handler, + `Could not find the ${type} to run on the "${match.route.id}" route` + ); + + result = await runHandler(handler); + } + + invariant( + result !== undefined, + `You defined ${type === "action" ? "an action" : "a loader"} for route ` + + `"${match.route.id}" but didn't return anything from your \`${type}\` ` + + `function. Please return a value or \`null\`.` + ); + } catch (e) { + resultType = ResultType.error; + result = e; + } finally { + if (onReject) { + request.signal.removeEventListener("abort", onReject); + } + } + + if (isResponse(result)) { + let status = result.status; + + // Process redirects + if (redirectStatusCodes.has(status)) { + let location = result.headers.get("Location"); + invariant( + location, + "Redirects returned/thrown from loaders/actions must have a Location header" + ); + + // Support relative routing in internal redirects + if (!ABSOLUTE_URL_REGEX.test(location)) { + let activeMatches = matches.slice(0, matches.indexOf(match) + 1); + let routePathnames = getPathContributingMatches(activeMatches).map( + (match) => match.pathnameBase + ); + let resolvedLocation = resolveTo( + location, + routePathnames, + new URL(request.url).pathname + ); + invariant( + createPath(resolvedLocation), + `Unable to resolve redirect location: ${location}` + ); + + // Prepend the basename to the redirect location if we have one + if (basename) { + let path = resolvedLocation.pathname; + resolvedLocation.pathname = + path === "/" ? basename : joinPaths([basename, path]); + } + + location = createPath(resolvedLocation); + } else if (!isStaticRequest) { + // Strip off the protocol+origin for same-origin + same-basename absolute + // redirects. If this is a static request, we can let it go back to the + // browser as-is + let currentUrl = new URL(request.url); + let url = location.startsWith("//") + ? new URL(currentUrl.protocol + location) + : new URL(location); + let isSameBasename = stripBasename(url.pathname, basename) != null; + if (url.origin === currentUrl.origin && isSameBasename) { + location = url.pathname + url.search + url.hash; + } + } + + // Don't process redirects in the router during static requests requests. + // Instead, throw the Response and let the server handle it with an HTTP + // redirect. We also update the Location header in place in this flow so + // basename and relative routing is taken into account + if (isStaticRequest) { + result.headers.set("Location", location); + throw result; + } + + return { + type: ResultType.redirect, + status, + location, + revalidate: result.headers.get("X-Remix-Revalidate") !== null, + }; + } + + // For SSR single-route requests, we want to hand Responses back directly + // without unwrapping. We do this with the QueryRouteResponse wrapper + // interface so we can know whether it was returned or thrown + if (isRouteRequest) { + // eslint-disable-next-line no-throw-literal + throw { + type: resultType || ResultType.data, + response: result, + }; + } + + let data: any; + let contentType = result.headers.get("Content-Type"); + // Check between word boundaries instead of startsWith() due to the last + // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type + if (contentType && /\bapplication\/json\b/.test(contentType)) { + data = await result.json(); + } else { + data = await result.text(); + } + + if (resultType === ResultType.error) { + return { + type: resultType, + error: new ErrorResponse(status, result.statusText, data), + headers: result.headers, + }; + } + + return { + type: ResultType.data, + data, + statusCode: result.status, + headers: result.headers, + }; + } + + if (resultType === ResultType.error) { + return { type: resultType, error: result }; + } + + if (isDeferredData(result)) { + return { + type: ResultType.deferred, + deferredData: result, + statusCode: result.init?.status, + headers: result.init?.headers && new Headers(result.init.headers), + }; + } + + return { type: ResultType.data, data: result }; +} + +// Utility method for creating the Request instances for loaders/actions during +// client-side navigations and fetches. During SSR we will always have a +// Request instance from the static handler (query/queryRoute) +function createClientSideRequest( + history: History, + location: string | Location, + signal: AbortSignal, + submission?: Submission +): Request { + let url = history.createURL(stripHashFromPath(location)).toString(); + let init: RequestInit = { signal }; + + if (submission && isMutationMethod(submission.formMethod)) { + let { formMethod, formEncType, formData } = submission; + // Didn't think we needed this but it turns out unlike other methods, patch + // won't be properly normalized to uppercase and results in a 405 error. + // See: https://fetch.spec.whatwg.org/#concept-method + init.method = formMethod.toUpperCase(); + init.body = + formEncType === "application/x-www-form-urlencoded" + ? convertFormDataToSearchParams(formData) + : formData; + } + + // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request) + return new Request(url, init); +} + +function convertFormDataToSearchParams(formData: FormData): URLSearchParams { + let searchParams = new URLSearchParams(); + + for (let [key, value] of formData.entries()) { + // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs + searchParams.append(key, value instanceof File ? value.name : value); + } + + return searchParams; +} + +function processRouteLoaderData( + matches: AgnosticDataRouteMatch[], + matchesToLoad: AgnosticDataRouteMatch[], + results: DataResult[], + pendingError: RouteData | undefined, + activeDeferreds: Map +): { + loaderData: RouterState["loaderData"]; + errors: RouterState["errors"] | null; + statusCode: number; + loaderHeaders: Record; +} { + // Fill in loaderData/errors from our loaders + let loaderData: RouterState["loaderData"] = {}; + let errors: RouterState["errors"] | null = null; + let statusCode: number | undefined; + let foundError = false; + let loaderHeaders: Record = {}; + + // Process loader results into state.loaderData/state.errors + results.forEach((result, index) => { + let id = matchesToLoad[index].route.id; + invariant( + !isRedirectResult(result), + "Cannot handle redirect results in processLoaderData" + ); + if (isErrorResult(result)) { + // Look upwards from the matched route for the closest ancestor + // error boundary, defaulting to the root match + let boundaryMatch = findNearestBoundary(matches, id); + let error = result.error; + // If we have a pending action error, we report it at the highest-route + // that throws a loader error, and then clear it out to indicate that + // it was consumed + if (pendingError) { + error = Object.values(pendingError)[0]; + pendingError = undefined; + } + + errors = errors || {}; + + // Prefer higher error values if lower errors bubble to the same boundary + if (errors[boundaryMatch.route.id] == null) { + errors[boundaryMatch.route.id] = error; + } + + // Clear our any prior loaderData for the throwing route + loaderData[id] = undefined; + + // Once we find our first (highest) error, we set the status code and + // prevent deeper status codes from overriding + if (!foundError) { + foundError = true; + statusCode = isRouteErrorResponse(result.error) + ? result.error.status + : 500; + } + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } else { + if (isDeferredResult(result)) { + activeDeferreds.set(id, result.deferredData); + loaderData[id] = result.deferredData.data; + } else { + loaderData[id] = result.data; + } + + // Error status codes always override success status codes, but if all + // loaders are successful we take the deepest status code. + if ( + result.statusCode != null && + result.statusCode !== 200 && + !foundError + ) { + statusCode = result.statusCode; + } + if (result.headers) { + loaderHeaders[id] = result.headers; + } + } + }); + + // If we didn't consume the pending action error (i.e., all loaders + // resolved), then consume it here. Also clear out any loaderData for the + // throwing route + if (pendingError) { + errors = pendingError; + loaderData[Object.keys(pendingError)[0]] = undefined; + } + + return { + loaderData, + errors, + statusCode: statusCode || 200, + loaderHeaders, + }; +} + +function processLoaderData( + state: RouterState, + matches: AgnosticDataRouteMatch[], + matchesToLoad: AgnosticDataRouteMatch[], + results: DataResult[], + pendingError: RouteData | undefined, + revalidatingFetchers: RevalidatingFetcher[], + fetcherResults: DataResult[], + activeDeferreds: Map +): { + loaderData: RouterState["loaderData"]; + errors?: RouterState["errors"]; +} { + let { loaderData, errors } = processRouteLoaderData( + matches, + matchesToLoad, + results, + pendingError, + activeDeferreds + ); + + // Process results from our revalidating fetchers + for (let index = 0; index < revalidatingFetchers.length; index++) { + let { key, match } = revalidatingFetchers[index]; + invariant( + fetcherResults !== undefined && fetcherResults[index] !== undefined, + "Did not find corresponding fetcher result" + ); + let result = fetcherResults[index]; + + // Process fetcher non-redirect errors + if (isErrorResult(result)) { + let boundaryMatch = findNearestBoundary(state.matches, match?.route.id); + if (!(errors && errors[boundaryMatch.route.id])) { + errors = { + ...errors, + [boundaryMatch.route.id]: result.error, + }; + } + state.fetchers.delete(key); + } else if (isRedirectResult(result)) { + // Should never get here, redirects should get processed above, but we + // keep this to type narrow to a success result in the else + invariant(false, "Unhandled fetcher revalidation redirect"); + } else if (isDeferredResult(result)) { + // Should never get here, deferred data should be awaited for fetchers + // in resolveDeferredResults + invariant(false, "Unhandled fetcher deferred data"); + } else { + let doneFetcher: FetcherStates["Idle"] = { + state: "idle", + data: result.data, + formMethod: undefined, + formAction: undefined, + formEncType: undefined, + formData: undefined, + " _hasFetcherDoneAnything ": true, + }; + state.fetchers.set(key, doneFetcher); + } + } + + return { loaderData, errors }; +} + +function mergeLoaderData( + loaderData: RouteData, + newLoaderData: RouteData, + matches: AgnosticDataRouteMatch[], + errors: RouteData | null | undefined +): RouteData { + let mergedLoaderData = { ...newLoaderData }; + for (let match of matches) { + let id = match.route.id; + if (newLoaderData.hasOwnProperty(id)) { + if (newLoaderData[id] !== undefined) { + mergedLoaderData[id] = newLoaderData[id]; + } else { + // No-op - this is so we ignore existing data if we have a key in the + // incoming object with an undefined value, which is how we unset a prior + // loaderData if we encounter a loader error + } + } else if (loaderData[id] !== undefined && match.route.loader) { + // Preserve existing keys not included in newLoaderData and where a loader + // wasn't removed by HMR + mergedLoaderData[id] = loaderData[id]; + } + + if (errors && errors.hasOwnProperty(id)) { + // Don't keep any loader data below the boundary + break; + } + } + return mergedLoaderData; +} + +// Find the nearest error boundary, looking upwards from the leaf route (or the +// route specified by routeId) for the closest ancestor error boundary, +// defaulting to the root match +function findNearestBoundary( + matches: AgnosticDataRouteMatch[], + routeId?: string +): AgnosticDataRouteMatch { + let eligibleMatches = routeId + ? matches.slice(0, matches.findIndex((m) => m.route.id === routeId) + 1) + : [...matches]; + return ( + eligibleMatches.reverse().find((m) => m.route.hasErrorBoundary === true) || + matches[0] + ); +} + +function getShortCircuitMatches(routes: AgnosticDataRouteObject[]): { + matches: AgnosticDataRouteMatch[]; + route: AgnosticDataRouteObject; +} { + // Prefer a root layout route if present, otherwise shim in a route object + let route = routes.find((r) => r.index || !r.path || r.path === "/") || { + id: `__shim-error-route__`, + }; + + return { + matches: [ + { + params: {}, + pathname: "", + pathnameBase: "", + route, + }, + ], + route, + }; +} + +function getInternalRouterError( + status: number, + { + pathname, + routeId, + method, + type, + }: { + pathname?: string; + routeId?: string; + method?: string; + type?: "defer-action"; + } = {} +) { + let statusText = "Unknown Server Error"; + let errorMessage = "Unknown @remix-run/router error"; + + if (status === 400) { + statusText = "Bad Request"; + if (method && pathname && routeId) { + errorMessage = + `You made a ${method} request to "${pathname}" but ` + + `did not provide a \`loader\` for route "${routeId}", ` + + `so there is no way to handle the request.`; + } else if (type === "defer-action") { + errorMessage = "defer() is not supported in actions"; + } + } else if (status === 403) { + statusText = "Forbidden"; + errorMessage = `Route "${routeId}" does not match URL "${pathname}"`; + } else if (status === 404) { + statusText = "Not Found"; + errorMessage = `No route matches URL "${pathname}"`; + } else if (status === 405) { + statusText = "Method Not Allowed"; + if (method && pathname && routeId) { + errorMessage = + `You made a ${method.toUpperCase()} request to "${pathname}" but ` + + `did not provide an \`action\` for route "${routeId}", ` + + `so there is no way to handle the request.`; + } else if (method) { + errorMessage = `Invalid request method "${method.toUpperCase()}"`; + } + } + + return new ErrorResponse( + status || 500, + statusText, + new Error(errorMessage), + true + ); +} + +// Find any returned redirect errors, starting from the lowest match +function findRedirect(results: DataResult[]): RedirectResult | undefined { + for (let i = results.length - 1; i >= 0; i--) { + let result = results[i]; + if (isRedirectResult(result)) { + return result; + } + } +} + +function stripHashFromPath(path: To) { + let parsedPath = typeof path === "string" ? parsePath(path) : path; + return createPath({ ...parsedPath, hash: "" }); +} + +function isHashChangeOnly(a: Location, b: Location): boolean { + return ( + a.pathname === b.pathname && a.search === b.search && a.hash !== b.hash + ); +} + +function isDeferredResult(result: DataResult): result is DeferredResult { + return result.type === ResultType.deferred; +} + +function isErrorResult(result: DataResult): result is ErrorResult { + return result.type === ResultType.error; +} + +function isRedirectResult(result?: DataResult): result is RedirectResult { + return (result && result.type) === ResultType.redirect; +} + +export function isDeferredData(value: any): value is DeferredData { + let deferred: DeferredData = value; + return ( + deferred && + typeof deferred === "object" && + typeof deferred.data === "object" && + typeof deferred.subscribe === "function" && + typeof deferred.cancel === "function" && + typeof deferred.resolveData === "function" + ); +} + +function isResponse(value: any): value is Response { + return ( + value != null && + typeof value.status === "number" && + typeof value.statusText === "string" && + typeof value.headers === "object" && + typeof value.body !== "undefined" + ); +} + +function isRedirectResponse(result: any): result is Response { + if (!isResponse(result)) { + return false; + } + + let status = result.status; + let location = result.headers.get("Location"); + return status >= 300 && status <= 399 && location != null; +} + +function isQueryRouteResponse(obj: any): obj is QueryRouteResponse { + return ( + obj && + isResponse(obj.response) && + (obj.type === ResultType.data || ResultType.error) + ); +} + +function isValidMethod(method: string): method is FormMethod | V7_FormMethod { + return validRequestMethods.has(method.toLowerCase() as FormMethod); +} + +function isMutationMethod( + method: string +): method is MutationFormMethod | V7_MutationFormMethod { + return validMutationMethods.has(method.toLowerCase() as MutationFormMethod); +} + +async function resolveDeferredResults( + currentMatches: AgnosticDataRouteMatch[], + matchesToLoad: (AgnosticDataRouteMatch | null)[], + results: DataResult[], + signal: AbortSignal, + isFetcher: boolean, + currentLoaderData?: RouteData +) { + for (let index = 0; index < results.length; index++) { + let result = results[index]; + let match = matchesToLoad[index]; + // If we don't have a match, then we can have a deferred result to do + // anything with. This is for revalidating fetchers where the route was + // removed during HMR + if (!match) { + continue; + } + + let currentMatch = currentMatches.find( + (m) => m.route.id === match!.route.id + ); + let isRevalidatingLoader = + currentMatch != null && + !isNewRouteInstance(currentMatch, match) && + (currentLoaderData && currentLoaderData[match.route.id]) !== undefined; + + if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) { + // Note: we do not have to touch activeDeferreds here since we race them + // against the signal in resolveDeferredData and they'll get aborted + // there if needed + await resolveDeferredData(result, signal, isFetcher).then((result) => { + if (result) { + results[index] = result || results[index]; + } + }); + } + } +} + +async function resolveDeferredData( + result: DeferredResult, + signal: AbortSignal, + unwrap = false +): Promise { + let aborted = await result.deferredData.resolveData(signal); + if (aborted) { + return; + } + + if (unwrap) { + try { + return { + type: ResultType.data, + data: result.deferredData.unwrappedData, + }; + } catch (e) { + // Handle any TrackedPromise._error values encountered while unwrapping + return { + type: ResultType.error, + error: e, + }; + } + } + + return { + type: ResultType.data, + data: result.deferredData.data, + }; +} + +function hasNakedIndexQuery(search: string): boolean { + return new URLSearchParams(search).getAll("index").some((v) => v === ""); +} + +// Note: This should match the format exported by useMatches, so if you change +// this please also change that :) Eventually we'll DRY this up +function createUseMatchesMatch( + match: AgnosticDataRouteMatch, + loaderData: RouteData +): UseMatchesMatch { + let { route, pathname, params } = match; + return { + id: route.id, + pathname, + params, + data: loaderData[route.id] as unknown, + handle: route.handle as unknown, + }; +} + +function getTargetMatch( + matches: AgnosticDataRouteMatch[], + location: Location | string +) { + let search = + typeof location === "string" ? parsePath(location).search : location.search; + if ( + matches[matches.length - 1].route.index && + hasNakedIndexQuery(search || "") + ) { + // Return the leaf index route when index is present + return matches[matches.length - 1]; + } + // Otherwise grab the deepest "path contributing" match (ignoring index and + // pathless layout routes) + let pathMatches = getPathContributingMatches(matches); + return pathMatches[pathMatches.length - 1]; +} +//#endregion diff --git a/node_modules/@remix-run/router/utils.ts b/node_modules/@remix-run/router/utils.ts new file mode 100644 index 00000000..4851168d --- /dev/null +++ b/node_modules/@remix-run/router/utils.ts @@ -0,0 +1,1466 @@ +import type { Location, Path, To } from "./history"; +import { warning, invariant, parsePath } from "./history"; + +/** + * Map of routeId -> data returned from a loader/action/error + */ +export interface RouteData { + [routeId: string]: any; +} + +export enum ResultType { + data = "data", + deferred = "deferred", + redirect = "redirect", + error = "error", +} + +/** + * Successful result from a loader or action + */ +export interface SuccessResult { + type: ResultType.data; + data: any; + statusCode?: number; + headers?: Headers; +} + +/** + * Successful defer() result from a loader or action + */ +export interface DeferredResult { + type: ResultType.deferred; + deferredData: DeferredData; + statusCode?: number; + headers?: Headers; +} + +/** + * Redirect result from a loader or action + */ +export interface RedirectResult { + type: ResultType.redirect; + status: number; + location: string; + revalidate: boolean; +} + +/** + * Unsuccessful result from a loader or action + */ +export interface ErrorResult { + type: ResultType.error; + error: any; + headers?: Headers; +} + +/** + * Result from a loader or action - potentially successful or unsuccessful + */ +export type DataResult = + | SuccessResult + | DeferredResult + | RedirectResult + | ErrorResult; + +type LowerCaseFormMethod = "get" | "post" | "put" | "patch" | "delete"; +type UpperCaseFormMethod = Uppercase; + +/** + * Users can specify either lowercase or uppercase form methods on , + * useSubmit(), , etc. + */ +export type HTMLFormMethod = LowerCaseFormMethod | UpperCaseFormMethod; + +/** + * Active navigation/fetcher form methods are exposed in lowercase on the + * RouterState + */ +export type FormMethod = LowerCaseFormMethod; +export type MutationFormMethod = Exclude; + +/** + * In v7, active navigation/fetcher form methods are exposed in uppercase on the + * RouterState. This is to align with the normalization done via fetch(). + */ +export type V7_FormMethod = UpperCaseFormMethod; +export type V7_MutationFormMethod = Exclude; + +export type FormEncType = + | "application/x-www-form-urlencoded" + | "multipart/form-data"; + +/** + * @private + * Internal interface to pass around for action submissions, not intended for + * external consumption + */ +export interface Submission { + formMethod: FormMethod | V7_FormMethod; + formAction: string; + formEncType: FormEncType; + formData: FormData; +} + +/** + * @private + * Arguments passed to route loader/action functions. Same for now but we keep + * this as a private implementation detail in case they diverge in the future. + */ +interface DataFunctionArgs { + request: Request; + params: Params; + context?: any; +} + +/** + * Arguments passed to loader functions + */ +export interface LoaderFunctionArgs extends DataFunctionArgs {} + +/** + * Arguments passed to action functions + */ +export interface ActionFunctionArgs extends DataFunctionArgs {} + +/** + * Route loader function signature + */ +export interface LoaderFunction { + (args: LoaderFunctionArgs): Promise | Response | Promise | any; +} + +/** + * Route action function signature + */ +export interface ActionFunction { + (args: ActionFunctionArgs): Promise | Response | Promise | any; +} + +/** + * Route shouldRevalidate function signature. This runs after any submission + * (navigation or fetcher), so we flatten the navigation/fetcher submission + * onto the arguments. It shouldn't matter whether it came from a navigation + * or a fetcher, what really matters is the URLs and the formData since loaders + * have to re-run based on the data models that were potentially mutated. + */ +export interface ShouldRevalidateFunction { + (args: { + currentUrl: URL; + currentParams: AgnosticDataRouteMatch["params"]; + nextUrl: URL; + nextParams: AgnosticDataRouteMatch["params"]; + formMethod?: Submission["formMethod"]; + formAction?: Submission["formAction"]; + formEncType?: Submission["formEncType"]; + formData?: Submission["formData"]; + actionResult?: DataResult; + defaultShouldRevalidate: boolean; + }): boolean; +} + +/** + * Function provided by the framework-aware layers to set `hasErrorBoundary` + * from the framework-aware `errorElement` prop + */ +export interface DetectErrorBoundaryFunction { + (route: AgnosticRouteObject): boolean; +} + +/** + * Keys we cannot change from within a lazy() function. We spread all other keys + * onto the route. Either they're meaningful to the router, or they'll get + * ignored. + */ +export type ImmutableRouteKey = + | "lazy" + | "caseSensitive" + | "path" + | "id" + | "index" + | "children"; + +export const immutableRouteKeys = new Set([ + "lazy", + "caseSensitive", + "path", + "id", + "index", + "children", +]); + +/** + * lazy() function to load a route definition, which can add non-matching + * related properties to a route + */ +export interface LazyRouteFunction { + (): Promise>; +} + +/** + * Base RouteObject with common props shared by all types of routes + */ +type AgnosticBaseRouteObject = { + caseSensitive?: boolean; + path?: string; + id?: string; + loader?: LoaderFunction; + action?: ActionFunction; + hasErrorBoundary?: boolean; + shouldRevalidate?: ShouldRevalidateFunction; + handle?: any; + lazy?: LazyRouteFunction; +}; + +/** + * Index routes must not have children + */ +export type AgnosticIndexRouteObject = AgnosticBaseRouteObject & { + children?: undefined; + index: true; +}; + +/** + * Non-index routes may have children, but cannot have index + */ +export type AgnosticNonIndexRouteObject = AgnosticBaseRouteObject & { + children?: AgnosticRouteObject[]; + index?: false; +}; + +/** + * A route object represents a logical route, with (optionally) its child + * routes organized in a tree-like structure. + */ +export type AgnosticRouteObject = + | AgnosticIndexRouteObject + | AgnosticNonIndexRouteObject; + +export type AgnosticDataIndexRouteObject = AgnosticIndexRouteObject & { + id: string; +}; + +export type AgnosticDataNonIndexRouteObject = AgnosticNonIndexRouteObject & { + children?: AgnosticDataRouteObject[]; + id: string; +}; + +/** + * A data route object, which is just a RouteObject with a required unique ID + */ +export type AgnosticDataRouteObject = + | AgnosticDataIndexRouteObject + | AgnosticDataNonIndexRouteObject; + +export type RouteManifest = Record; + +// Recursive helper for finding path parameters in the absence of wildcards +type _PathParam = + // split path into individual path segments + Path extends `${infer L}/${infer R}` + ? _PathParam | _PathParam + : // find params after `:` + Path extends `:${infer Param}` + ? Param extends `${infer Optional}?` + ? Optional + : Param + : // otherwise, there aren't any params present + never; + +/** + * Examples: + * "/a/b/*" -> "*" + * ":a" -> "a" + * "/a/:b" -> "b" + * "/a/blahblahblah:b" -> "b" + * "/:a/:b" -> "a" | "b" + * "/:a/b/:c/*" -> "a" | "c" | "*" + */ +type PathParam = + // check if path is just a wildcard + Path extends "*" | "/*" + ? "*" + : // look for wildcard at the end of the path + Path extends `${infer Rest}/*` + ? "*" | _PathParam + : // look for params in the absence of wildcards + _PathParam; + +// Attempt to parse the given string segment. If it fails, then just return the +// plain string type as a default fallback. Otherwise return the union of the +// parsed string literals that were referenced as dynamic segments in the route. +export type ParamParseKey = + // if could not find path params, fallback to `string` + [PathParam] extends [never] ? string : PathParam; + +/** + * The parameters that were parsed from the URL path. + */ +export type Params = { + readonly [key in Key]: string | undefined; +}; + +/** + * A RouteMatch contains info about how a route matched a URL. + */ +export interface AgnosticRouteMatch< + ParamKey extends string = string, + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +> { + /** + * The names and values of dynamic parameters in the URL. + */ + params: Params; + /** + * The portion of the URL pathname that was matched. + */ + pathname: string; + /** + * The portion of the URL pathname that was matched before child routes. + */ + pathnameBase: string; + /** + * The route object that was used to match. + */ + route: RouteObjectType; +} + +export interface AgnosticDataRouteMatch + extends AgnosticRouteMatch {} + +function isIndexRoute( + route: AgnosticRouteObject +): route is AgnosticIndexRouteObject { + return route.index === true; +} + +// Walk the route tree generating unique IDs where necessary so we are working +// solely with AgnosticDataRouteObject's within the Router +export function convertRoutesToDataRoutes( + routes: AgnosticRouteObject[], + detectErrorBoundary: DetectErrorBoundaryFunction, + parentPath: number[] = [], + manifest: RouteManifest = {} +): AgnosticDataRouteObject[] { + return routes.map((route, index) => { + let treePath = [...parentPath, index]; + let id = typeof route.id === "string" ? route.id : treePath.join("-"); + invariant( + route.index !== true || !route.children, + `Cannot specify children on an index route` + ); + invariant( + !manifest[id], + `Found a route id collision on id "${id}". Route ` + + "id's must be globally unique within Data Router usages" + ); + + if (isIndexRoute(route)) { + let indexRoute: AgnosticDataIndexRouteObject = { + ...route, + hasErrorBoundary: detectErrorBoundary(route), + id, + }; + manifest[id] = indexRoute; + return indexRoute; + } else { + let pathOrLayoutRoute: AgnosticDataNonIndexRouteObject = { + ...route, + id, + hasErrorBoundary: detectErrorBoundary(route), + children: undefined, + }; + manifest[id] = pathOrLayoutRoute; + + if (route.children) { + pathOrLayoutRoute.children = convertRoutesToDataRoutes( + route.children, + detectErrorBoundary, + treePath, + manifest + ); + } + + return pathOrLayoutRoute; + } + }); +} + +/** + * Matches the given routes to a location and returns the match data. + * + * @see https://reactrouter.com/utils/match-routes + */ +export function matchRoutes< + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +>( + routes: RouteObjectType[], + locationArg: Partial | string, + basename = "/" +): AgnosticRouteMatch[] | null { + let location = + typeof locationArg === "string" ? parsePath(locationArg) : locationArg; + + let pathname = stripBasename(location.pathname || "/", basename); + + if (pathname == null) { + return null; + } + + let branches = flattenRoutes(routes); + rankRouteBranches(branches); + + let matches = null; + for (let i = 0; matches == null && i < branches.length; ++i) { + matches = matchRouteBranch( + branches[i], + // Incoming pathnames are generally encoded from either window.location + // or from router.navigate, but we want to match against the unencoded + // paths in the route definitions. Memory router locations won't be + // encoded here but there also shouldn't be anything to decode so this + // should be a safe operation. This avoids needing matchRoutes to be + // history-aware. + safelyDecodeURI(pathname) + ); + } + + return matches; +} + +interface RouteMeta< + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +> { + relativePath: string; + caseSensitive: boolean; + childrenIndex: number; + route: RouteObjectType; +} + +interface RouteBranch< + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +> { + path: string; + score: number; + routesMeta: RouteMeta[]; +} + +function flattenRoutes< + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +>( + routes: RouteObjectType[], + branches: RouteBranch[] = [], + parentsMeta: RouteMeta[] = [], + parentPath = "" +): RouteBranch[] { + let flattenRoute = ( + route: RouteObjectType, + index: number, + relativePath?: string + ) => { + let meta: RouteMeta = { + relativePath: + relativePath === undefined ? route.path || "" : relativePath, + caseSensitive: route.caseSensitive === true, + childrenIndex: index, + route, + }; + + if (meta.relativePath.startsWith("/")) { + invariant( + meta.relativePath.startsWith(parentPath), + `Absolute route path "${meta.relativePath}" nested under path ` + + `"${parentPath}" is not valid. An absolute child route path ` + + `must start with the combined path of all its parent routes.` + ); + + meta.relativePath = meta.relativePath.slice(parentPath.length); + } + + let path = joinPaths([parentPath, meta.relativePath]); + let routesMeta = parentsMeta.concat(meta); + + // Add the children before adding this route to the array so we traverse the + // route tree depth-first and child routes appear before their parents in + // the "flattened" version. + if (route.children && route.children.length > 0) { + invariant( + // Our types know better, but runtime JS may not! + // @ts-expect-error + route.index !== true, + `Index routes must not have child routes. Please remove ` + + `all child routes from route path "${path}".` + ); + + flattenRoutes(route.children, branches, routesMeta, path); + } + + // Routes without a path shouldn't ever match by themselves unless they are + // index routes, so don't add them to the list of possible branches. + if (route.path == null && !route.index) { + return; + } + + branches.push({ + path, + score: computeScore(path, route.index), + routesMeta, + }); + }; + routes.forEach((route, index) => { + // coarse-grain check for optional params + if (route.path === "" || !route.path?.includes("?")) { + flattenRoute(route, index); + } else { + for (let exploded of explodeOptionalSegments(route.path)) { + flattenRoute(route, index, exploded); + } + } + }); + + return branches; +} + +/** + * Computes all combinations of optional path segments for a given path, + * excluding combinations that are ambiguous and of lower priority. + * + * For example, `/one/:two?/three/:four?/:five?` explodes to: + * - `/one/three` + * - `/one/:two/three` + * - `/one/three/:four` + * - `/one/three/:five` + * - `/one/:two/three/:four` + * - `/one/:two/three/:five` + * - `/one/three/:four/:five` + * - `/one/:two/three/:four/:five` + */ +function explodeOptionalSegments(path: string): string[] { + let segments = path.split("/"); + if (segments.length === 0) return []; + + let [first, ...rest] = segments; + + // Optional path segments are denoted by a trailing `?` + let isOptional = first.endsWith("?"); + // Compute the corresponding required segment: `foo?` -> `foo` + let required = first.replace(/\?$/, ""); + + if (rest.length === 0) { + // Intepret empty string as omitting an optional segment + // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three` + return isOptional ? [required, ""] : [required]; + } + + let restExploded = explodeOptionalSegments(rest.join("/")); + + let result: string[] = []; + + // All child paths with the prefix. Do this for all children before the + // optional version for all children so we get consistent ordering where the + // parent optional aspect is preferred as required. Otherwise, we can get + // child sections interspersed where deeper optional segments are higher than + // parent optional segments, where for example, /:two would explodes _earlier_ + // then /:one. By always including the parent as required _for all children_ + // first, we avoid this issue + result.push( + ...restExploded.map((subpath) => + subpath === "" ? required : [required, subpath].join("/") + ) + ); + + // Then if this is an optional value, add all child versions without + if (isOptional) { + result.push(...restExploded); + } + + // for absolute paths, ensure `/` instead of empty segment + return result.map((exploded) => + path.startsWith("/") && exploded === "" ? "/" : exploded + ); +} + +function rankRouteBranches(branches: RouteBranch[]): void { + branches.sort((a, b) => + a.score !== b.score + ? b.score - a.score // Higher score first + : compareIndexes( + a.routesMeta.map((meta) => meta.childrenIndex), + b.routesMeta.map((meta) => meta.childrenIndex) + ) + ); +} + +const paramRe = /^:\w+$/; +const dynamicSegmentValue = 3; +const indexRouteValue = 2; +const emptySegmentValue = 1; +const staticSegmentValue = 10; +const splatPenalty = -2; +const isSplat = (s: string) => s === "*"; + +function computeScore(path: string, index: boolean | undefined): number { + let segments = path.split("/"); + let initialScore = segments.length; + if (segments.some(isSplat)) { + initialScore += splatPenalty; + } + + if (index) { + initialScore += indexRouteValue; + } + + return segments + .filter((s) => !isSplat(s)) + .reduce( + (score, segment) => + score + + (paramRe.test(segment) + ? dynamicSegmentValue + : segment === "" + ? emptySegmentValue + : staticSegmentValue), + initialScore + ); +} + +function compareIndexes(a: number[], b: number[]): number { + let siblings = + a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]); + + return siblings + ? // If two routes are siblings, we should try to match the earlier sibling + // first. This allows people to have fine-grained control over the matching + // behavior by simply putting routes with identical paths in the order they + // want them tried. + a[a.length - 1] - b[b.length - 1] + : // Otherwise, it doesn't really make sense to rank non-siblings by index, + // so they sort equally. + 0; +} + +function matchRouteBranch< + ParamKey extends string = string, + RouteObjectType extends AgnosticRouteObject = AgnosticRouteObject +>( + branch: RouteBranch, + pathname: string +): AgnosticRouteMatch[] | null { + let { routesMeta } = branch; + + let matchedParams = {}; + let matchedPathname = "/"; + let matches: AgnosticRouteMatch[] = []; + for (let i = 0; i < routesMeta.length; ++i) { + let meta = routesMeta[i]; + let end = i === routesMeta.length - 1; + let remainingPathname = + matchedPathname === "/" + ? pathname + : pathname.slice(matchedPathname.length) || "/"; + let match = matchPath( + { path: meta.relativePath, caseSensitive: meta.caseSensitive, end }, + remainingPathname + ); + + if (!match) return null; + + Object.assign(matchedParams, match.params); + + let route = meta.route; + + matches.push({ + // TODO: Can this as be avoided? + params: matchedParams as Params, + pathname: joinPaths([matchedPathname, match.pathname]), + pathnameBase: normalizePathname( + joinPaths([matchedPathname, match.pathnameBase]) + ), + route, + }); + + if (match.pathnameBase !== "/") { + matchedPathname = joinPaths([matchedPathname, match.pathnameBase]); + } + } + + return matches; +} + +/** + * Returns a path with params interpolated. + * + * @see https://reactrouter.com/utils/generate-path + */ +export function generatePath( + originalPath: Path, + params: { + [key in PathParam]: string | null; + } = {} as any +): string { + let path: string = originalPath; + if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) { + warning( + false, + `Route path "${path}" will be treated as if it were ` + + `"${path.replace(/\*$/, "/*")}" because the \`*\` character must ` + + `always follow a \`/\` in the pattern. To get rid of this warning, ` + + `please change the route path to "${path.replace(/\*$/, "/*")}".` + ); + path = path.replace(/\*$/, "/*") as Path; + } + + // ensure `/` is added at the beginning if the path is absolute + const prefix = path.startsWith("/") ? "/" : ""; + + const segments = path + .split(/\/+/) + .map((segment, index, array) => { + const isLastSegment = index === array.length - 1; + + // only apply the splat if it's the last segment + if (isLastSegment && segment === "*") { + const star = "*" as PathParam; + const starParam = params[star]; + + // Apply the splat + return starParam; + } + + const keyMatch = segment.match(/^:(\w+)(\??)$/); + if (keyMatch) { + const [, key, optional] = keyMatch; + let param = params[key as PathParam]; + + if (optional === "?") { + return param == null ? "" : param; + } + + if (param == null) { + invariant(false, `Missing ":${key}" param`); + } + + return param; + } + + // Remove any optional markers from optional static segments + return segment.replace(/\?$/g, ""); + }) + // Remove empty segments + .filter((segment) => !!segment); + + return prefix + segments.join("/"); +} + +/** + * A PathPattern is used to match on some portion of a URL pathname. + */ +export interface PathPattern { + /** + * A string to match against a URL pathname. May contain `:id`-style segments + * to indicate placeholders for dynamic parameters. May also end with `/*` to + * indicate matching the rest of the URL pathname. + */ + path: Path; + /** + * Should be `true` if the static portions of the `path` should be matched in + * the same case. + */ + caseSensitive?: boolean; + /** + * Should be `true` if this pattern should match the entire URL pathname. + */ + end?: boolean; +} + +/** + * A PathMatch contains info about how a PathPattern matched on a URL pathname. + */ +export interface PathMatch { + /** + * The names and values of dynamic parameters in the URL. + */ + params: Params; + /** + * The portion of the URL pathname that was matched. + */ + pathname: string; + /** + * The portion of the URL pathname that was matched before child routes. + */ + pathnameBase: string; + /** + * The pattern that was used to match. + */ + pattern: PathPattern; +} + +type Mutable = { + -readonly [P in keyof T]: T[P]; +}; + +/** + * Performs pattern matching on a URL pathname and returns information about + * the match. + * + * @see https://reactrouter.com/utils/match-path + */ +export function matchPath< + ParamKey extends ParamParseKey, + Path extends string +>( + pattern: PathPattern | Path, + pathname: string +): PathMatch | null { + if (typeof pattern === "string") { + pattern = { path: pattern, caseSensitive: false, end: true }; + } + + let [matcher, paramNames] = compilePath( + pattern.path, + pattern.caseSensitive, + pattern.end + ); + + let match = pathname.match(matcher); + if (!match) return null; + + let matchedPathname = match[0]; + let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1"); + let captureGroups = match.slice(1); + let params: Params = paramNames.reduce>( + (memo, paramName, index) => { + // We need to compute the pathnameBase here using the raw splat value + // instead of using params["*"] later because it will be decoded then + if (paramName === "*") { + let splatValue = captureGroups[index] || ""; + pathnameBase = matchedPathname + .slice(0, matchedPathname.length - splatValue.length) + .replace(/(.)\/+$/, "$1"); + } + + memo[paramName] = safelyDecodeURIComponent( + captureGroups[index] || "", + paramName + ); + return memo; + }, + {} + ); + + return { + params, + pathname: matchedPathname, + pathnameBase, + pattern, + }; +} + +function compilePath( + path: string, + caseSensitive = false, + end = true +): [RegExp, string[]] { + warning( + path === "*" || !path.endsWith("*") || path.endsWith("/*"), + `Route path "${path}" will be treated as if it were ` + + `"${path.replace(/\*$/, "/*")}" because the \`*\` character must ` + + `always follow a \`/\` in the pattern. To get rid of this warning, ` + + `please change the route path to "${path.replace(/\*$/, "/*")}".` + ); + + let paramNames: string[] = []; + let regexpSource = + "^" + + path + .replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below + .replace(/^\/*/, "/") // Make sure it has a leading / + .replace(/[\\.*+^$?{}|()[\]]/g, "\\$&") // Escape special regex chars + .replace(/\/:(\w+)/g, (_: string, paramName: string) => { + paramNames.push(paramName); + return "/([^\\/]+)"; + }); + + if (path.endsWith("*")) { + paramNames.push("*"); + regexpSource += + path === "*" || path === "/*" + ? "(.*)$" // Already matched the initial /, just match the rest + : "(?:\\/(.+)|\\/*)$"; // Don't include the / in params["*"] + } else if (end) { + // When matching to the end, ignore trailing slashes + regexpSource += "\\/*$"; + } else if (path !== "" && path !== "/") { + // If our path is non-empty and contains anything beyond an initial slash, + // then we have _some_ form of path in our regex so we should expect to + // match only if we find the end of this path segment. Look for an optional + // non-captured trailing slash (to match a portion of the URL) or the end + // of the path (if we've matched to the end). We used to do this with a + // word boundary but that gives false positives on routes like + // /user-preferences since `-` counts as a word boundary. + regexpSource += "(?:(?=\\/|$))"; + } else { + // Nothing to match for "" or "/" + } + + let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i"); + + return [matcher, paramNames]; +} + +function safelyDecodeURI(value: string) { + try { + return decodeURI(value); + } catch (error) { + warning( + false, + `The URL path "${value}" could not be decoded because it is is a ` + + `malformed URL segment. This is probably due to a bad percent ` + + `encoding (${error}).` + ); + + return value; + } +} + +function safelyDecodeURIComponent(value: string, paramName: string) { + try { + return decodeURIComponent(value); + } catch (error) { + warning( + false, + `The value for the URL param "${paramName}" will not be decoded because` + + ` the string "${value}" is a malformed URL segment. This is probably` + + ` due to a bad percent encoding (${error}).` + ); + + return value; + } +} + +/** + * @private + */ +export function stripBasename( + pathname: string, + basename: string +): string | null { + if (basename === "/") return pathname; + + if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) { + return null; + } + + // We want to leave trailing slash behavior in the user's control, so if they + // specify a basename with a trailing slash, we should support it + let startIndex = basename.endsWith("/") + ? basename.length - 1 + : basename.length; + let nextChar = pathname.charAt(startIndex); + if (nextChar && nextChar !== "/") { + // pathname does not start with basename/ + return null; + } + + return pathname.slice(startIndex) || "/"; +} + +/** + * Returns a resolved path object relative to the given pathname. + * + * @see https://reactrouter.com/utils/resolve-path + */ +export function resolvePath(to: To, fromPathname = "/"): Path { + let { + pathname: toPathname, + search = "", + hash = "", + } = typeof to === "string" ? parsePath(to) : to; + + let pathname = toPathname + ? toPathname.startsWith("/") + ? toPathname + : resolvePathname(toPathname, fromPathname) + : fromPathname; + + return { + pathname, + search: normalizeSearch(search), + hash: normalizeHash(hash), + }; +} + +function resolvePathname(relativePath: string, fromPathname: string): string { + let segments = fromPathname.replace(/\/+$/, "").split("/"); + let relativeSegments = relativePath.split("/"); + + relativeSegments.forEach((segment) => { + if (segment === "..") { + // Keep the root "" segment so the pathname starts at / + if (segments.length > 1) segments.pop(); + } else if (segment !== ".") { + segments.push(segment); + } + }); + + return segments.length > 1 ? segments.join("/") : "/"; +} + +function getInvalidPathError( + char: string, + field: string, + dest: string, + path: Partial +) { + return ( + `Cannot include a '${char}' character in a manually specified ` + + `\`to.${field}\` field [${JSON.stringify( + path + )}]. Please separate it out to the ` + + `\`to.${dest}\` field. Alternatively you may provide the full path as ` + + `a string in and the router will parse it for you.` + ); +} + +/** + * @private + * + * When processing relative navigation we want to ignore ancestor routes that + * do not contribute to the path, such that index/pathless layout routes don't + * interfere. + * + * For example, when moving a route element into an index route and/or a + * pathless layout route, relative link behavior contained within should stay + * the same. Both of the following examples should link back to the root: + * + * + * + * + * + * + * + * }> // <-- Does not contribute + * // <-- Does not contribute + * + * + */ +export function getPathContributingMatches< + T extends AgnosticRouteMatch = AgnosticRouteMatch +>(matches: T[]) { + return matches.filter( + (match, index) => + index === 0 || (match.route.path && match.route.path.length > 0) + ); +} + +/** + * @private + */ +export function resolveTo( + toArg: To, + routePathnames: string[], + locationPathname: string, + isPathRelative = false +): Path { + let to: Partial; + if (typeof toArg === "string") { + to = parsePath(toArg); + } else { + to = { ...toArg }; + + invariant( + !to.pathname || !to.pathname.includes("?"), + getInvalidPathError("?", "pathname", "search", to) + ); + invariant( + !to.pathname || !to.pathname.includes("#"), + getInvalidPathError("#", "pathname", "hash", to) + ); + invariant( + !to.search || !to.search.includes("#"), + getInvalidPathError("#", "search", "hash", to) + ); + } + + let isEmptyPath = toArg === "" || to.pathname === ""; + let toPathname = isEmptyPath ? "/" : to.pathname; + + let from: string; + + // Routing is relative to the current pathname if explicitly requested. + // + // If a pathname is explicitly provided in `to`, it should be relative to the + // route context. This is explained in `Note on `` values` in our + // migration guide from v5 as a means of disambiguation between `to` values + // that begin with `/` and those that do not. However, this is problematic for + // `to` values that do not provide a pathname. `to` can simply be a search or + // hash string, in which case we should assume that the navigation is relative + // to the current location's pathname and *not* the route pathname. + if (isPathRelative || toPathname == null) { + from = locationPathname; + } else { + let routePathnameIndex = routePathnames.length - 1; + + if (toPathname.startsWith("..")) { + let toSegments = toPathname.split("/"); + + // Each leading .. segment means "go up one route" instead of "go up one + // URL segment". This is a key difference from how works and a + // major reason we call this a "to" value instead of a "href". + while (toSegments[0] === "..") { + toSegments.shift(); + routePathnameIndex -= 1; + } + + to.pathname = toSegments.join("/"); + } + + // If there are more ".." segments than parent routes, resolve relative to + // the root / URL. + from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/"; + } + + let path = resolvePath(to, from); + + // Ensure the pathname has a trailing slash if the original "to" had one + let hasExplicitTrailingSlash = + toPathname && toPathname !== "/" && toPathname.endsWith("/"); + // Or if this was a link to the current path which has a trailing slash + let hasCurrentTrailingSlash = + (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/"); + if ( + !path.pathname.endsWith("/") && + (hasExplicitTrailingSlash || hasCurrentTrailingSlash) + ) { + path.pathname += "/"; + } + + return path; +} + +/** + * @private + */ +export function getToPathname(to: To): string | undefined { + // Empty strings should be treated the same as / paths + return to === "" || (to as Path).pathname === "" + ? "/" + : typeof to === "string" + ? parsePath(to).pathname + : to.pathname; +} + +/** + * @private + */ +export const joinPaths = (paths: string[]): string => + paths.join("/").replace(/\/\/+/g, "/"); + +/** + * @private + */ +export const normalizePathname = (pathname: string): string => + pathname.replace(/\/+$/, "").replace(/^\/*/, "/"); + +/** + * @private + */ +export const normalizeSearch = (search: string): string => + !search || search === "?" + ? "" + : search.startsWith("?") + ? search + : "?" + search; + +/** + * @private + */ +export const normalizeHash = (hash: string): string => + !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash; + +export type JsonFunction = ( + data: Data, + init?: number | ResponseInit +) => Response; + +/** + * This is a shortcut for creating `application/json` responses. Converts `data` + * to JSON and sets the `Content-Type` header. + */ +export const json: JsonFunction = (data, init = {}) => { + let responseInit = typeof init === "number" ? { status: init } : init; + + let headers = new Headers(responseInit.headers); + if (!headers.has("Content-Type")) { + headers.set("Content-Type", "application/json; charset=utf-8"); + } + + return new Response(JSON.stringify(data), { + ...responseInit, + headers, + }); +}; + +export interface TrackedPromise extends Promise { + _tracked?: boolean; + _data?: any; + _error?: any; +} + +export class AbortedDeferredError extends Error {} + +export class DeferredData { + private pendingKeysSet: Set = new Set(); + private controller: AbortController; + private abortPromise: Promise; + private unlistenAbortSignal: () => void; + private subscribers: Set<(aborted: boolean, settledKey?: string) => void> = + new Set(); + data: Record; + init?: ResponseInit; + deferredKeys: string[] = []; + + constructor(data: Record, responseInit?: ResponseInit) { + invariant( + data && typeof data === "object" && !Array.isArray(data), + "defer() only accepts plain objects" + ); + + // Set up an AbortController + Promise we can race against to exit early + // cancellation + let reject: (e: AbortedDeferredError) => void; + this.abortPromise = new Promise((_, r) => (reject = r)); + this.controller = new AbortController(); + let onAbort = () => + reject(new AbortedDeferredError("Deferred data aborted")); + this.unlistenAbortSignal = () => + this.controller.signal.removeEventListener("abort", onAbort); + this.controller.signal.addEventListener("abort", onAbort); + + this.data = Object.entries(data).reduce( + (acc, [key, value]) => + Object.assign(acc, { + [key]: this.trackPromise(key, value), + }), + {} + ); + + if (this.done) { + // All incoming values were resolved + this.unlistenAbortSignal(); + } + + this.init = responseInit; + } + + private trackPromise( + key: string, + value: Promise | unknown + ): TrackedPromise | unknown { + if (!(value instanceof Promise)) { + return value; + } + + this.deferredKeys.push(key); + this.pendingKeysSet.add(key); + + // We store a little wrapper promise that will be extended with + // _data/_error props upon resolve/reject + let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then( + (data) => this.onSettle(promise, key, null, data as unknown), + (error) => this.onSettle(promise, key, error as unknown) + ); + + // Register rejection listeners to avoid uncaught promise rejections on + // errors or aborted deferred values + promise.catch(() => {}); + + Object.defineProperty(promise, "_tracked", { get: () => true }); + return promise; + } + + private onSettle( + promise: TrackedPromise, + key: string, + error: unknown, + data?: unknown + ): unknown { + if ( + this.controller.signal.aborted && + error instanceof AbortedDeferredError + ) { + this.unlistenAbortSignal(); + Object.defineProperty(promise, "_error", { get: () => error }); + return Promise.reject(error); + } + + this.pendingKeysSet.delete(key); + + if (this.done) { + // Nothing left to abort! + this.unlistenAbortSignal(); + } + + if (error) { + Object.defineProperty(promise, "_error", { get: () => error }); + this.emit(false, key); + return Promise.reject(error); + } + + Object.defineProperty(promise, "_data", { get: () => data }); + this.emit(false, key); + return data; + } + + private emit(aborted: boolean, settledKey?: string) { + this.subscribers.forEach((subscriber) => subscriber(aborted, settledKey)); + } + + subscribe(fn: (aborted: boolean, settledKey?: string) => void) { + this.subscribers.add(fn); + return () => this.subscribers.delete(fn); + } + + cancel() { + this.controller.abort(); + this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k)); + this.emit(true); + } + + async resolveData(signal: AbortSignal) { + let aborted = false; + if (!this.done) { + let onAbort = () => this.cancel(); + signal.addEventListener("abort", onAbort); + aborted = await new Promise((resolve) => { + this.subscribe((aborted) => { + signal.removeEventListener("abort", onAbort); + if (aborted || this.done) { + resolve(aborted); + } + }); + }); + } + return aborted; + } + + get done() { + return this.pendingKeysSet.size === 0; + } + + get unwrappedData() { + invariant( + this.data !== null && this.done, + "Can only unwrap data on initialized and settled deferreds" + ); + + return Object.entries(this.data).reduce( + (acc, [key, value]) => + Object.assign(acc, { + [key]: unwrapTrackedPromise(value), + }), + {} + ); + } + + get pendingKeys() { + return Array.from(this.pendingKeysSet); + } +} + +function isTrackedPromise(value: any): value is TrackedPromise { + return ( + value instanceof Promise && (value as TrackedPromise)._tracked === true + ); +} + +function unwrapTrackedPromise(value: any) { + if (!isTrackedPromise(value)) { + return value; + } + + if (value._error) { + throw value._error; + } + return value._data; +} + +export type DeferFunction = ( + data: Record, + init?: number | ResponseInit +) => DeferredData; + +export const defer: DeferFunction = (data, init = {}) => { + let responseInit = typeof init === "number" ? { status: init } : init; + + return new DeferredData(data, responseInit); +}; + +export type RedirectFunction = ( + url: string, + init?: number | ResponseInit +) => Response; + +/** + * A redirect response. Sets the status code and the `Location` header. + * Defaults to "302 Found". + */ +export const redirect: RedirectFunction = (url, init = 302) => { + let responseInit = init; + if (typeof responseInit === "number") { + responseInit = { status: responseInit }; + } else if (typeof responseInit.status === "undefined") { + responseInit.status = 302; + } + + let headers = new Headers(responseInit.headers); + headers.set("Location", url); + + return new Response(null, { + ...responseInit, + headers, + }); +}; + +/** + * @private + * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies + */ +export class ErrorResponse { + status: number; + statusText: string; + data: any; + error?: Error; + internal: boolean; + + constructor( + status: number, + statusText: string | undefined, + data: any, + internal = false + ) { + this.status = status; + this.statusText = statusText || ""; + this.internal = internal; + if (data instanceof Error) { + this.data = data.toString(); + this.error = data; + } else { + this.data = data; + } + } +} + +/** + * Check if the given error is an ErrorResponse generated from a 4xx/5xx + * Response thrown from an action/loader + */ +export function isRouteErrorResponse(error: any): error is ErrorResponse { + return ( + error != null && + typeof error.status === "number" && + typeof error.statusText === "string" && + typeof error.internal === "boolean" && + "data" in error + ); +} diff --git a/node_modules/js-tokens/CHANGELOG.md b/node_modules/js-tokens/CHANGELOG.md new file mode 100644 index 00000000..755e6f6e --- /dev/null +++ b/node_modules/js-tokens/CHANGELOG.md @@ -0,0 +1,151 @@ +### Version 4.0.0 (2018-01-28) ### + +- Added: Support for ES2018. The only change needed was recognizing the `s` + regex flag. +- Changed: _All_ tokens returned by the `matchToToken` function now have a + `closed` property. It is set to `undefined` for the tokens where “closed” + doesn’t make sense. This means that all tokens objects have the same shape, + which might improve performance. + +These are the breaking changes: + +- `'/a/s'.match(jsTokens)` no longer returns `['/', 'a', '/', 's']`, but + `['/a/s']`. (There are of course other variations of this.) +- Code that rely on some token objects not having the `closed` property could + now behave differently. + + +### Version 3.0.2 (2017-06-28) ### + +- No code changes. Just updates to the readme. + + +### Version 3.0.1 (2017-01-30) ### + +- Fixed: ES2015 unicode escapes with more than 6 hex digits are now matched + correctly. + + +### Version 3.0.0 (2017-01-11) ### + +This release contains one breaking change, that should [improve performance in +V8][v8-perf]: + +> So how can you, as a JavaScript developer, ensure that your RegExps are fast? +> If you are not interested in hooking into RegExp internals, make sure that +> neither the RegExp instance, nor its prototype is modified in order to get the +> best performance: +> +> ```js +> var re = /./g; +> re.exec(''); // Fast path. +> re.new_property = 'slow'; +> ``` + +This module used to export a single regex, with `.matchToToken` bolted +on, just like in the above example. This release changes the exports of +the module to avoid this issue. + +Before: + +```js +import jsTokens from "js-tokens" +// or: +var jsTokens = require("js-tokens") +var matchToToken = jsTokens.matchToToken +``` + +After: + +```js +import jsTokens, {matchToToken} from "js-tokens" +// or: +var jsTokens = require("js-tokens").default +var matchToToken = require("js-tokens").matchToToken +``` + +[v8-perf]: http://v8project.blogspot.se/2017/01/speeding-up-v8-regular-expressions.html + + +### Version 2.0.0 (2016-06-19) ### + +- Added: Support for ES2016. In other words, support for the `**` exponentiation + operator. + +These are the breaking changes: + +- `'**'.match(jsTokens)` no longer returns `['*', '*']`, but `['**']`. +- `'**='.match(jsTokens)` no longer returns `['*', '*=']`, but `['**=']`. + + +### Version 1.0.3 (2016-03-27) ### + +- Improved: Made the regex ever so slightly smaller. +- Updated: The readme. + + +### Version 1.0.2 (2015-10-18) ### + +- Improved: Limited npm package contents for a smaller download. Thanks to + @zertosh! + + +### Version 1.0.1 (2015-06-20) ### + +- Fixed: Declared an undeclared variable. + + +### Version 1.0.0 (2015-02-26) ### + +- Changed: Merged the 'operator' and 'punctuation' types into 'punctuator'. That + type is now equivalent to the Punctuator token in the ECMAScript + specification. (Backwards-incompatible change.) +- Fixed: A `-` followed by a number is now correctly matched as a punctuator + followed by a number. It used to be matched as just a number, but there is no + such thing as negative number literals. (Possibly backwards-incompatible + change.) + + +### Version 0.4.1 (2015-02-21) ### + +- Added: Support for the regex `u` flag. + + +### Version 0.4.0 (2015-02-21) ### + +- Improved: `jsTokens.matchToToken` performance. +- Added: Support for octal and binary number literals. +- Added: Support for template strings. + + +### Version 0.3.1 (2015-01-06) ### + +- Fixed: Support for unicode spaces. They used to be allowed in names (which is + very confusing), and some unicode newlines were wrongly allowed in strings and + regexes. + + +### Version 0.3.0 (2014-12-19) ### + +- Changed: The `jsTokens.names` array has been replaced with the + `jsTokens.matchToToken` function. The capturing groups of `jsTokens` are no + longer part of the public API; instead use said function. See this [gist] for + an example. (Backwards-incompatible change.) +- Changed: The empty string is now considered an “invalid” token, instead an + “empty” token (its own group). (Backwards-incompatible change.) +- Removed: component support. (Backwards-incompatible change.) + +[gist]: https://gist.github.com/lydell/be49dbf80c382c473004 + + +### Version 0.2.0 (2014-06-19) ### + +- Changed: Match ES6 function arrows (`=>`) as an operator, instead of its own + category (“functionArrow”), for simplicity. (Backwards-incompatible change.) +- Added: ES6 splats (`...`) are now matched as an operator (instead of three + punctuations). (Backwards-incompatible change.) + + +### Version 0.1.0 (2014-03-08) ### + +- Initial release. diff --git a/node_modules/js-tokens/LICENSE b/node_modules/js-tokens/LICENSE new file mode 100644 index 00000000..54aef52f --- /dev/null +++ b/node_modules/js-tokens/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/js-tokens/README.md b/node_modules/js-tokens/README.md new file mode 100644 index 00000000..00cdf163 --- /dev/null +++ b/node_modules/js-tokens/README.md @@ -0,0 +1,240 @@ +Overview [![Build Status](https://travis-ci.org/lydell/js-tokens.svg?branch=master)](https://travis-ci.org/lydell/js-tokens) +======== + +A regex that tokenizes JavaScript. + +```js +var jsTokens = require("js-tokens").default + +var jsString = "var foo=opts.foo;\n..." + +jsString.match(jsTokens) +// ["var", " ", "foo", "=", "opts", ".", "foo", ";", "\n", ...] +``` + + +Installation +============ + +`npm install js-tokens` + +```js +import jsTokens from "js-tokens" +// or: +var jsTokens = require("js-tokens").default +``` + + +Usage +===== + +### `jsTokens` ### + +A regex with the `g` flag that matches JavaScript tokens. + +The regex _always_ matches, even invalid JavaScript and the empty string. + +The next match is always directly after the previous. + +### `var token = matchToToken(match)` ### + +```js +import {matchToToken} from "js-tokens" +// or: +var matchToToken = require("js-tokens").matchToToken +``` + +Takes a `match` returned by `jsTokens.exec(string)`, and returns a `{type: +String, value: String}` object. The following types are available: + +- string +- comment +- regex +- number +- name +- punctuator +- whitespace +- invalid + +Multi-line comments and strings also have a `closed` property indicating if the +token was closed or not (see below). + +Comments and strings both come in several flavors. To distinguish them, check if +the token starts with `//`, `/*`, `'`, `"` or `` ` ``. + +Names are ECMAScript IdentifierNames, that is, including both identifiers and +keywords. You may use [is-keyword-js] to tell them apart. + +Whitespace includes both line terminators and other whitespace. + +[is-keyword-js]: https://github.com/crissdev/is-keyword-js + + +ECMAScript support +================== + +The intention is to always support the latest ECMAScript version whose feature +set has been finalized. + +If adding support for a newer version requires changes, a new version with a +major verion bump will be released. + +Currently, ECMAScript 2018 is supported. + + +Invalid code handling +===================== + +Unterminated strings are still matched as strings. JavaScript strings cannot +contain (unescaped) newlines, so unterminated strings simply end at the end of +the line. Unterminated template strings can contain unescaped newlines, though, +so they go on to the end of input. + +Unterminated multi-line comments are also still matched as comments. They +simply go on to the end of the input. + +Unterminated regex literals are likely matched as division and whatever is +inside the regex. + +Invalid ASCII characters have their own capturing group. + +Invalid non-ASCII characters are treated as names, to simplify the matching of +names (except unicode spaces which are treated as whitespace). Note: See also +the [ES2018](#es2018) section. + +Regex literals may contain invalid regex syntax. They are still matched as +regex literals. They may also contain repeated regex flags, to keep the regex +simple. + +Strings may contain invalid escape sequences. + + +Limitations +=========== + +Tokenizing JavaScript using regexes—in fact, _one single regex_—won’t be +perfect. But that’s not the point either. + +You may compare jsTokens with [esprima] by using `esprima-compare.js`. +See `npm run esprima-compare`! + +[esprima]: http://esprima.org/ + +### Template string interpolation ### + +Template strings are matched as single tokens, from the starting `` ` `` to the +ending `` ` ``, including interpolations (whose tokens are not matched +individually). + +Matching template string interpolations requires recursive balancing of `{` and +`}`—something that JavaScript regexes cannot do. Only one level of nesting is +supported. + +### Division and regex literals collision ### + +Consider this example: + +```js +var g = 9.82 +var number = bar / 2/g + +var regex = / 2/g +``` + +A human can easily understand that in the `number` line we’re dealing with +division, and in the `regex` line we’re dealing with a regex literal. How come? +Because humans can look at the whole code to put the `/` characters in context. +A JavaScript regex cannot. It only sees forwards. (Well, ES2018 regexes can also +look backwards. See the [ES2018](#es2018) section). + +When the `jsTokens` regex scans throught the above, it will see the following +at the end of both the `number` and `regex` rows: + +```js +/ 2/g +``` + +It is then impossible to know if that is a regex literal, or part of an +expression dealing with division. + +Here is a similar case: + +```js +foo /= 2/g +foo(/= 2/g) +``` + +The first line divides the `foo` variable with `2/g`. The second line calls the +`foo` function with the regex literal `/= 2/g`. Again, since `jsTokens` only +sees forwards, it cannot tell the two cases apart. + +There are some cases where we _can_ tell division and regex literals apart, +though. + +First off, we have the simple cases where there’s only one slash in the line: + +```js +var foo = 2/g +foo /= 2 +``` + +Regex literals cannot contain newlines, so the above cases are correctly +identified as division. Things are only problematic when there are more than +one non-comment slash in a single line. + +Secondly, not every character is a valid regex flag. + +```js +var number = bar / 2/e +``` + +The above example is also correctly identified as division, because `e` is not a +valid regex flag. I initially wanted to future-proof by allowing `[a-zA-Z]*` +(any letter) as flags, but it is not worth it since it increases the amount of +ambigous cases. So only the standard `g`, `m`, `i`, `y` and `u` flags are +allowed. This means that the above example will be identified as division as +long as you don’t rename the `e` variable to some permutation of `gmiyus` 1 to 6 +characters long. + +Lastly, we can look _forward_ for information. + +- If the token following what looks like a regex literal is not valid after a + regex literal, but is valid in a division expression, then the regex literal + is treated as division instead. For example, a flagless regex cannot be + followed by a string, number or name, but all of those three can be the + denominator of a division. +- Generally, if what looks like a regex literal is followed by an operator, the + regex literal is treated as division instead. This is because regexes are + seldomly used with operators (such as `+`, `*`, `&&` and `==`), but division + could likely be part of such an expression. + +Please consult the regex source and the test cases for precise information on +when regex or division is matched (should you need to know). In short, you +could sum it up as: + +If the end of a statement looks like a regex literal (even if it isn’t), it +will be treated as one. Otherwise it should work as expected (if you write sane +code). + +### ES2018 ### + +ES2018 added some nice regex improvements to the language. + +- [Unicode property escapes] should allow telling names and invalid non-ASCII + characters apart without blowing up the regex size. +- [Lookbehind assertions] should allow matching telling division and regex + literals apart in more cases. +- [Named capture groups] might simplify some things. + +These things would be nice to do, but are not critical. They probably have to +wait until the oldest maintained Node.js LTS release supports those features. + +[Unicode property escapes]: http://2ality.com/2017/07/regexp-unicode-property-escapes.html +[Lookbehind assertions]: http://2ality.com/2017/05/regexp-lookbehind-assertions.html +[Named capture groups]: http://2ality.com/2017/05/regexp-named-capture-groups.html + + +License +======= + +[MIT](LICENSE). diff --git a/node_modules/js-tokens/index.js b/node_modules/js-tokens/index.js new file mode 100644 index 00000000..b23a4a0e --- /dev/null +++ b/node_modules/js-tokens/index.js @@ -0,0 +1,23 @@ +// Copyright 2014, 2015, 2016, 2017, 2018 Simon Lydell +// License: MIT. (See LICENSE.) + +Object.defineProperty(exports, "__esModule", { + value: true +}) + +// This regex comes from regex.coffee, and is inserted here by generate-index.js +// (run `npm run build`). +exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyus]{1,6}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g + +exports.matchToToken = function(match) { + var token = {type: "invalid", value: match[0], closed: undefined} + if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]) + else if (match[ 5]) token.type = "comment" + else if (match[ 6]) token.type = "comment", token.closed = !!match[7] + else if (match[ 8]) token.type = "regex" + else if (match[ 9]) token.type = "number" + else if (match[10]) token.type = "name" + else if (match[11]) token.type = "punctuator" + else if (match[12]) token.type = "whitespace" + return token +} diff --git a/node_modules/js-tokens/package.json b/node_modules/js-tokens/package.json new file mode 100644 index 00000000..66752fab --- /dev/null +++ b/node_modules/js-tokens/package.json @@ -0,0 +1,30 @@ +{ + "name": "js-tokens", + "version": "4.0.0", + "author": "Simon Lydell", + "license": "MIT", + "description": "A regex that tokenizes JavaScript.", + "keywords": [ + "JavaScript", + "js", + "token", + "tokenize", + "regex" + ], + "files": [ + "index.js" + ], + "repository": "lydell/js-tokens", + "scripts": { + "test": "mocha --ui tdd", + "esprima-compare": "node esprima-compare ./index.js everything.js/es5.js", + "build": "node generate-index.js", + "dev": "npm run build && npm test" + }, + "devDependencies": { + "coffeescript": "2.1.1", + "esprima": "4.0.0", + "everything.js": "1.0.3", + "mocha": "5.0.0" + } +} diff --git a/node_modules/loose-envify/LICENSE b/node_modules/loose-envify/LICENSE new file mode 100644 index 00000000..fbafb487 --- /dev/null +++ b/node_modules/loose-envify/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andres Suarez + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/loose-envify/README.md b/node_modules/loose-envify/README.md new file mode 100644 index 00000000..7f4e07b0 --- /dev/null +++ b/node_modules/loose-envify/README.md @@ -0,0 +1,45 @@ +# loose-envify + +[![Build Status](https://travis-ci.org/zertosh/loose-envify.svg?branch=master)](https://travis-ci.org/zertosh/loose-envify) + +Fast (and loose) selective `process.env` replacer using [js-tokens](https://github.com/lydell/js-tokens) instead of an AST. Works just like [envify](https://github.com/hughsk/envify) but much faster. + +## Gotchas + +* Doesn't handle broken syntax. +* Doesn't look inside embedded expressions in template strings. + - **this won't work:** + ```js + console.log(`the current env is ${process.env.NODE_ENV}`); + ``` +* Doesn't replace oddly-spaced or oddly-commented expressions. + - **this won't work:** + ```js + console.log(process./*won't*/env./*work*/NODE_ENV); + ``` + +## Usage/Options + +loose-envify has the exact same interface as [envify](https://github.com/hughsk/envify), including the CLI. + +## Benchmark + +``` +envify: + + $ for i in {1..5}; do node bench/bench.js 'envify'; done + 708ms + 727ms + 791ms + 719ms + 720ms + +loose-envify: + + $ for i in {1..5}; do node bench/bench.js '../'; done + 51ms + 52ms + 52ms + 52ms + 52ms +``` diff --git a/node_modules/loose-envify/cli.js b/node_modules/loose-envify/cli.js new file mode 100755 index 00000000..c0b63cb1 --- /dev/null +++ b/node_modules/loose-envify/cli.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node +'use strict'; + +var looseEnvify = require('./'); +var fs = require('fs'); + +if (process.argv[2]) { + fs.createReadStream(process.argv[2], {encoding: 'utf8'}) + .pipe(looseEnvify(process.argv[2])) + .pipe(process.stdout); +} else { + process.stdin.resume() + process.stdin + .pipe(looseEnvify(__filename)) + .pipe(process.stdout); +} diff --git a/node_modules/loose-envify/custom.js b/node_modules/loose-envify/custom.js new file mode 100644 index 00000000..6389bfac --- /dev/null +++ b/node_modules/loose-envify/custom.js @@ -0,0 +1,4 @@ +// envify compatibility +'use strict'; + +module.exports = require('./loose-envify'); diff --git a/node_modules/loose-envify/index.js b/node_modules/loose-envify/index.js new file mode 100644 index 00000000..8cd8305d --- /dev/null +++ b/node_modules/loose-envify/index.js @@ -0,0 +1,3 @@ +'use strict'; + +module.exports = require('./loose-envify')(process.env); diff --git a/node_modules/loose-envify/loose-envify.js b/node_modules/loose-envify/loose-envify.js new file mode 100644 index 00000000..b5a5be22 --- /dev/null +++ b/node_modules/loose-envify/loose-envify.js @@ -0,0 +1,36 @@ +'use strict'; + +var stream = require('stream'); +var util = require('util'); +var replace = require('./replace'); + +var jsonExtRe = /\.json$/; + +module.exports = function(rootEnv) { + rootEnv = rootEnv || process.env; + return function (file, trOpts) { + if (jsonExtRe.test(file)) { + return stream.PassThrough(); + } + var envs = trOpts ? [rootEnv, trOpts] : [rootEnv]; + return new LooseEnvify(envs); + }; +}; + +function LooseEnvify(envs) { + stream.Transform.call(this); + this._data = ''; + this._envs = envs; +} +util.inherits(LooseEnvify, stream.Transform); + +LooseEnvify.prototype._transform = function(buf, enc, cb) { + this._data += buf; + cb(); +}; + +LooseEnvify.prototype._flush = function(cb) { + var replaced = replace(this._data, this._envs); + this.push(replaced); + cb(); +}; diff --git a/node_modules/loose-envify/package.json b/node_modules/loose-envify/package.json new file mode 100644 index 00000000..5e3d0e27 --- /dev/null +++ b/node_modules/loose-envify/package.json @@ -0,0 +1,36 @@ +{ + "name": "loose-envify", + "version": "1.4.0", + "description": "Fast (and loose) selective `process.env` replacer using js-tokens instead of an AST", + "keywords": [ + "environment", + "variables", + "browserify", + "browserify-transform", + "transform", + "source", + "configuration" + ], + "homepage": "https://github.com/zertosh/loose-envify", + "license": "MIT", + "author": "Andres Suarez ", + "main": "index.js", + "bin": { + "loose-envify": "cli.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/zertosh/loose-envify.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "devDependencies": { + "browserify": "^13.1.1", + "envify": "^3.4.0", + "tap": "^8.0.0" + } +} diff --git a/node_modules/loose-envify/replace.js b/node_modules/loose-envify/replace.js new file mode 100644 index 00000000..ec15e81c --- /dev/null +++ b/node_modules/loose-envify/replace.js @@ -0,0 +1,65 @@ +'use strict'; + +var jsTokens = require('js-tokens').default; + +var processEnvRe = /\bprocess\.env\.[_$a-zA-Z][$\w]+\b/; +var spaceOrCommentRe = /^(?:\s|\/[/*])/; + +function replace(src, envs) { + if (!processEnvRe.test(src)) { + return src; + } + + var out = []; + var purge = envs.some(function(env) { + return env._ && env._.indexOf('purge') !== -1; + }); + + jsTokens.lastIndex = 0 + var parts = src.match(jsTokens); + + for (var i = 0; i < parts.length; i++) { + if (parts[i ] === 'process' && + parts[i + 1] === '.' && + parts[i + 2] === 'env' && + parts[i + 3] === '.') { + var prevCodeToken = getAdjacentCodeToken(-1, parts, i); + var nextCodeToken = getAdjacentCodeToken(1, parts, i + 4); + var replacement = getReplacementString(envs, parts[i + 4], purge); + if (prevCodeToken !== '.' && + nextCodeToken !== '.' && + nextCodeToken !== '=' && + typeof replacement === 'string') { + out.push(replacement); + i += 4; + continue; + } + } + out.push(parts[i]); + } + + return out.join(''); +} + +function getAdjacentCodeToken(dir, parts, i) { + while (true) { + var part = parts[i += dir]; + if (!spaceOrCommentRe.test(part)) { + return part; + } + } +} + +function getReplacementString(envs, name, purge) { + for (var j = 0; j < envs.length; j++) { + var env = envs[j]; + if (typeof env[name] !== 'undefined') { + return JSON.stringify(env[name]); + } + } + if (purge) { + return 'undefined'; + } +} + +module.exports = replace; diff --git a/node_modules/react-dom/LICENSE b/node_modules/react-dom/LICENSE new file mode 100644 index 00000000..b96dcb04 --- /dev/null +++ b/node_modules/react-dom/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/react-dom/README.md b/node_modules/react-dom/README.md new file mode 100644 index 00000000..ecba5cfb --- /dev/null +++ b/node_modules/react-dom/README.md @@ -0,0 +1,60 @@ +# `react-dom` + +This package serves as the entry point to the DOM and server renderers for React. It is intended to be paired with the generic React package, which is shipped as `react` to npm. + +## Installation + +```sh +npm install react react-dom +``` + +## Usage + +### In the browser + +```js +import { createRoot } from 'react-dom/client'; + +function App() { + return
    Hello World
    ; +} + +const root = createRoot(document.getElementById('root')); +root.render(); +``` + +### On the server + +```js +import { renderToPipeableStream } from 'react-dom/server'; + +function App() { + return
    Hello World
    ; +} + +function handleRequest(res) { + // ... in your server handler ... + const stream = renderToPipeableStream(, { + onShellReady() { + res.statusCode = 200; + res.setHeader('Content-type', 'text/html'); + stream.pipe(res); + }, + // ... + }); +} +``` + +## API + +### `react-dom` + +See https://reactjs.org/docs/react-dom.html + +### `react-dom/client` + +See https://reactjs.org/docs/react-dom-client.html + +### `react-dom/server` + +See https://reactjs.org/docs/react-dom-server.html diff --git a/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js b/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js new file mode 100644 index 00000000..11c25e08 --- /dev/null +++ b/node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js @@ -0,0 +1,7018 @@ +/** + * @license React + * react-dom-server-legacy.browser.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +if (process.env.NODE_ENV !== "production") { + (function() { +'use strict'; + +var React = require('react'); + +var ReactVersion = '18.2.0'; + +var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; + +// by calls to these methods by a Babel plugin. +// +// In PROD (or in packages without access to React internals), +// they are left as they are instead. + +function warn(format) { + { + { + for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + printWarning('warn', format, args); + } + } +} +function error(format) { + { + { + for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + args[_key2 - 1] = arguments[_key2]; + } + + printWarning('error', format, args); + } + } +} + +function printWarning(level, format, args) { + // When changing this logic, you might want to also + // update consoleWithStackDev.www.js as well. + { + var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + var stack = ReactDebugCurrentFrame.getStackAddendum(); + + if (stack !== '') { + format += '%s'; + args = args.concat([stack]); + } // eslint-disable-next-line react-internal/safe-string-coercion + + + var argsWithFormat = args.map(function (item) { + return String(item); + }); // Careful: RN currently depends on this prefix + + argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it + // breaks IE9: https://github.com/facebook/react/issues/13610 + // eslint-disable-next-line react-internal/no-production-logging + + Function.prototype.apply.call(console[level], console, argsWithFormat); + } +} + +function scheduleWork(callback) { + callback(); +} +function beginWriting(destination) {} +function writeChunk(destination, chunk) { + writeChunkAndReturn(destination, chunk); +} +function writeChunkAndReturn(destination, chunk) { + return destination.push(chunk); +} +function completeWriting(destination) {} +function close(destination) { + destination.push(null); +} +function stringToChunk(content) { + return content; +} +function stringToPrecomputedChunk(content) { + return content; +} +function closeWithError(destination, error) { + // $FlowFixMe: This is an Error object or the destination accepts other types. + destination.destroy(error); +} + +/* + * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol + * and Temporal.* types. See https://github.com/facebook/react/pull/22064. + * + * The functions in this module will throw an easier-to-understand, + * easier-to-debug exception with a clear errors message message explaining the + * problem. (Instead of a confusing exception thrown inside the implementation + * of the `value` object). + */ +// $FlowFixMe only called in DEV, so void return is not possible. +function typeName(value) { + { + // toStringTag is needed for namespaced types like Temporal.Instant + var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag; + var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object'; + return type; + } +} // $FlowFixMe only called in DEV, so void return is not possible. + + +function willCoercionThrow(value) { + { + try { + testStringCoercion(value); + return false; + } catch (e) { + return true; + } + } +} + +function testStringCoercion(value) { + // If you ended up here by following an exception call stack, here's what's + // happened: you supplied an object or symbol value to React (as a prop, key, + // DOM attribute, CSS property, string ref, etc.) and when React tried to + // coerce it to a string using `'' + value`, an exception was thrown. + // + // The most common types that will cause this exception are `Symbol` instances + // and Temporal objects like `Temporal.Instant`. But any object that has a + // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this + // exception. (Library authors do this to prevent users from using built-in + // numeric operators like `+` or comparison operators like `>=` because custom + // methods are needed to perform accurate arithmetic or comparison.) + // + // To fix the problem, coerce this object or symbol value to a string before + // passing it to React. The most reliable way is usually `String(value)`. + // + // To find which value is throwing, check the browser or debugger console. + // Before this exception was thrown, there should be `console.error` output + // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the + // problem and how that type was used: key, atrribute, input value prop, etc. + // In most cases, this console output also shows the component and its + // ancestor components where the exception happened. + // + // eslint-disable-next-line react-internal/safe-string-coercion + return '' + value; +} + +function checkAttributeStringCoercion(value, attributeName) { + { + if (willCoercionThrow(value)) { + error('The provided `%s` attribute is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', attributeName, typeName(value)); + + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } +} +function checkCSSPropertyStringCoercion(value, propName) { + { + if (willCoercionThrow(value)) { + error('The provided `%s` CSS property is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', propName, typeName(value)); + + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } +} +function checkHtmlStringCoercion(value) { + { + if (willCoercionThrow(value)) { + error('The provided HTML markup uses a value of unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); + + return testStringCoercion(value); // throw (to help callers find troubleshooting comments) + } + } +} + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +// A reserved attribute. +// It is handled by React separately and shouldn't be written to the DOM. +var RESERVED = 0; // A simple string attribute. +// Attributes that aren't in the filter are presumed to have this type. + +var STRING = 1; // A string attribute that accepts booleans in React. In HTML, these are called +// "enumerated" attributes with "true" and "false" as possible values. +// When true, it should be set to a "true" string. +// When false, it should be set to a "false" string. + +var BOOLEANISH_STRING = 2; // A real boolean attribute. +// When true, it should be present (set either to an empty string or its name). +// When false, it should be omitted. + +var BOOLEAN = 3; // An attribute that can be used as a flag as well as with a value. +// When true, it should be present (set either to an empty string or its name). +// When false, it should be omitted. +// For any other value, should be present with that value. + +var OVERLOADED_BOOLEAN = 4; // An attribute that must be numeric or parse as a numeric. +// When falsy, it should be removed. + +var NUMERIC = 5; // An attribute that must be positive numeric or parse as a positive numeric. +// When falsy, it should be removed. + +var POSITIVE_NUMERIC = 6; + +/* eslint-disable max-len */ +var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; +/* eslint-enable max-len */ + +var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; +var VALID_ATTRIBUTE_NAME_REGEX = new RegExp('^[' + ATTRIBUTE_NAME_START_CHAR + '][' + ATTRIBUTE_NAME_CHAR + ']*$'); +var illegalAttributeNameCache = {}; +var validatedAttributeNameCache = {}; +function isAttributeNameSafe(attributeName) { + if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { + return true; + } + + if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { + return false; + } + + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { + validatedAttributeNameCache[attributeName] = true; + return true; + } + + illegalAttributeNameCache[attributeName] = true; + + { + error('Invalid attribute name: `%s`', attributeName); + } + + return false; +} +function shouldRemoveAttributeWithWarning(name, value, propertyInfo, isCustomComponentTag) { + if (propertyInfo !== null && propertyInfo.type === RESERVED) { + return false; + } + + switch (typeof value) { + case 'function': // $FlowIssue symbol is perfectly valid here + + case 'symbol': + // eslint-disable-line + return true; + + case 'boolean': + { + if (isCustomComponentTag) { + return false; + } + + if (propertyInfo !== null) { + return !propertyInfo.acceptsBooleans; + } else { + var prefix = name.toLowerCase().slice(0, 5); + return prefix !== 'data-' && prefix !== 'aria-'; + } + } + + default: + return false; + } +} +function getPropertyInfo(name) { + return properties.hasOwnProperty(name) ? properties[name] : null; +} + +function PropertyInfoRecord(name, type, mustUseProperty, attributeName, attributeNamespace, sanitizeURL, removeEmptyString) { + this.acceptsBooleans = type === BOOLEANISH_STRING || type === BOOLEAN || type === OVERLOADED_BOOLEAN; + this.attributeName = attributeName; + this.attributeNamespace = attributeNamespace; + this.mustUseProperty = mustUseProperty; + this.propertyName = name; + this.type = type; + this.sanitizeURL = sanitizeURL; + this.removeEmptyString = removeEmptyString; +} // When adding attributes to this list, be sure to also add them to +// the `possibleStandardNames` module to ensure casing and incorrect +// name warnings. + + +var properties = {}; // These props are reserved by React. They shouldn't be written to the DOM. + +var reservedProps = ['children', 'dangerouslySetInnerHTML', // TODO: This prevents the assignment of defaultValue to regular +// elements (not just inputs). Now that ReactDOMInput assigns to the +// defaultValue property -- do we need this? +'defaultValue', 'defaultChecked', 'innerHTML', 'suppressContentEditableWarning', 'suppressHydrationWarning', 'style']; + +reservedProps.forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, RESERVED, false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // A few React string attributes have a different name. +// This is a mapping from React prop names to the attribute names. + +[['acceptCharset', 'accept-charset'], ['className', 'class'], ['htmlFor', 'for'], ['httpEquiv', 'http-equiv']].forEach(function (_ref) { + var name = _ref[0], + attributeName = _ref[1]; + properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty + attributeName, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are "enumerated" HTML attributes that accept "true" and "false". +// In React, we let users pass `true` and `false` even though technically +// these aren't boolean attributes (they are coerced to strings). + +['contentEditable', 'draggable', 'spellCheck', 'value'].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are "enumerated" SVG attributes that accept "true" and "false". +// In React, we let users pass `true` and `false` even though technically +// these aren't boolean attributes (they are coerced to strings). +// Since these are SVG attributes, their attribute names are case-sensitive. + +['autoReverse', 'externalResourcesRequired', 'focusable', 'preserveAlpha'].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, BOOLEANISH_STRING, false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are HTML boolean attributes. + +['allowFullScreen', 'async', // Note: there is a special case that prevents it from being written to the DOM +// on the client side because the browsers are inconsistent. Instead we call focus(). +'autoFocus', 'autoPlay', 'controls', 'default', 'defer', 'disabled', 'disablePictureInPicture', 'disableRemotePlayback', 'formNoValidate', 'hidden', 'loop', 'noModule', 'noValidate', 'open', 'playsInline', 'readOnly', 'required', 'reversed', 'scoped', 'seamless', // Microdata +'itemScope'].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, BOOLEAN, false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are the few React props that we set as DOM properties +// rather than attributes. These are all booleans. + +['checked', // Note: `option.selected` is not updated if `select.multiple` is +// disabled with `removeAttribute`. We have special logic for handling this. +'multiple', 'muted', 'selected' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, BOOLEAN, true, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are HTML attributes that are "overloaded booleans": they behave like +// booleans, but can also accept a string value. + +['capture', 'download' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, OVERLOADED_BOOLEAN, false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are HTML attributes that must be positive numbers. + +['cols', 'rows', 'size', 'span' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, POSITIVE_NUMERIC, false, // mustUseProperty + name, // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These are HTML attributes that must be numbers. + +['rowSpan', 'start'].forEach(function (name) { + properties[name] = new PropertyInfoRecord(name, NUMERIC, false, // mustUseProperty + name.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); +var CAMELIZE = /[\-\:]([a-z])/g; + +var capitalize = function (token) { + return token[1].toUpperCase(); +}; // This is a list of all SVG attributes that need special casing, namespacing, +// or boolean value assignment. Regular attributes that just accept strings +// and have the same names are omitted, just like in the HTML attribute filter. +// Some of these attributes can be hard to find. This list was created by +// scraping the MDN documentation. + + +['accent-height', 'alignment-baseline', 'arabic-form', 'baseline-shift', 'cap-height', 'clip-path', 'clip-rule', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'dominant-baseline', 'enable-background', 'fill-opacity', 'fill-rule', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-name', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'horiz-adv-x', 'horiz-origin-x', 'image-rendering', 'letter-spacing', 'lighting-color', 'marker-end', 'marker-mid', 'marker-start', 'overline-position', 'overline-thickness', 'paint-order', 'panose-1', 'pointer-events', 'rendering-intent', 'shape-rendering', 'stop-color', 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-decoration', 'text-rendering', 'underline-position', 'underline-thickness', 'unicode-bidi', 'unicode-range', 'units-per-em', 'v-alphabetic', 'v-hanging', 'v-ideographic', 'v-mathematical', 'vector-effect', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'word-spacing', 'writing-mode', 'xmlns:xlink', 'x-height' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (attributeName) { + var name = attributeName.replace(CAMELIZE, capitalize); + properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty + attributeName, null, // attributeNamespace + false, // sanitizeURL + false); +}); // String SVG attributes with the xlink namespace. + +['xlink:actuate', 'xlink:arcrole', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (attributeName) { + var name = attributeName.replace(CAMELIZE, capitalize); + properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty + attributeName, 'http://www.w3.org/1999/xlink', false, // sanitizeURL + false); +}); // String SVG attributes with the xml namespace. + +['xml:base', 'xml:lang', 'xml:space' // NOTE: if you add a camelCased prop to this list, +// you'll need to set attributeName to name.toLowerCase() +// instead in the assignment below. +].forEach(function (attributeName) { + var name = attributeName.replace(CAMELIZE, capitalize); + properties[name] = new PropertyInfoRecord(name, STRING, false, // mustUseProperty + attributeName, 'http://www.w3.org/XML/1998/namespace', false, // sanitizeURL + false); +}); // These attribute exists both in HTML and SVG. +// The attribute name is case-sensitive in SVG so we can't just use +// the React name like we do for attributes that exist only in HTML. + +['tabIndex', 'crossOrigin'].forEach(function (attributeName) { + properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty + attributeName.toLowerCase(), // attributeName + null, // attributeNamespace + false, // sanitizeURL + false); +}); // These attributes accept URLs. These must not allow javascript: URLS. +// These will also need to accept Trusted Types object in the future. + +var xlinkHref = 'xlinkHref'; +properties[xlinkHref] = new PropertyInfoRecord('xlinkHref', STRING, false, // mustUseProperty +'xlink:href', 'http://www.w3.org/1999/xlink', true, // sanitizeURL +false); +['src', 'href', 'action', 'formAction'].forEach(function (attributeName) { + properties[attributeName] = new PropertyInfoRecord(attributeName, STRING, false, // mustUseProperty + attributeName.toLowerCase(), // attributeName + null, // attributeNamespace + true, // sanitizeURL + true); +}); + +/** + * CSS properties which accept numbers but are not in units of "px". + */ +var isUnitlessNumber = { + animationIterationCount: true, + aspectRatio: true, + borderImageOutset: true, + borderImageSlice: true, + borderImageWidth: true, + boxFlex: true, + boxFlexGroup: true, + boxOrdinalGroup: true, + columnCount: true, + columns: true, + flex: true, + flexGrow: true, + flexPositive: true, + flexShrink: true, + flexNegative: true, + flexOrder: true, + gridArea: true, + gridRow: true, + gridRowEnd: true, + gridRowSpan: true, + gridRowStart: true, + gridColumn: true, + gridColumnEnd: true, + gridColumnSpan: true, + gridColumnStart: true, + fontWeight: true, + lineClamp: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + tabSize: true, + widows: true, + zIndex: true, + zoom: true, + // SVG-related properties + fillOpacity: true, + floodOpacity: true, + stopOpacity: true, + strokeDasharray: true, + strokeDashoffset: true, + strokeMiterlimit: true, + strokeOpacity: true, + strokeWidth: true +}; +/** + * @param {string} prefix vendor-specific prefix, eg: Webkit + * @param {string} key style name, eg: transitionDuration + * @return {string} style name prefixed with `prefix`, properly camelCased, eg: + * WebkitTransitionDuration + */ + +function prefixKey(prefix, key) { + return prefix + key.charAt(0).toUpperCase() + key.substring(1); +} +/** + * Support style names that may come passed in prefixed by adding permutations + * of vendor prefixes. + */ + + +var prefixes = ['Webkit', 'ms', 'Moz', 'O']; // Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an +// infinite loop, because it iterates over the newly added props too. + +Object.keys(isUnitlessNumber).forEach(function (prop) { + prefixes.forEach(function (prefix) { + isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop]; + }); +}); + +var hasReadOnlyValue = { + button: true, + checkbox: true, + image: true, + hidden: true, + radio: true, + reset: true, + submit: true +}; +function checkControlledValueProps(tagName, props) { + { + if (!(hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null)) { + error('You provided a `value` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultValue`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); + } + + if (!(props.onChange || props.readOnly || props.disabled || props.checked == null)) { + error('You provided a `checked` prop to a form field without an ' + '`onChange` handler. This will render a read-only field. If ' + 'the field should be mutable use `defaultChecked`. Otherwise, ' + 'set either `onChange` or `readOnly`.'); + } + } +} + +function isCustomComponent(tagName, props) { + if (tagName.indexOf('-') === -1) { + return typeof props.is === 'string'; + } + + switch (tagName) { + // These are reserved SVG and MathML elements. + // We don't mind this list too much because we expect it to never grow. + // The alternative is to track the namespace in a few places which is convoluted. + // https://w3c.github.io/webcomponents/spec/custom/#custom-elements-core-concepts + case 'annotation-xml': + case 'color-profile': + case 'font-face': + case 'font-face-src': + case 'font-face-uri': + case 'font-face-format': + case 'font-face-name': + case 'missing-glyph': + return false; + + default: + return true; + } +} + +var ariaProperties = { + 'aria-current': 0, + // state + 'aria-description': 0, + 'aria-details': 0, + 'aria-disabled': 0, + // state + 'aria-hidden': 0, + // state + 'aria-invalid': 0, + // state + 'aria-keyshortcuts': 0, + 'aria-label': 0, + 'aria-roledescription': 0, + // Widget Attributes + 'aria-autocomplete': 0, + 'aria-checked': 0, + 'aria-expanded': 0, + 'aria-haspopup': 0, + 'aria-level': 0, + 'aria-modal': 0, + 'aria-multiline': 0, + 'aria-multiselectable': 0, + 'aria-orientation': 0, + 'aria-placeholder': 0, + 'aria-pressed': 0, + 'aria-readonly': 0, + 'aria-required': 0, + 'aria-selected': 0, + 'aria-sort': 0, + 'aria-valuemax': 0, + 'aria-valuemin': 0, + 'aria-valuenow': 0, + 'aria-valuetext': 0, + // Live Region Attributes + 'aria-atomic': 0, + 'aria-busy': 0, + 'aria-live': 0, + 'aria-relevant': 0, + // Drag-and-Drop Attributes + 'aria-dropeffect': 0, + 'aria-grabbed': 0, + // Relationship Attributes + 'aria-activedescendant': 0, + 'aria-colcount': 0, + 'aria-colindex': 0, + 'aria-colspan': 0, + 'aria-controls': 0, + 'aria-describedby': 0, + 'aria-errormessage': 0, + 'aria-flowto': 0, + 'aria-labelledby': 0, + 'aria-owns': 0, + 'aria-posinset': 0, + 'aria-rowcount': 0, + 'aria-rowindex': 0, + 'aria-rowspan': 0, + 'aria-setsize': 0 +}; + +var warnedProperties = {}; +var rARIA = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); +var rARIACamel = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); + +function validateProperty(tagName, name) { + { + if (hasOwnProperty.call(warnedProperties, name) && warnedProperties[name]) { + return true; + } + + if (rARIACamel.test(name)) { + var ariaName = 'aria-' + name.slice(4).toLowerCase(); + var correctName = ariaProperties.hasOwnProperty(ariaName) ? ariaName : null; // If this is an aria-* attribute, but is not listed in the known DOM + // DOM properties, then it is an invalid aria-* attribute. + + if (correctName == null) { + error('Invalid ARIA attribute `%s`. ARIA attributes follow the pattern aria-* and must be lowercase.', name); + + warnedProperties[name] = true; + return true; + } // aria-* attributes should be lowercase; suggest the lowercase version. + + + if (name !== correctName) { + error('Invalid ARIA attribute `%s`. Did you mean `%s`?', name, correctName); + + warnedProperties[name] = true; + return true; + } + } + + if (rARIA.test(name)) { + var lowerCasedName = name.toLowerCase(); + var standardName = ariaProperties.hasOwnProperty(lowerCasedName) ? lowerCasedName : null; // If this is an aria-* attribute, but is not listed in the known DOM + // DOM properties, then it is an invalid aria-* attribute. + + if (standardName == null) { + warnedProperties[name] = true; + return false; + } // aria-* attributes should be lowercase; suggest the lowercase version. + + + if (name !== standardName) { + error('Unknown ARIA attribute `%s`. Did you mean `%s`?', name, standardName); + + warnedProperties[name] = true; + return true; + } + } + } + + return true; +} + +function warnInvalidARIAProps(type, props) { + { + var invalidProps = []; + + for (var key in props) { + var isValid = validateProperty(type, key); + + if (!isValid) { + invalidProps.push(key); + } + } + + var unknownPropString = invalidProps.map(function (prop) { + return '`' + prop + '`'; + }).join(', '); + + if (invalidProps.length === 1) { + error('Invalid aria prop %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); + } else if (invalidProps.length > 1) { + error('Invalid aria props %s on <%s> tag. ' + 'For details, see https://reactjs.org/link/invalid-aria-props', unknownPropString, type); + } + } +} + +function validateProperties(type, props) { + if (isCustomComponent(type, props)) { + return; + } + + warnInvalidARIAProps(type, props); +} + +var didWarnValueNull = false; +function validateProperties$1(type, props) { + { + if (type !== 'input' && type !== 'textarea' && type !== 'select') { + return; + } + + if (props != null && props.value === null && !didWarnValueNull) { + didWarnValueNull = true; + + if (type === 'select' && props.multiple) { + error('`value` prop on `%s` should not be null. ' + 'Consider using an empty array when `multiple` is set to `true` ' + 'to clear the component or `undefined` for uncontrolled components.', type); + } else { + error('`value` prop on `%s` should not be null. ' + 'Consider using an empty string to clear the component or `undefined` ' + 'for uncontrolled components.', type); + } + } + } +} + +// When adding attributes to the HTML or SVG allowed attribute list, be sure to +// also add them to this module to ensure casing and incorrect name +// warnings. +var possibleStandardNames = { + // HTML + accept: 'accept', + acceptcharset: 'acceptCharset', + 'accept-charset': 'acceptCharset', + accesskey: 'accessKey', + action: 'action', + allowfullscreen: 'allowFullScreen', + alt: 'alt', + as: 'as', + async: 'async', + autocapitalize: 'autoCapitalize', + autocomplete: 'autoComplete', + autocorrect: 'autoCorrect', + autofocus: 'autoFocus', + autoplay: 'autoPlay', + autosave: 'autoSave', + capture: 'capture', + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing', + challenge: 'challenge', + charset: 'charSet', + checked: 'checked', + children: 'children', + cite: 'cite', + class: 'className', + classid: 'classID', + classname: 'className', + cols: 'cols', + colspan: 'colSpan', + content: 'content', + contenteditable: 'contentEditable', + contextmenu: 'contextMenu', + controls: 'controls', + controlslist: 'controlsList', + coords: 'coords', + crossorigin: 'crossOrigin', + dangerouslysetinnerhtml: 'dangerouslySetInnerHTML', + data: 'data', + datetime: 'dateTime', + default: 'default', + defaultchecked: 'defaultChecked', + defaultvalue: 'defaultValue', + defer: 'defer', + dir: 'dir', + disabled: 'disabled', + disablepictureinpicture: 'disablePictureInPicture', + disableremoteplayback: 'disableRemotePlayback', + download: 'download', + draggable: 'draggable', + enctype: 'encType', + enterkeyhint: 'enterKeyHint', + for: 'htmlFor', + form: 'form', + formmethod: 'formMethod', + formaction: 'formAction', + formenctype: 'formEncType', + formnovalidate: 'formNoValidate', + formtarget: 'formTarget', + frameborder: 'frameBorder', + headers: 'headers', + height: 'height', + hidden: 'hidden', + high: 'high', + href: 'href', + hreflang: 'hrefLang', + htmlfor: 'htmlFor', + httpequiv: 'httpEquiv', + 'http-equiv': 'httpEquiv', + icon: 'icon', + id: 'id', + imagesizes: 'imageSizes', + imagesrcset: 'imageSrcSet', + innerhtml: 'innerHTML', + inputmode: 'inputMode', + integrity: 'integrity', + is: 'is', + itemid: 'itemID', + itemprop: 'itemProp', + itemref: 'itemRef', + itemscope: 'itemScope', + itemtype: 'itemType', + keyparams: 'keyParams', + keytype: 'keyType', + kind: 'kind', + label: 'label', + lang: 'lang', + list: 'list', + loop: 'loop', + low: 'low', + manifest: 'manifest', + marginwidth: 'marginWidth', + marginheight: 'marginHeight', + max: 'max', + maxlength: 'maxLength', + media: 'media', + mediagroup: 'mediaGroup', + method: 'method', + min: 'min', + minlength: 'minLength', + multiple: 'multiple', + muted: 'muted', + name: 'name', + nomodule: 'noModule', + nonce: 'nonce', + novalidate: 'noValidate', + open: 'open', + optimum: 'optimum', + pattern: 'pattern', + placeholder: 'placeholder', + playsinline: 'playsInline', + poster: 'poster', + preload: 'preload', + profile: 'profile', + radiogroup: 'radioGroup', + readonly: 'readOnly', + referrerpolicy: 'referrerPolicy', + rel: 'rel', + required: 'required', + reversed: 'reversed', + role: 'role', + rows: 'rows', + rowspan: 'rowSpan', + sandbox: 'sandbox', + scope: 'scope', + scoped: 'scoped', + scrolling: 'scrolling', + seamless: 'seamless', + selected: 'selected', + shape: 'shape', + size: 'size', + sizes: 'sizes', + span: 'span', + spellcheck: 'spellCheck', + src: 'src', + srcdoc: 'srcDoc', + srclang: 'srcLang', + srcset: 'srcSet', + start: 'start', + step: 'step', + style: 'style', + summary: 'summary', + tabindex: 'tabIndex', + target: 'target', + title: 'title', + type: 'type', + usemap: 'useMap', + value: 'value', + width: 'width', + wmode: 'wmode', + wrap: 'wrap', + // SVG + about: 'about', + accentheight: 'accentHeight', + 'accent-height': 'accentHeight', + accumulate: 'accumulate', + additive: 'additive', + alignmentbaseline: 'alignmentBaseline', + 'alignment-baseline': 'alignmentBaseline', + allowreorder: 'allowReorder', + alphabetic: 'alphabetic', + amplitude: 'amplitude', + arabicform: 'arabicForm', + 'arabic-form': 'arabicForm', + ascent: 'ascent', + attributename: 'attributeName', + attributetype: 'attributeType', + autoreverse: 'autoReverse', + azimuth: 'azimuth', + basefrequency: 'baseFrequency', + baselineshift: 'baselineShift', + 'baseline-shift': 'baselineShift', + baseprofile: 'baseProfile', + bbox: 'bbox', + begin: 'begin', + bias: 'bias', + by: 'by', + calcmode: 'calcMode', + capheight: 'capHeight', + 'cap-height': 'capHeight', + clip: 'clip', + clippath: 'clipPath', + 'clip-path': 'clipPath', + clippathunits: 'clipPathUnits', + cliprule: 'clipRule', + 'clip-rule': 'clipRule', + color: 'color', + colorinterpolation: 'colorInterpolation', + 'color-interpolation': 'colorInterpolation', + colorinterpolationfilters: 'colorInterpolationFilters', + 'color-interpolation-filters': 'colorInterpolationFilters', + colorprofile: 'colorProfile', + 'color-profile': 'colorProfile', + colorrendering: 'colorRendering', + 'color-rendering': 'colorRendering', + contentscripttype: 'contentScriptType', + contentstyletype: 'contentStyleType', + cursor: 'cursor', + cx: 'cx', + cy: 'cy', + d: 'd', + datatype: 'datatype', + decelerate: 'decelerate', + descent: 'descent', + diffuseconstant: 'diffuseConstant', + direction: 'direction', + display: 'display', + divisor: 'divisor', + dominantbaseline: 'dominantBaseline', + 'dominant-baseline': 'dominantBaseline', + dur: 'dur', + dx: 'dx', + dy: 'dy', + edgemode: 'edgeMode', + elevation: 'elevation', + enablebackground: 'enableBackground', + 'enable-background': 'enableBackground', + end: 'end', + exponent: 'exponent', + externalresourcesrequired: 'externalResourcesRequired', + fill: 'fill', + fillopacity: 'fillOpacity', + 'fill-opacity': 'fillOpacity', + fillrule: 'fillRule', + 'fill-rule': 'fillRule', + filter: 'filter', + filterres: 'filterRes', + filterunits: 'filterUnits', + floodopacity: 'floodOpacity', + 'flood-opacity': 'floodOpacity', + floodcolor: 'floodColor', + 'flood-color': 'floodColor', + focusable: 'focusable', + fontfamily: 'fontFamily', + 'font-family': 'fontFamily', + fontsize: 'fontSize', + 'font-size': 'fontSize', + fontsizeadjust: 'fontSizeAdjust', + 'font-size-adjust': 'fontSizeAdjust', + fontstretch: 'fontStretch', + 'font-stretch': 'fontStretch', + fontstyle: 'fontStyle', + 'font-style': 'fontStyle', + fontvariant: 'fontVariant', + 'font-variant': 'fontVariant', + fontweight: 'fontWeight', + 'font-weight': 'fontWeight', + format: 'format', + from: 'from', + fx: 'fx', + fy: 'fy', + g1: 'g1', + g2: 'g2', + glyphname: 'glyphName', + 'glyph-name': 'glyphName', + glyphorientationhorizontal: 'glyphOrientationHorizontal', + 'glyph-orientation-horizontal': 'glyphOrientationHorizontal', + glyphorientationvertical: 'glyphOrientationVertical', + 'glyph-orientation-vertical': 'glyphOrientationVertical', + glyphref: 'glyphRef', + gradienttransform: 'gradientTransform', + gradientunits: 'gradientUnits', + hanging: 'hanging', + horizadvx: 'horizAdvX', + 'horiz-adv-x': 'horizAdvX', + horizoriginx: 'horizOriginX', + 'horiz-origin-x': 'horizOriginX', + ideographic: 'ideographic', + imagerendering: 'imageRendering', + 'image-rendering': 'imageRendering', + in2: 'in2', + in: 'in', + inlist: 'inlist', + intercept: 'intercept', + k1: 'k1', + k2: 'k2', + k3: 'k3', + k4: 'k4', + k: 'k', + kernelmatrix: 'kernelMatrix', + kernelunitlength: 'kernelUnitLength', + kerning: 'kerning', + keypoints: 'keyPoints', + keysplines: 'keySplines', + keytimes: 'keyTimes', + lengthadjust: 'lengthAdjust', + letterspacing: 'letterSpacing', + 'letter-spacing': 'letterSpacing', + lightingcolor: 'lightingColor', + 'lighting-color': 'lightingColor', + limitingconeangle: 'limitingConeAngle', + local: 'local', + markerend: 'markerEnd', + 'marker-end': 'markerEnd', + markerheight: 'markerHeight', + markermid: 'markerMid', + 'marker-mid': 'markerMid', + markerstart: 'markerStart', + 'marker-start': 'markerStart', + markerunits: 'markerUnits', + markerwidth: 'markerWidth', + mask: 'mask', + maskcontentunits: 'maskContentUnits', + maskunits: 'maskUnits', + mathematical: 'mathematical', + mode: 'mode', + numoctaves: 'numOctaves', + offset: 'offset', + opacity: 'opacity', + operator: 'operator', + order: 'order', + orient: 'orient', + orientation: 'orientation', + origin: 'origin', + overflow: 'overflow', + overlineposition: 'overlinePosition', + 'overline-position': 'overlinePosition', + overlinethickness: 'overlineThickness', + 'overline-thickness': 'overlineThickness', + paintorder: 'paintOrder', + 'paint-order': 'paintOrder', + panose1: 'panose1', + 'panose-1': 'panose1', + pathlength: 'pathLength', + patterncontentunits: 'patternContentUnits', + patterntransform: 'patternTransform', + patternunits: 'patternUnits', + pointerevents: 'pointerEvents', + 'pointer-events': 'pointerEvents', + points: 'points', + pointsatx: 'pointsAtX', + pointsaty: 'pointsAtY', + pointsatz: 'pointsAtZ', + prefix: 'prefix', + preservealpha: 'preserveAlpha', + preserveaspectratio: 'preserveAspectRatio', + primitiveunits: 'primitiveUnits', + property: 'property', + r: 'r', + radius: 'radius', + refx: 'refX', + refy: 'refY', + renderingintent: 'renderingIntent', + 'rendering-intent': 'renderingIntent', + repeatcount: 'repeatCount', + repeatdur: 'repeatDur', + requiredextensions: 'requiredExtensions', + requiredfeatures: 'requiredFeatures', + resource: 'resource', + restart: 'restart', + result: 'result', + results: 'results', + rotate: 'rotate', + rx: 'rx', + ry: 'ry', + scale: 'scale', + security: 'security', + seed: 'seed', + shaperendering: 'shapeRendering', + 'shape-rendering': 'shapeRendering', + slope: 'slope', + spacing: 'spacing', + specularconstant: 'specularConstant', + specularexponent: 'specularExponent', + speed: 'speed', + spreadmethod: 'spreadMethod', + startoffset: 'startOffset', + stddeviation: 'stdDeviation', + stemh: 'stemh', + stemv: 'stemv', + stitchtiles: 'stitchTiles', + stopcolor: 'stopColor', + 'stop-color': 'stopColor', + stopopacity: 'stopOpacity', + 'stop-opacity': 'stopOpacity', + strikethroughposition: 'strikethroughPosition', + 'strikethrough-position': 'strikethroughPosition', + strikethroughthickness: 'strikethroughThickness', + 'strikethrough-thickness': 'strikethroughThickness', + string: 'string', + stroke: 'stroke', + strokedasharray: 'strokeDasharray', + 'stroke-dasharray': 'strokeDasharray', + strokedashoffset: 'strokeDashoffset', + 'stroke-dashoffset': 'strokeDashoffset', + strokelinecap: 'strokeLinecap', + 'stroke-linecap': 'strokeLinecap', + strokelinejoin: 'strokeLinejoin', + 'stroke-linejoin': 'strokeLinejoin', + strokemiterlimit: 'strokeMiterlimit', + 'stroke-miterlimit': 'strokeMiterlimit', + strokewidth: 'strokeWidth', + 'stroke-width': 'strokeWidth', + strokeopacity: 'strokeOpacity', + 'stroke-opacity': 'strokeOpacity', + suppresscontenteditablewarning: 'suppressContentEditableWarning', + suppresshydrationwarning: 'suppressHydrationWarning', + surfacescale: 'surfaceScale', + systemlanguage: 'systemLanguage', + tablevalues: 'tableValues', + targetx: 'targetX', + targety: 'targetY', + textanchor: 'textAnchor', + 'text-anchor': 'textAnchor', + textdecoration: 'textDecoration', + 'text-decoration': 'textDecoration', + textlength: 'textLength', + textrendering: 'textRendering', + 'text-rendering': 'textRendering', + to: 'to', + transform: 'transform', + typeof: 'typeof', + u1: 'u1', + u2: 'u2', + underlineposition: 'underlinePosition', + 'underline-position': 'underlinePosition', + underlinethickness: 'underlineThickness', + 'underline-thickness': 'underlineThickness', + unicode: 'unicode', + unicodebidi: 'unicodeBidi', + 'unicode-bidi': 'unicodeBidi', + unicoderange: 'unicodeRange', + 'unicode-range': 'unicodeRange', + unitsperem: 'unitsPerEm', + 'units-per-em': 'unitsPerEm', + unselectable: 'unselectable', + valphabetic: 'vAlphabetic', + 'v-alphabetic': 'vAlphabetic', + values: 'values', + vectoreffect: 'vectorEffect', + 'vector-effect': 'vectorEffect', + version: 'version', + vertadvy: 'vertAdvY', + 'vert-adv-y': 'vertAdvY', + vertoriginx: 'vertOriginX', + 'vert-origin-x': 'vertOriginX', + vertoriginy: 'vertOriginY', + 'vert-origin-y': 'vertOriginY', + vhanging: 'vHanging', + 'v-hanging': 'vHanging', + videographic: 'vIdeographic', + 'v-ideographic': 'vIdeographic', + viewbox: 'viewBox', + viewtarget: 'viewTarget', + visibility: 'visibility', + vmathematical: 'vMathematical', + 'v-mathematical': 'vMathematical', + vocab: 'vocab', + widths: 'widths', + wordspacing: 'wordSpacing', + 'word-spacing': 'wordSpacing', + writingmode: 'writingMode', + 'writing-mode': 'writingMode', + x1: 'x1', + x2: 'x2', + x: 'x', + xchannelselector: 'xChannelSelector', + xheight: 'xHeight', + 'x-height': 'xHeight', + xlinkactuate: 'xlinkActuate', + 'xlink:actuate': 'xlinkActuate', + xlinkarcrole: 'xlinkArcrole', + 'xlink:arcrole': 'xlinkArcrole', + xlinkhref: 'xlinkHref', + 'xlink:href': 'xlinkHref', + xlinkrole: 'xlinkRole', + 'xlink:role': 'xlinkRole', + xlinkshow: 'xlinkShow', + 'xlink:show': 'xlinkShow', + xlinktitle: 'xlinkTitle', + 'xlink:title': 'xlinkTitle', + xlinktype: 'xlinkType', + 'xlink:type': 'xlinkType', + xmlbase: 'xmlBase', + 'xml:base': 'xmlBase', + xmllang: 'xmlLang', + 'xml:lang': 'xmlLang', + xmlns: 'xmlns', + 'xml:space': 'xmlSpace', + xmlnsxlink: 'xmlnsXlink', + 'xmlns:xlink': 'xmlnsXlink', + xmlspace: 'xmlSpace', + y1: 'y1', + y2: 'y2', + y: 'y', + ychannelselector: 'yChannelSelector', + z: 'z', + zoomandpan: 'zoomAndPan' +}; + +var validateProperty$1 = function () {}; + +{ + var warnedProperties$1 = {}; + var EVENT_NAME_REGEX = /^on./; + var INVALID_EVENT_NAME_REGEX = /^on[^A-Z]/; + var rARIA$1 = new RegExp('^(aria)-[' + ATTRIBUTE_NAME_CHAR + ']*$'); + var rARIACamel$1 = new RegExp('^(aria)[A-Z][' + ATTRIBUTE_NAME_CHAR + ']*$'); + + validateProperty$1 = function (tagName, name, value, eventRegistry) { + if (hasOwnProperty.call(warnedProperties$1, name) && warnedProperties$1[name]) { + return true; + } + + var lowerCasedName = name.toLowerCase(); + + if (lowerCasedName === 'onfocusin' || lowerCasedName === 'onfocusout') { + error('React uses onFocus and onBlur instead of onFocusIn and onFocusOut. ' + 'All React events are normalized to bubble, so onFocusIn and onFocusOut ' + 'are not needed/supported by React.'); + + warnedProperties$1[name] = true; + return true; + } // We can't rely on the event system being injected on the server. + + + if (eventRegistry != null) { + var registrationNameDependencies = eventRegistry.registrationNameDependencies, + possibleRegistrationNames = eventRegistry.possibleRegistrationNames; + + if (registrationNameDependencies.hasOwnProperty(name)) { + return true; + } + + var registrationName = possibleRegistrationNames.hasOwnProperty(lowerCasedName) ? possibleRegistrationNames[lowerCasedName] : null; + + if (registrationName != null) { + error('Invalid event handler property `%s`. Did you mean `%s`?', name, registrationName); + + warnedProperties$1[name] = true; + return true; + } + + if (EVENT_NAME_REGEX.test(name)) { + error('Unknown event handler property `%s`. It will be ignored.', name); + + warnedProperties$1[name] = true; + return true; + } + } else if (EVENT_NAME_REGEX.test(name)) { + // If no event plugins have been injected, we are in a server environment. + // So we can't tell if the event name is correct for sure, but we can filter + // out known bad ones like `onclick`. We can't suggest a specific replacement though. + if (INVALID_EVENT_NAME_REGEX.test(name)) { + error('Invalid event handler property `%s`. ' + 'React events use the camelCase naming convention, for example `onClick`.', name); + } + + warnedProperties$1[name] = true; + return true; + } // Let the ARIA attribute hook validate ARIA attributes + + + if (rARIA$1.test(name) || rARIACamel$1.test(name)) { + return true; + } + + if (lowerCasedName === 'innerhtml') { + error('Directly setting property `innerHTML` is not permitted. ' + 'For more information, lookup documentation on `dangerouslySetInnerHTML`.'); + + warnedProperties$1[name] = true; + return true; + } + + if (lowerCasedName === 'aria') { + error('The `aria` attribute is reserved for future use in React. ' + 'Pass individual `aria-` attributes instead.'); + + warnedProperties$1[name] = true; + return true; + } + + if (lowerCasedName === 'is' && value !== null && value !== undefined && typeof value !== 'string') { + error('Received a `%s` for a string attribute `is`. If this is expected, cast ' + 'the value to a string.', typeof value); + + warnedProperties$1[name] = true; + return true; + } + + if (typeof value === 'number' && isNaN(value)) { + error('Received NaN for the `%s` attribute. If this is expected, cast ' + 'the value to a string.', name); + + warnedProperties$1[name] = true; + return true; + } + + var propertyInfo = getPropertyInfo(name); + var isReserved = propertyInfo !== null && propertyInfo.type === RESERVED; // Known attributes should match the casing specified in the property config. + + if (possibleStandardNames.hasOwnProperty(lowerCasedName)) { + var standardName = possibleStandardNames[lowerCasedName]; + + if (standardName !== name) { + error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName); + + warnedProperties$1[name] = true; + return true; + } + } else if (!isReserved && name !== lowerCasedName) { + // Unknown attributes should have lowercase casing since that's how they + // will be cased anyway with server rendering. + error('React does not recognize the `%s` prop on a DOM element. If you ' + 'intentionally want it to appear in the DOM as a custom ' + 'attribute, spell it as lowercase `%s` instead. ' + 'If you accidentally passed it from a parent component, remove ' + 'it from the DOM element.', name, lowerCasedName); + + warnedProperties$1[name] = true; + return true; + } + + if (typeof value === 'boolean' && shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { + if (value) { + error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.', value, name, name, value, name); + } else { + error('Received `%s` for a non-boolean attribute `%s`.\n\n' + 'If you want to write it to the DOM, pass a string instead: ' + '%s="%s" or %s={value.toString()}.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', value, name, name, value, name, name, name); + } + + warnedProperties$1[name] = true; + return true; + } // Now that we've validated casing, do not validate + // data types for reserved props + + + if (isReserved) { + return true; + } // Warn when a known attribute is a bad type + + + if (shouldRemoveAttributeWithWarning(name, value, propertyInfo, false)) { + warnedProperties$1[name] = true; + return false; + } // Warn when passing the strings 'false' or 'true' into a boolean prop + + + if ((value === 'false' || value === 'true') && propertyInfo !== null && propertyInfo.type === BOOLEAN) { + error('Received the string `%s` for the boolean attribute `%s`. ' + '%s ' + 'Did you mean %s={%s}?', value, name, value === 'false' ? 'The browser will interpret it as a truthy value.' : 'Although this works, it will not work as expected if you pass the string "false".', name, value); + + warnedProperties$1[name] = true; + return true; + } + + return true; + }; +} + +var warnUnknownProperties = function (type, props, eventRegistry) { + { + var unknownProps = []; + + for (var key in props) { + var isValid = validateProperty$1(type, key, props[key], eventRegistry); + + if (!isValid) { + unknownProps.push(key); + } + } + + var unknownPropString = unknownProps.map(function (prop) { + return '`' + prop + '`'; + }).join(', '); + + if (unknownProps.length === 1) { + error('Invalid value for prop %s on <%s> tag. Either remove it from the element, ' + 'or pass a string or number value to keep it in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); + } else if (unknownProps.length > 1) { + error('Invalid values for props %s on <%s> tag. Either remove them from the element, ' + 'or pass a string or number value to keep them in the DOM. ' + 'For details, see https://reactjs.org/link/attribute-behavior ', unknownPropString, type); + } + } +}; + +function validateProperties$2(type, props, eventRegistry) { + if (isCustomComponent(type, props)) { + return; + } + + warnUnknownProperties(type, props, eventRegistry); +} + +var warnValidStyle = function () {}; + +{ + // 'msTransform' is correct, but the other prefixes should be capitalized + var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/; + var msPattern = /^-ms-/; + var hyphenPattern = /-(.)/g; // style values shouldn't contain a semicolon + + var badStyleValueWithSemicolonPattern = /;\s*$/; + var warnedStyleNames = {}; + var warnedStyleValues = {}; + var warnedForNaNValue = false; + var warnedForInfinityValue = false; + + var camelize = function (string) { + return string.replace(hyphenPattern, function (_, character) { + return character.toUpperCase(); + }); + }; + + var warnHyphenatedStyleName = function (name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + + error('Unsupported style property %s. Did you mean %s?', name, // As Andi Smith suggests + // (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix + // is converted to lowercase `ms`. + camelize(name.replace(msPattern, 'ms-'))); + }; + + var warnBadVendoredStyleName = function (name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + + error('Unsupported vendor-prefixed style property %s. Did you mean %s?', name, name.charAt(0).toUpperCase() + name.slice(1)); + }; + + var warnStyleValueWithSemicolon = function (name, value) { + if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) { + return; + } + + warnedStyleValues[value] = true; + + error("Style property values shouldn't contain a semicolon. " + 'Try "%s: %s" instead.', name, value.replace(badStyleValueWithSemicolonPattern, '')); + }; + + var warnStyleValueIsNaN = function (name, value) { + if (warnedForNaNValue) { + return; + } + + warnedForNaNValue = true; + + error('`NaN` is an invalid value for the `%s` css style property.', name); + }; + + var warnStyleValueIsInfinity = function (name, value) { + if (warnedForInfinityValue) { + return; + } + + warnedForInfinityValue = true; + + error('`Infinity` is an invalid value for the `%s` css style property.', name); + }; + + warnValidStyle = function (name, value) { + if (name.indexOf('-') > -1) { + warnHyphenatedStyleName(name); + } else if (badVendoredStyleNamePattern.test(name)) { + warnBadVendoredStyleName(name); + } else if (badStyleValueWithSemicolonPattern.test(value)) { + warnStyleValueWithSemicolon(name, value); + } + + if (typeof value === 'number') { + if (isNaN(value)) { + warnStyleValueIsNaN(name, value); + } else if (!isFinite(value)) { + warnStyleValueIsInfinity(name, value); + } + } + }; +} + +var warnValidStyle$1 = warnValidStyle; + +// code copied and modified from escape-html +var matchHtmlRegExp = /["'&<>]/; +/** + * Escapes special characters and HTML entities in a given html string. + * + * @param {string} string HTML string to escape for later insertion + * @return {string} + * @public + */ + +function escapeHtml(string) { + { + checkHtmlStringCoercion(string); + } + + var str = '' + string; + var match = matchHtmlRegExp.exec(str); + + if (!match) { + return str; + } + + var escape; + var html = ''; + var index; + var lastIndex = 0; + + for (index = match.index; index < str.length; index++) { + switch (str.charCodeAt(index)) { + case 34: + // " + escape = '"'; + break; + + case 38: + // & + escape = '&'; + break; + + case 39: + // ' + escape = '''; // modified from escape-html; used to be ''' + + break; + + case 60: + // < + escape = '<'; + break; + + case 62: + // > + escape = '>'; + break; + + default: + continue; + } + + if (lastIndex !== index) { + html += str.substring(lastIndex, index); + } + + lastIndex = index + 1; + html += escape; + } + + return lastIndex !== index ? html + str.substring(lastIndex, index) : html; +} // end code copied and modified from escape-html + +/** + * Escapes text to prevent scripting attacks. + * + * @param {*} text Text value to escape. + * @return {string} An escaped string. + */ + + +function escapeTextForBrowser(text) { + if (typeof text === 'boolean' || typeof text === 'number') { + // this shortcircuit helps perf for types that we know will never have + // special characters, especially given that this function is used often + // for numeric dom ids. + return '' + text; + } + + return escapeHtml(text); +} + +var uppercasePattern = /([A-Z])/g; +var msPattern$1 = /^ms-/; +/** + * Hyphenates a camelcased CSS property name, for example: + * + * > hyphenateStyleName('backgroundColor') + * < "background-color" + * > hyphenateStyleName('MozTransition') + * < "-moz-transition" + * > hyphenateStyleName('msTransition') + * < "-ms-transition" + * + * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix + * is converted to `-ms-`. + */ + +function hyphenateStyleName(name) { + return name.replace(uppercasePattern, '-$1').toLowerCase().replace(msPattern$1, '-ms-'); +} + +// and any newline or tab are filtered out as if they're not part of the URL. +// https://url.spec.whatwg.org/#url-parsing +// Tab or newline are defined as \r\n\t: +// https://infra.spec.whatwg.org/#ascii-tab-or-newline +// A C0 control is a code point in the range \u0000 NULL to \u001F +// INFORMATION SEPARATOR ONE, inclusive: +// https://infra.spec.whatwg.org/#c0-control-or-space + +/* eslint-disable max-len */ + +var isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i; +var didWarn = false; + +function sanitizeURL(url) { + { + if (!didWarn && isJavaScriptProtocol.test(url)) { + didWarn = true; + + error('A future version of React will block javascript: URLs as a security precaution. ' + 'Use event handlers instead if you can. If you need to generate unsafe HTML try ' + 'using dangerouslySetInnerHTML instead. React was passed %s.', JSON.stringify(url)); + } + } +} + +var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare + +function isArray(a) { + return isArrayImpl(a); +} + +var startInlineScript = stringToPrecomputedChunk(''); +var startScriptSrc = stringToPrecomputedChunk(''); +/** + * This escaping function is designed to work with bootstrapScriptContent only. + * because we know we are escaping the entire script. We can avoid for instance + * escaping html comment string sequences that are valid javascript as well because + * if there are no sebsequent '); +function writeCompletedSegmentInstruction(destination, responseState, contentSegmentID) { + writeChunk(destination, responseState.startInlineScript); + + if (!responseState.sentCompleteSegmentFunction) { + // The first time we write this, we'll need to include the full implementation. + responseState.sentCompleteSegmentFunction = true; + writeChunk(destination, completeSegmentScript1Full); + } else { + // Future calls can just reuse the same function. + writeChunk(destination, completeSegmentScript1Partial); + } + + writeChunk(destination, responseState.segmentPrefix); + var formattedID = stringToChunk(contentSegmentID.toString(16)); + writeChunk(destination, formattedID); + writeChunk(destination, completeSegmentScript2); + writeChunk(destination, responseState.placeholderPrefix); + writeChunk(destination, formattedID); + return writeChunkAndReturn(destination, completeSegmentScript3); +} +var completeBoundaryScript1Full = stringToPrecomputedChunk(completeBoundaryFunction + ';$RC("'); +var completeBoundaryScript1Partial = stringToPrecomputedChunk('$RC("'); +var completeBoundaryScript2 = stringToPrecomputedChunk('","'); +var completeBoundaryScript3 = stringToPrecomputedChunk('")'); +function writeCompletedBoundaryInstruction(destination, responseState, boundaryID, contentSegmentID) { + writeChunk(destination, responseState.startInlineScript); + + if (!responseState.sentCompleteBoundaryFunction) { + // The first time we write this, we'll need to include the full implementation. + responseState.sentCompleteBoundaryFunction = true; + writeChunk(destination, completeBoundaryScript1Full); + } else { + // Future calls can just reuse the same function. + writeChunk(destination, completeBoundaryScript1Partial); + } + + if (boundaryID === null) { + throw new Error('An ID must have been assigned before we can complete the boundary.'); + } + + var formattedContentID = stringToChunk(contentSegmentID.toString(16)); + writeChunk(destination, boundaryID); + writeChunk(destination, completeBoundaryScript2); + writeChunk(destination, responseState.segmentPrefix); + writeChunk(destination, formattedContentID); + return writeChunkAndReturn(destination, completeBoundaryScript3); +} +var clientRenderScript1Full = stringToPrecomputedChunk(clientRenderFunction + ';$RX("'); +var clientRenderScript1Partial = stringToPrecomputedChunk('$RX("'); +var clientRenderScript1A = stringToPrecomputedChunk('"'); +var clientRenderScript2 = stringToPrecomputedChunk(')'); +var clientRenderErrorScriptArgInterstitial = stringToPrecomputedChunk(','); +function writeClientRenderBoundaryInstruction(destination, responseState, boundaryID, errorDigest, errorMessage, errorComponentStack) { + writeChunk(destination, responseState.startInlineScript); + + if (!responseState.sentClientRenderFunction) { + // The first time we write this, we'll need to include the full implementation. + responseState.sentClientRenderFunction = true; + writeChunk(destination, clientRenderScript1Full); + } else { + // Future calls can just reuse the same function. + writeChunk(destination, clientRenderScript1Partial); + } + + if (boundaryID === null) { + throw new Error('An ID must have been assigned before we can complete the boundary.'); + } + + writeChunk(destination, boundaryID); + writeChunk(destination, clientRenderScript1A); + + if (errorDigest || errorMessage || errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk(destination, stringToChunk(escapeJSStringsForInstructionScripts(errorDigest || ''))); + } + + if (errorMessage || errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk(destination, stringToChunk(escapeJSStringsForInstructionScripts(errorMessage || ''))); + } + + if (errorComponentStack) { + writeChunk(destination, clientRenderErrorScriptArgInterstitial); + writeChunk(destination, stringToChunk(escapeJSStringsForInstructionScripts(errorComponentStack))); + } + + return writeChunkAndReturn(destination, clientRenderScript2); +} +var regexForJSStringsInScripts = /[<\u2028\u2029]/g; + +function escapeJSStringsForInstructionScripts(input) { + var escaped = JSON.stringify(input); + return escaped.replace(regexForJSStringsInScripts, function (match) { + switch (match) { + // santizing breaking out of strings and script tags + case '<': + return "\\u003c"; + + case "\u2028": + return "\\u2028"; + + case "\u2029": + return "\\u2029"; + + default: + { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error('escapeJSStringsForInstructionScripts encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React'); + } + } + }); +} + +function createResponseState$1(generateStaticMarkup, identifierPrefix) { + var responseState = createResponseState(identifierPrefix, undefined); + return { + // Keep this in sync with ReactDOMServerFormatConfig + bootstrapChunks: responseState.bootstrapChunks, + startInlineScript: responseState.startInlineScript, + placeholderPrefix: responseState.placeholderPrefix, + segmentPrefix: responseState.segmentPrefix, + boundaryPrefix: responseState.boundaryPrefix, + idPrefix: responseState.idPrefix, + nextSuspenseID: responseState.nextSuspenseID, + sentCompleteSegmentFunction: responseState.sentCompleteSegmentFunction, + sentCompleteBoundaryFunction: responseState.sentCompleteBoundaryFunction, + sentClientRenderFunction: responseState.sentClientRenderFunction, + // This is an extra field for the legacy renderer + generateStaticMarkup: generateStaticMarkup + }; +} +function createRootFormatContext() { + return { + insertionMode: HTML_MODE, + // We skip the root mode because we don't want to emit the DOCTYPE in legacy mode. + selectedValue: null + }; +} +function pushTextInstance$1(target, text, responseState, textEmbedded) { + if (responseState.generateStaticMarkup) { + target.push(stringToChunk(escapeTextForBrowser(text))); + return false; + } else { + return pushTextInstance(target, text, responseState, textEmbedded); + } +} +function pushSegmentFinale$1(target, responseState, lastPushedText, textEmbedded) { + if (responseState.generateStaticMarkup) { + return; + } else { + return pushSegmentFinale(target, responseState, lastPushedText, textEmbedded); + } +} +function writeStartCompletedSuspenseBoundary$1(destination, responseState) { + if (responseState.generateStaticMarkup) { + // A completed boundary is done and doesn't need a representation in the HTML + // if we're not going to be hydrating it. + return true; + } + + return writeStartCompletedSuspenseBoundary(destination); +} +function writeStartClientRenderedSuspenseBoundary$1(destination, responseState, // flushing these error arguments are not currently supported in this legacy streaming format. +errorDigest, errorMessage, errorComponentStack) { + if (responseState.generateStaticMarkup) { + // A client rendered boundary is done and doesn't need a representation in the HTML + // since we'll never hydrate it. This is arguably an error in static generation. + return true; + } + + return writeStartClientRenderedSuspenseBoundary(destination, responseState, errorDigest, errorMessage, errorComponentStack); +} +function writeEndCompletedSuspenseBoundary$1(destination, responseState) { + if (responseState.generateStaticMarkup) { + return true; + } + + return writeEndCompletedSuspenseBoundary(destination); +} +function writeEndClientRenderedSuspenseBoundary$1(destination, responseState) { + if (responseState.generateStaticMarkup) { + return true; + } + + return writeEndClientRenderedSuspenseBoundary(destination); +} + +var assign = Object.assign; + +// ATTENTION +// When adding new symbols to this file, +// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' +// The Symbol used to tag the ReactElement-like types. +var REACT_ELEMENT_TYPE = Symbol.for('react.element'); +var REACT_PORTAL_TYPE = Symbol.for('react.portal'); +var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); +var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); +var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); +var REACT_PROVIDER_TYPE = Symbol.for('react.provider'); +var REACT_CONTEXT_TYPE = Symbol.for('react.context'); +var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); +var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); +var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); +var REACT_MEMO_TYPE = Symbol.for('react.memo'); +var REACT_LAZY_TYPE = Symbol.for('react.lazy'); +var REACT_SCOPE_TYPE = Symbol.for('react.scope'); +var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for('react.debug_trace_mode'); +var REACT_LEGACY_HIDDEN_TYPE = Symbol.for('react.legacy_hidden'); +var REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED = Symbol.for('react.default_value'); +var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; +var FAUX_ITERATOR_SYMBOL = '@@iterator'; +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== 'object') { + return null; + } + + var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; + + if (typeof maybeIterator === 'function') { + return maybeIterator; + } + + return null; +} + +function getWrappedName(outerType, innerType, wrapperName) { + var displayName = outerType.displayName; + + if (displayName) { + return displayName; + } + + var functionName = innerType.displayName || innerType.name || ''; + return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName; +} // Keep in sync with react-reconciler/getComponentNameFromFiber + + +function getContextName(type) { + return type.displayName || 'Context'; +} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. + + +function getComponentNameFromType(type) { + if (type == null) { + // Host root, text node or just invalid type. + return null; + } + + { + if (typeof type.tag === 'number') { + error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.'); + } + } + + if (typeof type === 'function') { + return type.displayName || type.name || null; + } + + if (typeof type === 'string') { + return type; + } + + switch (type) { + case REACT_FRAGMENT_TYPE: + return 'Fragment'; + + case REACT_PORTAL_TYPE: + return 'Portal'; + + case REACT_PROFILER_TYPE: + return 'Profiler'; + + case REACT_STRICT_MODE_TYPE: + return 'StrictMode'; + + case REACT_SUSPENSE_TYPE: + return 'Suspense'; + + case REACT_SUSPENSE_LIST_TYPE: + return 'SuspenseList'; + + } + + if (typeof type === 'object') { + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE: + var context = type; + return getContextName(context) + '.Consumer'; + + case REACT_PROVIDER_TYPE: + var provider = type; + return getContextName(provider._context) + '.Provider'; + + case REACT_FORWARD_REF_TYPE: + return getWrappedName(type, type.render, 'ForwardRef'); + + case REACT_MEMO_TYPE: + var outerName = type.displayName || null; + + if (outerName !== null) { + return outerName; + } + + return getComponentNameFromType(type.type) || 'Memo'; + + case REACT_LAZY_TYPE: + { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + return getComponentNameFromType(init(payload)); + } catch (x) { + return null; + } + } + + // eslint-disable-next-line no-fallthrough + } + } + + return null; +} + +// Helpers to patch console.logs to avoid logging during side-effect free +// replaying on render function. This currently only patches the object +// lazily which won't cover if the log function was extracted eagerly. +// We could also eagerly patch the method. +var disabledDepth = 0; +var prevLog; +var prevInfo; +var prevWarn; +var prevError; +var prevGroup; +var prevGroupCollapsed; +var prevGroupEnd; + +function disabledLog() {} + +disabledLog.__reactDisabledLog = true; +function disableLogs() { + { + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + prevLog = console.log; + prevInfo = console.info; + prevWarn = console.warn; + prevError = console.error; + prevGroup = console.group; + prevGroupCollapsed = console.groupCollapsed; + prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 + + var props = { + configurable: true, + enumerable: true, + value: disabledLog, + writable: true + }; // $FlowFixMe Flow thinks console is immutable. + + Object.defineProperties(console, { + info: props, + log: props, + warn: props, + error: props, + group: props, + groupCollapsed: props, + groupEnd: props + }); + /* eslint-enable react-internal/no-production-logging */ + } + + disabledDepth++; + } +} +function reenableLogs() { + { + disabledDepth--; + + if (disabledDepth === 0) { + /* eslint-disable react-internal/no-production-logging */ + var props = { + configurable: true, + enumerable: true, + writable: true + }; // $FlowFixMe Flow thinks console is immutable. + + Object.defineProperties(console, { + log: assign({}, props, { + value: prevLog + }), + info: assign({}, props, { + value: prevInfo + }), + warn: assign({}, props, { + value: prevWarn + }), + error: assign({}, props, { + value: prevError + }), + group: assign({}, props, { + value: prevGroup + }), + groupCollapsed: assign({}, props, { + value: prevGroupCollapsed + }), + groupEnd: assign({}, props, { + value: prevGroupEnd + }) + }); + /* eslint-enable react-internal/no-production-logging */ + } + + if (disabledDepth < 0) { + error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.'); + } + } +} + +var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; +var prefix; +function describeBuiltInComponentFrame(name, source, ownerFn) { + { + if (prefix === undefined) { + // Extract the VM specific prefix used by each line. + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = match && match[1] || ''; + } + } // We use the prefix to ensure our stacks line up with native stack frames. + + + return '\n' + prefix + name; + } +} +var reentry = false; +var componentFrameCache; + +{ + var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; + componentFrameCache = new PossiblyWeakMap(); +} + +function describeNativeComponentFrame(fn, construct) { + // If something asked for a stack inside a fake render, it should get ignored. + if ( !fn || reentry) { + return ''; + } + + { + var frame = componentFrameCache.get(fn); + + if (frame !== undefined) { + return frame; + } + } + + var control; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined. + + Error.prepareStackTrace = undefined; + var previousDispatcher; + + { + previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function + // for warnings. + + ReactCurrentDispatcher.current = null; + disableLogs(); + } + + try { + // This should throw. + if (construct) { + // Something should be setting the props in the constructor. + var Fake = function () { + throw Error(); + }; // $FlowFixMe + + + Object.defineProperty(Fake.prototype, 'props', { + set: function () { + // We use a throwing setter instead of frozen or non-writable props + // because that won't throw in a non-strict mode function. + throw Error(); + } + }); + + if (typeof Reflect === 'object' && Reflect.construct) { + // We construct a different control for this case to include any extra + // frames added by the construct call. + try { + Reflect.construct(Fake, []); + } catch (x) { + control = x; + } + + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x) { + control = x; + } + + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x) { + control = x; + } + + fn(); + } + } catch (sample) { + // This is inlined manually because closure doesn't do it for us. + if (sample && control && typeof sample.stack === 'string') { + // This extracts the first frame from the sample that isn't also in the control. + // Skipping one frame that we assume is the frame that calls the two. + var sampleLines = sample.stack.split('\n'); + var controlLines = control.stack.split('\n'); + var s = sampleLines.length - 1; + var c = controlLines.length - 1; + + while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { + // We expect at least one stack frame to be shared. + // Typically this will be the root most one. However, stack frames may be + // cut off due to maximum stack limits. In this case, one maybe cut off + // earlier than the other. We assume that the sample is longer or the same + // and there for cut off earlier. So we should find the root most frame in + // the sample somewhere in the control. + c--; + } + + for (; s >= 1 && c >= 0; s--, c--) { + // Next we find the first one that isn't the same which should be the + // frame that called our sample function and the control. + if (sampleLines[s] !== controlLines[c]) { + // In V8, the first line is describing the message but other VMs don't. + // If we're about to return the first line, and the control is also on the same + // line, that's a pretty good indicator that our sample threw at same line as + // the control. I.e. before we entered the sample frame. So we ignore this result. + // This can happen if you passed a class to function component, or non-function. + if (s !== 1 || c !== 1) { + do { + s--; + c--; // We may still have similar intermediate frames from the construct call. + // The next one that isn't the same should be our match though. + + if (c < 0 || sampleLines[s] !== controlLines[c]) { + // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. + var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "" + // but we have a user-provided "displayName" + // splice it in to make the stack more readable. + + + if (fn.displayName && _frame.includes('')) { + _frame = _frame.replace('', fn.displayName); + } + + { + if (typeof fn === 'function') { + componentFrameCache.set(fn, _frame); + } + } // Return the line we found. + + + return _frame; + } + } while (s >= 1 && c >= 0); + } + + break; + } + } + } + } finally { + reentry = false; + + { + ReactCurrentDispatcher.current = previousDispatcher; + reenableLogs(); + } + + Error.prepareStackTrace = previousPrepareStackTrace; + } // Fallback to just using the name if we couldn't make it throw. + + + var name = fn ? fn.displayName || fn.name : ''; + var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; + + { + if (typeof fn === 'function') { + componentFrameCache.set(fn, syntheticFrame); + } + } + + return syntheticFrame; +} + +function describeClassComponentFrame(ctor, source, ownerFn) { + { + return describeNativeComponentFrame(ctor, true); + } +} +function describeFunctionComponentFrame(fn, source, ownerFn) { + { + return describeNativeComponentFrame(fn, false); + } +} + +function shouldConstruct(Component) { + var prototype = Component.prototype; + return !!(prototype && prototype.isReactComponent); +} + +function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { + + if (type == null) { + return ''; + } + + if (typeof type === 'function') { + { + return describeNativeComponentFrame(type, shouldConstruct(type)); + } + } + + if (typeof type === 'string') { + return describeBuiltInComponentFrame(type); + } + + switch (type) { + case REACT_SUSPENSE_TYPE: + return describeBuiltInComponentFrame('Suspense'); + + case REACT_SUSPENSE_LIST_TYPE: + return describeBuiltInComponentFrame('SuspenseList'); + } + + if (typeof type === 'object') { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + return describeFunctionComponentFrame(type.render); + + case REACT_MEMO_TYPE: + // Memo may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); + + case REACT_LAZY_TYPE: + { + var lazyComponent = type; + var payload = lazyComponent._payload; + var init = lazyComponent._init; + + try { + // Lazy may contain any component type so we recursively resolve it. + return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn); + } catch (x) {} + } + } + } + + return ''; +} + +var loggedTypeFailures = {}; +var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; + +function setCurrentlyValidatingElement(element) { + { + if (element) { + var owner = element._owner; + var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null); + ReactDebugCurrentFrame.setExtraStackFrame(stack); + } else { + ReactDebugCurrentFrame.setExtraStackFrame(null); + } + } +} + +function checkPropTypes(typeSpecs, values, location, componentName, element) { + { + // $FlowFixMe This is okay but Flow doesn't know it. + var has = Function.call.bind(hasOwnProperty); + + for (var typeSpecName in typeSpecs) { + if (has(typeSpecs, typeSpecName)) { + var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to + // fail the render phase where it didn't fail before. So we log it. + // After these have been cleaned up, we'll let them throw. + + try { + // This is intentionally an invariant that gets caught. It's the same + // behavior as without this statement except with a better message. + if (typeof typeSpecs[typeSpecName] !== 'function') { + // eslint-disable-next-line react-internal/prod-error-codes + var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'); + err.name = 'Invariant Violation'; + throw err; + } + + error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'); + } catch (ex) { + error$1 = ex; + } + + if (error$1 && !(error$1 instanceof Error)) { + setCurrentlyValidatingElement(element); + + error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1); + + setCurrentlyValidatingElement(null); + } + + if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) { + // Only monitor this failure once because there tends to be a lot of the + // same error. + loggedTypeFailures[error$1.message] = true; + setCurrentlyValidatingElement(element); + + error('Failed %s type: %s', location, error$1.message); + + setCurrentlyValidatingElement(null); + } + } + } + } +} + +var warnedAboutMissingGetChildContext; + +{ + warnedAboutMissingGetChildContext = {}; +} + +var emptyContextObject = {}; + +{ + Object.freeze(emptyContextObject); +} + +function getMaskedContext(type, unmaskedContext) { + { + var contextTypes = type.contextTypes; + + if (!contextTypes) { + return emptyContextObject; + } + + var context = {}; + + for (var key in contextTypes) { + context[key] = unmaskedContext[key]; + } + + { + var name = getComponentNameFromType(type) || 'Unknown'; + checkPropTypes(contextTypes, context, 'context', name); + } + + return context; + } +} +function processChildContext(instance, type, parentContext, childContextTypes) { + { + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== 'function') { + { + var componentName = getComponentNameFromType(type) || 'Unknown'; + + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[componentName] = true; + + error('%s.childContextTypes is specified but there is no getChildContext() method ' + 'on the instance. You can either define getChildContext() on %s or remove ' + 'childContextTypes from it.', componentName, componentName); + } + } + + return parentContext; + } + + var childContext = instance.getChildContext(); + + for (var contextKey in childContext) { + if (!(contextKey in childContextTypes)) { + throw new Error((getComponentNameFromType(type) || 'Unknown') + ".getChildContext(): key \"" + contextKey + "\" is not defined in childContextTypes."); + } + } + + { + var name = getComponentNameFromType(type) || 'Unknown'; + checkPropTypes(childContextTypes, childContext, 'child context', name); + } + + return assign({}, parentContext, childContext); + } +} + +var rendererSigil; + +{ + // Use this to detect multiple renderers using the same context + rendererSigil = {}; +} // Used to store the parent path of all context overrides in a shared linked list. +// Forming a reverse tree. + + +var rootContextSnapshot = null; // We assume that this runtime owns the "current" field on all ReactContext instances. +// This global (actually thread local) state represents what state all those "current", +// fields are currently in. + +var currentActiveSnapshot = null; + +function popNode(prev) { + { + prev.context._currentValue2 = prev.parentValue; + } +} + +function pushNode(next) { + { + next.context._currentValue2 = next.value; + } +} + +function popToNearestCommonAncestor(prev, next) { + if (prev === next) ; else { + popNode(prev); + var parentPrev = prev.parent; + var parentNext = next.parent; + + if (parentPrev === null) { + if (parentNext !== null) { + throw new Error('The stacks must reach the root at the same time. This is a bug in React.'); + } + } else { + if (parentNext === null) { + throw new Error('The stacks must reach the root at the same time. This is a bug in React.'); + } + + popToNearestCommonAncestor(parentPrev, parentNext); + } // On the way back, we push the new ones that weren't common. + + + pushNode(next); + } +} + +function popAllPrevious(prev) { + popNode(prev); + var parentPrev = prev.parent; + + if (parentPrev !== null) { + popAllPrevious(parentPrev); + } +} + +function pushAllNext(next) { + var parentNext = next.parent; + + if (parentNext !== null) { + pushAllNext(parentNext); + } + + pushNode(next); +} + +function popPreviousToCommonLevel(prev, next) { + popNode(prev); + var parentPrev = prev.parent; + + if (parentPrev === null) { + throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.'); + } + + if (parentPrev.depth === next.depth) { + // We found the same level. Now we just need to find a shared ancestor. + popToNearestCommonAncestor(parentPrev, next); + } else { + // We must still be deeper. + popPreviousToCommonLevel(parentPrev, next); + } +} + +function popNextToCommonLevel(prev, next) { + var parentNext = next.parent; + + if (parentNext === null) { + throw new Error('The depth must equal at least at zero before reaching the root. This is a bug in React.'); + } + + if (prev.depth === parentNext.depth) { + // We found the same level. Now we just need to find a shared ancestor. + popToNearestCommonAncestor(prev, parentNext); + } else { + // We must still be deeper. + popNextToCommonLevel(prev, parentNext); + } + + pushNode(next); +} // Perform context switching to the new snapshot. +// To make it cheap to read many contexts, while not suspending, we make the switch eagerly by +// updating all the context's current values. That way reads, always just read the current value. +// At the cost of updating contexts even if they're never read by this subtree. + + +function switchContext(newSnapshot) { + // The basic algorithm we need to do is to pop back any contexts that are no longer on the stack. + // We also need to update any new contexts that are now on the stack with the deepest value. + // The easiest way to update new contexts is to just reapply them in reverse order from the + // perspective of the backpointers. To avoid allocating a lot when switching, we use the stack + // for that. Therefore this algorithm is recursive. + // 1) First we pop which ever snapshot tree was deepest. Popping old contexts as we go. + // 2) Then we find the nearest common ancestor from there. Popping old contexts as we go. + // 3) Then we reapply new contexts on the way back up the stack. + var prev = currentActiveSnapshot; + var next = newSnapshot; + + if (prev !== next) { + if (prev === null) { + // $FlowFixMe: This has to be non-null since it's not equal to prev. + pushAllNext(next); + } else if (next === null) { + popAllPrevious(prev); + } else if (prev.depth === next.depth) { + popToNearestCommonAncestor(prev, next); + } else if (prev.depth > next.depth) { + popPreviousToCommonLevel(prev, next); + } else { + popNextToCommonLevel(prev, next); + } + + currentActiveSnapshot = next; + } +} +function pushProvider(context, nextValue) { + var prevValue; + + { + prevValue = context._currentValue2; + context._currentValue2 = nextValue; + + { + if (context._currentRenderer2 !== undefined && context._currentRenderer2 !== null && context._currentRenderer2 !== rendererSigil) { + error('Detected multiple renderers concurrently rendering the ' + 'same context provider. This is currently unsupported.'); + } + + context._currentRenderer2 = rendererSigil; + } + } + + var prevNode = currentActiveSnapshot; + var newNode = { + parent: prevNode, + depth: prevNode === null ? 0 : prevNode.depth + 1, + context: context, + parentValue: prevValue, + value: nextValue + }; + currentActiveSnapshot = newNode; + return newNode; +} +function popProvider(context) { + var prevSnapshot = currentActiveSnapshot; + + if (prevSnapshot === null) { + throw new Error('Tried to pop a Context at the root of the app. This is a bug in React.'); + } + + { + if (prevSnapshot.context !== context) { + error('The parent context is not the expected context. This is probably a bug in React.'); + } + } + + { + var _value = prevSnapshot.parentValue; + + if (_value === REACT_SERVER_CONTEXT_DEFAULT_VALUE_NOT_LOADED) { + prevSnapshot.context._currentValue2 = prevSnapshot.context._defaultValue; + } else { + prevSnapshot.context._currentValue2 = _value; + } + + { + if (context._currentRenderer2 !== undefined && context._currentRenderer2 !== null && context._currentRenderer2 !== rendererSigil) { + error('Detected multiple renderers concurrently rendering the ' + 'same context provider. This is currently unsupported.'); + } + + context._currentRenderer2 = rendererSigil; + } + } + + return currentActiveSnapshot = prevSnapshot.parent; +} +function getActiveContext() { + return currentActiveSnapshot; +} +function readContext(context) { + var value = context._currentValue2; + return value; +} + +/** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ +function get(key) { + return key._reactInternals; +} +function set(key, value) { + key._reactInternals = value; +} + +var didWarnAboutNoopUpdateForComponent = {}; +var didWarnAboutDeprecatedWillMount = {}; +var didWarnAboutUninitializedState; +var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate; +var didWarnAboutLegacyLifecyclesAndDerivedState; +var didWarnAboutUndefinedDerivedState; +var warnOnUndefinedDerivedState; +var warnOnInvalidCallback; +var didWarnAboutDirectlyAssigningPropsToState; +var didWarnAboutContextTypeAndContextTypes; +var didWarnAboutInvalidateContextType; + +{ + didWarnAboutUninitializedState = new Set(); + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); + didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); + didWarnAboutDirectlyAssigningPropsToState = new Set(); + didWarnAboutUndefinedDerivedState = new Set(); + didWarnAboutContextTypeAndContextTypes = new Set(); + didWarnAboutInvalidateContextType = new Set(); + var didWarnOnInvalidCallback = new Set(); + + warnOnInvalidCallback = function (callback, callerName) { + if (callback === null || typeof callback === 'function') { + return; + } + + var key = callerName + '_' + callback; + + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key); + + error('%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); + } + }; + + warnOnUndefinedDerivedState = function (type, partialState) { + if (partialState === undefined) { + var componentName = getComponentNameFromType(type) || 'Component'; + + if (!didWarnAboutUndefinedDerivedState.has(componentName)) { + didWarnAboutUndefinedDerivedState.add(componentName); + + error('%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + 'You have returned undefined.', componentName); + } + } + }; +} + +function warnNoop(publicInstance, callerName) { + { + var _constructor = publicInstance.constructor; + var componentName = _constructor && getComponentNameFromType(_constructor) || 'ReactClass'; + var warningKey = componentName + '.' + callerName; + + if (didWarnAboutNoopUpdateForComponent[warningKey]) { + return; + } + + error('%s(...): Can only update a mounting component. ' + 'This usually means you called %s() outside componentWillMount() on the server. ' + 'This is a no-op.\n\nPlease check the code for the %s component.', callerName, callerName, componentName); + + didWarnAboutNoopUpdateForComponent[warningKey] = true; + } +} + +var classComponentUpdater = { + isMounted: function (inst) { + return false; + }, + enqueueSetState: function (inst, payload, callback) { + var internals = get(inst); + + if (internals.queue === null) { + warnNoop(inst, 'setState'); + } else { + internals.queue.push(payload); + + { + if (callback !== undefined && callback !== null) { + warnOnInvalidCallback(callback, 'setState'); + } + } + } + }, + enqueueReplaceState: function (inst, payload, callback) { + var internals = get(inst); + internals.replace = true; + internals.queue = [payload]; + + { + if (callback !== undefined && callback !== null) { + warnOnInvalidCallback(callback, 'setState'); + } + } + }, + enqueueForceUpdate: function (inst, callback) { + var internals = get(inst); + + if (internals.queue === null) { + warnNoop(inst, 'forceUpdate'); + } else { + { + if (callback !== undefined && callback !== null) { + warnOnInvalidCallback(callback, 'setState'); + } + } + } + } +}; + +function applyDerivedStateFromProps(instance, ctor, getDerivedStateFromProps, prevState, nextProps) { + var partialState = getDerivedStateFromProps(nextProps, prevState); + + { + warnOnUndefinedDerivedState(ctor, partialState); + } // Merge the partial state and the previous state. + + + var newState = partialState === null || partialState === undefined ? prevState : assign({}, prevState, partialState); + return newState; +} + +function constructClassInstance(ctor, props, maskedLegacyContext) { + var context = emptyContextObject; + var contextType = ctor.contextType; + + { + if ('contextType' in ctor) { + var isValid = // Allow null for conditional declaration + contextType === null || contextType !== undefined && contextType.$$typeof === REACT_CONTEXT_TYPE && contextType._context === undefined; // Not a + + if (!isValid && !didWarnAboutInvalidateContextType.has(ctor)) { + didWarnAboutInvalidateContextType.add(ctor); + var addendum = ''; + + if (contextType === undefined) { + addendum = ' However, it is set to undefined. ' + 'This can be caused by a typo or by mixing up named and default imports. ' + 'This can also happen due to a circular dependency, so ' + 'try moving the createContext() call to a separate file.'; + } else if (typeof contextType !== 'object') { + addendum = ' However, it is set to a ' + typeof contextType + '.'; + } else if (contextType.$$typeof === REACT_PROVIDER_TYPE) { + addendum = ' Did you accidentally pass the Context.Provider instead?'; + } else if (contextType._context !== undefined) { + // + addendum = ' Did you accidentally pass the Context.Consumer instead?'; + } else { + addendum = ' However, it is set to an object with keys {' + Object.keys(contextType).join(', ') + '}.'; + } + + error('%s defines an invalid contextType. ' + 'contextType should point to the Context object returned by React.createContext().%s', getComponentNameFromType(ctor) || 'Component', addendum); + } + } + } + + if (typeof contextType === 'object' && contextType !== null) { + context = readContext(contextType); + } else { + context = maskedLegacyContext; + } + + var instance = new ctor(props, context); + + { + if (typeof ctor.getDerivedStateFromProps === 'function' && (instance.state === null || instance.state === undefined)) { + var componentName = getComponentNameFromType(ctor) || 'Component'; + + if (!didWarnAboutUninitializedState.has(componentName)) { + didWarnAboutUninitializedState.add(componentName); + + error('`%s` uses `getDerivedStateFromProps` but its initial state is ' + '%s. This is not recommended. Instead, define the initial state by ' + 'assigning an object to `this.state` in the constructor of `%s`. ' + 'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.', componentName, instance.state === null ? 'null' : 'undefined', componentName); + } + } // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. + + + if (typeof ctor.getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function') { + var foundWillMountName = null; + var foundWillReceivePropsName = null; + var foundWillUpdateName = null; + + if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) { + foundWillMountName = 'componentWillMount'; + } else if (typeof instance.UNSAFE_componentWillMount === 'function') { + foundWillMountName = 'UNSAFE_componentWillMount'; + } + + if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { + foundWillReceivePropsName = 'componentWillReceiveProps'; + } else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { + foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps'; + } + + if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { + foundWillUpdateName = 'componentWillUpdate'; + } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') { + foundWillUpdateName = 'UNSAFE_componentWillUpdate'; + } + + if (foundWillMountName !== null || foundWillReceivePropsName !== null || foundWillUpdateName !== null) { + var _componentName = getComponentNameFromType(ctor) || 'Component'; + + var newApiName = typeof ctor.getDerivedStateFromProps === 'function' ? 'getDerivedStateFromProps()' : 'getSnapshotBeforeUpdate()'; + + if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { + didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); + + error('Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' + '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' + 'The above lifecycles should be removed. Learn more about this warning here:\n' + 'https://reactjs.org/link/unsafe-component-lifecycles', _componentName, newApiName, foundWillMountName !== null ? "\n " + foundWillMountName : '', foundWillReceivePropsName !== null ? "\n " + foundWillReceivePropsName : '', foundWillUpdateName !== null ? "\n " + foundWillUpdateName : ''); + } + } + } + } + + return instance; +} + +function checkClassInstance(instance, ctor, newProps) { + { + var name = getComponentNameFromType(ctor) || 'Component'; + var renderPresent = instance.render; + + if (!renderPresent) { + if (ctor.prototype && typeof ctor.prototype.render === 'function') { + error('%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name); + } else { + error('%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name); + } + } + + if (instance.getInitialState && !instance.getInitialState.isReactClassApproved && !instance.state) { + error('getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', name); + } + + if (instance.getDefaultProps && !instance.getDefaultProps.isReactClassApproved) { + error('getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', name); + } + + if (instance.propTypes) { + error('propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name); + } + + if (instance.contextType) { + error('contextType was defined as an instance property on %s. Use a static ' + 'property to define contextType instead.', name); + } + + { + if (instance.contextTypes) { + error('contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name); + } + + if (ctor.contextType && ctor.contextTypes && !didWarnAboutContextTypeAndContextTypes.has(ctor)) { + didWarnAboutContextTypeAndContextTypes.add(ctor); + + error('%s declares both contextTypes and contextType static properties. ' + 'The legacy contextTypes property will be ignored.', name); + } + } + + if (typeof instance.componentShouldUpdate === 'function') { + error('%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', name); + } + + if (ctor.prototype && ctor.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') { + error('%s has a method called shouldComponentUpdate(). ' + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + 'Please extend React.Component if shouldComponentUpdate is used.', getComponentNameFromType(ctor) || 'A pure component'); + } + + if (typeof instance.componentDidUnmount === 'function') { + error('%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name); + } + + if (typeof instance.componentDidReceiveProps === 'function') { + error('%s has a method called ' + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + 'If you meant to update the state in response to changing props, ' + 'use componentWillReceiveProps(). If you meant to fetch data or ' + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', name); + } + + if (typeof instance.componentWillRecieveProps === 'function') { + error('%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name); + } + + if (typeof instance.UNSAFE_componentWillRecieveProps === 'function') { + error('%s has a method called ' + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', name); + } + + var hasMutatedProps = instance.props !== newProps; + + if (instance.props !== undefined && hasMutatedProps) { + error('%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name); + } + + if (instance.defaultProps) { + error('Setting defaultProps as an instance property on %s is not supported and will be ignored.' + ' Instead, define defaultProps as a static property on %s.', name, name); + } + + if (typeof instance.getSnapshotBeforeUpdate === 'function' && typeof instance.componentDidUpdate !== 'function' && !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(ctor)) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(ctor); + + error('%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + 'This component defines getSnapshotBeforeUpdate() only.', getComponentNameFromType(ctor)); + } + + if (typeof instance.getDerivedStateFromProps === 'function') { + error('%s: getDerivedStateFromProps() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); + } + + if (typeof instance.getDerivedStateFromError === 'function') { + error('%s: getDerivedStateFromError() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name); + } + + if (typeof ctor.getSnapshotBeforeUpdate === 'function') { + error('%s: getSnapshotBeforeUpdate() is defined as a static method ' + 'and will be ignored. Instead, declare it as an instance method.', name); + } + + var _state = instance.state; + + if (_state && (typeof _state !== 'object' || isArray(_state))) { + error('%s.state: must be set to an object or null', name); + } + + if (typeof instance.getChildContext === 'function' && typeof ctor.childContextTypes !== 'object') { + error('%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', name); + } + } +} + +function callComponentWillMount(type, instance) { + var oldState = instance.state; + + if (typeof instance.componentWillMount === 'function') { + { + if ( instance.componentWillMount.__suppressDeprecationWarning !== true) { + var componentName = getComponentNameFromType(type) || 'Unknown'; + + if (!didWarnAboutDeprecatedWillMount[componentName]) { + warn( // keep this warning in sync with ReactStrictModeWarning.js + 'componentWillMount has been renamed, and is not recommended for use. ' + 'See https://reactjs.org/link/unsafe-component-lifecycles for details.\n\n' + '* Move code from componentWillMount to componentDidMount (preferred in most cases) ' + 'or the constructor.\n' + '\nPlease update the following components: %s', componentName); + + didWarnAboutDeprecatedWillMount[componentName] = true; + } + } + } + + instance.componentWillMount(); + } + + if (typeof instance.UNSAFE_componentWillMount === 'function') { + instance.UNSAFE_componentWillMount(); + } + + if (oldState !== instance.state) { + { + error('%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentNameFromType(type) || 'Component'); + } + + classComponentUpdater.enqueueReplaceState(instance, instance.state, null); + } +} + +function processUpdateQueue(internalInstance, inst, props, maskedLegacyContext) { + if (internalInstance.queue !== null && internalInstance.queue.length > 0) { + var oldQueue = internalInstance.queue; + var oldReplace = internalInstance.replace; + internalInstance.queue = null; + internalInstance.replace = false; + + if (oldReplace && oldQueue.length === 1) { + inst.state = oldQueue[0]; + } else { + var nextState = oldReplace ? oldQueue[0] : inst.state; + var dontMutate = true; + + for (var i = oldReplace ? 1 : 0; i < oldQueue.length; i++) { + var partial = oldQueue[i]; + var partialState = typeof partial === 'function' ? partial.call(inst, nextState, props, maskedLegacyContext) : partial; + + if (partialState != null) { + if (dontMutate) { + dontMutate = false; + nextState = assign({}, nextState, partialState); + } else { + assign(nextState, partialState); + } + } + } + + inst.state = nextState; + } + } else { + internalInstance.queue = null; + } +} // Invokes the mount life-cycles on a previously never rendered instance. + + +function mountClassInstance(instance, ctor, newProps, maskedLegacyContext) { + { + checkClassInstance(instance, ctor, newProps); + } + + var initialState = instance.state !== undefined ? instance.state : null; + instance.updater = classComponentUpdater; + instance.props = newProps; + instance.state = initialState; // We don't bother initializing the refs object on the server, since we're not going to resolve them anyway. + // The internal instance will be used to manage updates that happen during this mount. + + var internalInstance = { + queue: [], + replace: false + }; + set(instance, internalInstance); + var contextType = ctor.contextType; + + if (typeof contextType === 'object' && contextType !== null) { + instance.context = readContext(contextType); + } else { + instance.context = maskedLegacyContext; + } + + { + if (instance.state === newProps) { + var componentName = getComponentNameFromType(ctor) || 'Component'; + + if (!didWarnAboutDirectlyAssigningPropsToState.has(componentName)) { + didWarnAboutDirectlyAssigningPropsToState.add(componentName); + + error('%s: It is not recommended to assign props directly to state ' + "because updates to props won't be reflected in state. " + 'In most cases, it is better to use props directly.', componentName); + } + } + } + + var getDerivedStateFromProps = ctor.getDerivedStateFromProps; + + if (typeof getDerivedStateFromProps === 'function') { + instance.state = applyDerivedStateFromProps(instance, ctor, getDerivedStateFromProps, initialState, newProps); + } // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + + + if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { + callComponentWillMount(ctor, instance); // If we had additional state updates during this life-cycle, let's + // process them now. + + processUpdateQueue(internalInstance, instance, newProps, maskedLegacyContext); + } +} + +// Ids are base 32 strings whose binary representation corresponds to the +// position of a node in a tree. +// Every time the tree forks into multiple children, we add additional bits to +// the left of the sequence that represent the position of the child within the +// current level of children. +// +// 00101 00010001011010101 +// ╰─┬─╯ ╰───────┬───────╯ +// Fork 5 of 20 Parent id +// +// The leading 0s are important. In the above example, you only need 3 bits to +// represent slot 5. However, you need 5 bits to represent all the forks at +// the current level, so we must account for the empty bits at the end. +// +// For this same reason, slots are 1-indexed instead of 0-indexed. Otherwise, +// the zeroth id at a level would be indistinguishable from its parent. +// +// If a node has only one child, and does not materialize an id (i.e. does not +// contain a useId hook), then we don't need to allocate any space in the +// sequence. It's treated as a transparent indirection. For example, these two +// trees produce the same ids: +// +// <> <> +//
    +// +// +// +// +// +// However, we cannot skip any node that materializes an id. Otherwise, a parent +// id that does not fork would be indistinguishable from its child id. For +// example, this tree does not fork, but the parent and child must have +// different ids. +// +// +// +// +// +// To handle this scenario, every time we materialize an id, we allocate a +// new level with a single slot. You can think of this as a fork with only one +// prong, or an array of children with length 1. +// +// It's possible for the size of the sequence to exceed 32 bits, the max +// size for bitwise operations. When this happens, we make more room by +// converting the right part of the id to a string and storing it in an overflow +// variable. We use a base 32 string representation, because 32 is the largest +// power of 2 that is supported by toString(). We want the base to be large so +// that the resulting ids are compact, and we want the base to be a power of 2 +// because every log2(base) bits corresponds to a single character, i.e. every +// log2(32) = 5 bits. That means we can lop bits off the end 5 at a time without +// affecting the final result. +var emptyTreeContext = { + id: 1, + overflow: '' +}; +function getTreeId(context) { + var overflow = context.overflow; + var idWithLeadingBit = context.id; + var id = idWithLeadingBit & ~getLeadingBit(idWithLeadingBit); + return id.toString(32) + overflow; +} +function pushTreeContext(baseContext, totalChildren, index) { + var baseIdWithLeadingBit = baseContext.id; + var baseOverflow = baseContext.overflow; // The leftmost 1 marks the end of the sequence, non-inclusive. It's not part + // of the id; we use it to account for leading 0s. + + var baseLength = getBitLength(baseIdWithLeadingBit) - 1; + var baseId = baseIdWithLeadingBit & ~(1 << baseLength); + var slot = index + 1; + var length = getBitLength(totalChildren) + baseLength; // 30 is the max length we can store without overflowing, taking into + // consideration the leading 1 we use to mark the end of the sequence. + + if (length > 30) { + // We overflowed the bitwise-safe range. Fall back to slower algorithm. + // This branch assumes the length of the base id is greater than 5; it won't + // work for smaller ids, because you need 5 bits per character. + // + // We encode the id in multiple steps: first the base id, then the + // remaining digits. + // + // Each 5 bit sequence corresponds to a single base 32 character. So for + // example, if the current id is 23 bits long, we can convert 20 of those + // bits into a string of 4 characters, with 3 bits left over. + // + // First calculate how many bits in the base id represent a complete + // sequence of characters. + var numberOfOverflowBits = baseLength - baseLength % 5; // Then create a bitmask that selects only those bits. + + var newOverflowBits = (1 << numberOfOverflowBits) - 1; // Select the bits, and convert them to a base 32 string. + + var newOverflow = (baseId & newOverflowBits).toString(32); // Now we can remove those bits from the base id. + + var restOfBaseId = baseId >> numberOfOverflowBits; + var restOfBaseLength = baseLength - numberOfOverflowBits; // Finally, encode the rest of the bits using the normal algorithm. Because + // we made more room, this time it won't overflow. + + var restOfLength = getBitLength(totalChildren) + restOfBaseLength; + var restOfNewBits = slot << restOfBaseLength; + var id = restOfNewBits | restOfBaseId; + var overflow = newOverflow + baseOverflow; + return { + id: 1 << restOfLength | id, + overflow: overflow + }; + } else { + // Normal path + var newBits = slot << baseLength; + + var _id = newBits | baseId; + + var _overflow = baseOverflow; + return { + id: 1 << length | _id, + overflow: _overflow + }; + } +} + +function getBitLength(number) { + return 32 - clz32(number); +} + +function getLeadingBit(id) { + return 1 << getBitLength(id) - 1; +} // TODO: Math.clz32 is supported in Node 12+. Maybe we can drop the fallback. + + +var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. +// Based on: +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 + +var log = Math.log; +var LN2 = Math.LN2; + +function clz32Fallback(x) { + var asUint = x >>> 0; + + if (asUint === 0) { + return 32; + } + + return 31 - (log(asUint) / LN2 | 0) | 0; +} + +/** + * inlined Object.is polyfill to avoid requiring consumers ship their own + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + */ +function is(x, y) { + return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare + ; +} + +var objectIs = typeof Object.is === 'function' ? Object.is : is; + +var currentlyRenderingComponent = null; +var currentlyRenderingTask = null; +var firstWorkInProgressHook = null; +var workInProgressHook = null; // Whether the work-in-progress hook is a re-rendered hook + +var isReRender = false; // Whether an update was scheduled during the currently executing render pass. + +var didScheduleRenderPhaseUpdate = false; // Counts the number of useId hooks in this component + +var localIdCounter = 0; // Lazily created map of render-phase updates + +var renderPhaseUpdates = null; // Counter to prevent infinite loops. + +var numberOfReRenders = 0; +var RE_RENDER_LIMIT = 25; +var isInHookUserCodeInDev = false; // In DEV, this is the name of the currently executing primitive hook + +var currentHookNameInDev; + +function resolveCurrentlyRenderingComponent() { + if (currentlyRenderingComponent === null) { + throw new Error('Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' + ' one of the following reasons:\n' + '1. You might have mismatching versions of React and the renderer (such as React DOM)\n' + '2. You might be breaking the Rules of Hooks\n' + '3. You might have more than one copy of React in the same app\n' + 'See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.'); + } + + { + if (isInHookUserCodeInDev) { + error('Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. ' + 'You can only call Hooks at the top level of your React function. ' + 'For more information, see ' + 'https://reactjs.org/link/rules-of-hooks'); + } + } + + return currentlyRenderingComponent; +} + +function areHookInputsEqual(nextDeps, prevDeps) { + if (prevDeps === null) { + { + error('%s received a final argument during this render, but not during ' + 'the previous render. Even though the final argument is optional, ' + 'its type cannot change between renders.', currentHookNameInDev); + } + + return false; + } + + { + // Don't bother comparing lengths in prod because these arrays should be + // passed inline. + if (nextDeps.length !== prevDeps.length) { + error('The final argument passed to %s changed size between renders. The ' + 'order and size of this array must remain constant.\n\n' + 'Previous: %s\n' + 'Incoming: %s', currentHookNameInDev, "[" + nextDeps.join(', ') + "]", "[" + prevDeps.join(', ') + "]"); + } + } + + for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++) { + if (objectIs(nextDeps[i], prevDeps[i])) { + continue; + } + + return false; + } + + return true; +} + +function createHook() { + if (numberOfReRenders > 0) { + throw new Error('Rendered more hooks than during the previous render'); + } + + return { + memoizedState: null, + queue: null, + next: null + }; +} + +function createWorkInProgressHook() { + if (workInProgressHook === null) { + // This is the first hook in the list + if (firstWorkInProgressHook === null) { + isReRender = false; + firstWorkInProgressHook = workInProgressHook = createHook(); + } else { + // There's already a work-in-progress. Reuse it. + isReRender = true; + workInProgressHook = firstWorkInProgressHook; + } + } else { + if (workInProgressHook.next === null) { + isReRender = false; // Append to the end of the list + + workInProgressHook = workInProgressHook.next = createHook(); + } else { + // There's already a work-in-progress. Reuse it. + isReRender = true; + workInProgressHook = workInProgressHook.next; + } + } + + return workInProgressHook; +} + +function prepareToUseHooks(task, componentIdentity) { + currentlyRenderingComponent = componentIdentity; + currentlyRenderingTask = task; + + { + isInHookUserCodeInDev = false; + } // The following should have already been reset + // didScheduleRenderPhaseUpdate = false; + // localIdCounter = 0; + // firstWorkInProgressHook = null; + // numberOfReRenders = 0; + // renderPhaseUpdates = null; + // workInProgressHook = null; + + + localIdCounter = 0; +} +function finishHooks(Component, props, children, refOrContext) { + // This must be called after every function component to prevent hooks from + // being used in classes. + while (didScheduleRenderPhaseUpdate) { + // Updates were scheduled during the render phase. They are stored in + // the `renderPhaseUpdates` map. Call the component again, reusing the + // work-in-progress hooks and applying the additional updates on top. Keep + // restarting until no more updates are scheduled. + didScheduleRenderPhaseUpdate = false; + localIdCounter = 0; + numberOfReRenders += 1; // Start over from the beginning of the list + + workInProgressHook = null; + children = Component(props, refOrContext); + } + + resetHooksState(); + return children; +} +function checkDidRenderIdHook() { + // This should be called immediately after every finishHooks call. + // Conceptually, it's part of the return value of finishHooks; it's only a + // separate function to avoid using an array tuple. + var didRenderIdHook = localIdCounter !== 0; + return didRenderIdHook; +} // Reset the internal hooks state if an error occurs while rendering a component + +function resetHooksState() { + { + isInHookUserCodeInDev = false; + } + + currentlyRenderingComponent = null; + currentlyRenderingTask = null; + didScheduleRenderPhaseUpdate = false; + firstWorkInProgressHook = null; + numberOfReRenders = 0; + renderPhaseUpdates = null; + workInProgressHook = null; +} + +function readContext$1(context) { + { + if (isInHookUserCodeInDev) { + error('Context can only be read while React is rendering. ' + 'In classes, you can read it in the render method or getDerivedStateFromProps. ' + 'In function components, you can read it directly in the function body, but not ' + 'inside Hooks like useReducer() or useMemo().'); + } + } + + return readContext(context); +} + +function useContext(context) { + { + currentHookNameInDev = 'useContext'; + } + + resolveCurrentlyRenderingComponent(); + return readContext(context); +} + +function basicStateReducer(state, action) { + // $FlowFixMe: Flow doesn't like mixed types + return typeof action === 'function' ? action(state) : action; +} + +function useState(initialState) { + { + currentHookNameInDev = 'useState'; + } + + return useReducer(basicStateReducer, // useReducer has a special case to support lazy useState initializers + initialState); +} +function useReducer(reducer, initialArg, init) { + { + if (reducer !== basicStateReducer) { + currentHookNameInDev = 'useReducer'; + } + } + + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + + if (isReRender) { + // This is a re-render. Apply the new render phase updates to the previous + // current hook. + var queue = workInProgressHook.queue; + var dispatch = queue.dispatch; + + if (renderPhaseUpdates !== null) { + // Render phase updates are stored in a map of queue -> linked list + var firstRenderPhaseUpdate = renderPhaseUpdates.get(queue); + + if (firstRenderPhaseUpdate !== undefined) { + renderPhaseUpdates.delete(queue); + var newState = workInProgressHook.memoizedState; + var update = firstRenderPhaseUpdate; + + do { + // Process this render phase update. We don't have to check the + // priority because it will always be the same as the current + // render's. + var action = update.action; + + { + isInHookUserCodeInDev = true; + } + + newState = reducer(newState, action); + + { + isInHookUserCodeInDev = false; + } + + update = update.next; + } while (update !== null); + + workInProgressHook.memoizedState = newState; + return [newState, dispatch]; + } + } + + return [workInProgressHook.memoizedState, dispatch]; + } else { + { + isInHookUserCodeInDev = true; + } + + var initialState; + + if (reducer === basicStateReducer) { + // Special case for `useState`. + initialState = typeof initialArg === 'function' ? initialArg() : initialArg; + } else { + initialState = init !== undefined ? init(initialArg) : initialArg; + } + + { + isInHookUserCodeInDev = false; + } + + workInProgressHook.memoizedState = initialState; + + var _queue = workInProgressHook.queue = { + last: null, + dispatch: null + }; + + var _dispatch = _queue.dispatch = dispatchAction.bind(null, currentlyRenderingComponent, _queue); + + return [workInProgressHook.memoizedState, _dispatch]; + } +} + +function useMemo(nextCreate, deps) { + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + var nextDeps = deps === undefined ? null : deps; + + if (workInProgressHook !== null) { + var prevState = workInProgressHook.memoizedState; + + if (prevState !== null) { + if (nextDeps !== null) { + var prevDeps = prevState[1]; + + if (areHookInputsEqual(nextDeps, prevDeps)) { + return prevState[0]; + } + } + } + } + + { + isInHookUserCodeInDev = true; + } + + var nextValue = nextCreate(); + + { + isInHookUserCodeInDev = false; + } + + workInProgressHook.memoizedState = [nextValue, nextDeps]; + return nextValue; +} + +function useRef(initialValue) { + currentlyRenderingComponent = resolveCurrentlyRenderingComponent(); + workInProgressHook = createWorkInProgressHook(); + var previousRef = workInProgressHook.memoizedState; + + if (previousRef === null) { + var ref = { + current: initialValue + }; + + { + Object.seal(ref); + } + + workInProgressHook.memoizedState = ref; + return ref; + } else { + return previousRef; + } +} + +function useLayoutEffect(create, inputs) { + { + currentHookNameInDev = 'useLayoutEffect'; + + error('useLayoutEffect does nothing on the server, because its effect cannot ' + "be encoded into the server renderer's output format. This will lead " + 'to a mismatch between the initial, non-hydrated UI and the intended ' + 'UI. To avoid this, useLayoutEffect should only be used in ' + 'components that render exclusively on the client. ' + 'See https://reactjs.org/link/uselayouteffect-ssr for common fixes.'); + } +} + +function dispatchAction(componentIdentity, queue, action) { + if (numberOfReRenders >= RE_RENDER_LIMIT) { + throw new Error('Too many re-renders. React limits the number of renders to prevent ' + 'an infinite loop.'); + } + + if (componentIdentity === currentlyRenderingComponent) { + // This is a render phase update. Stash it in a lazily-created map of + // queue -> linked list of updates. After this render pass, we'll restart + // and apply the stashed updates on top of the work-in-progress hook. + didScheduleRenderPhaseUpdate = true; + var update = { + action: action, + next: null + }; + + if (renderPhaseUpdates === null) { + renderPhaseUpdates = new Map(); + } + + var firstRenderPhaseUpdate = renderPhaseUpdates.get(queue); + + if (firstRenderPhaseUpdate === undefined) { + renderPhaseUpdates.set(queue, update); + } else { + // Append the update to the end of the list. + var lastRenderPhaseUpdate = firstRenderPhaseUpdate; + + while (lastRenderPhaseUpdate.next !== null) { + lastRenderPhaseUpdate = lastRenderPhaseUpdate.next; + } + + lastRenderPhaseUpdate.next = update; + } + } +} + +function useCallback(callback, deps) { + return useMemo(function () { + return callback; + }, deps); +} // TODO Decide on how to implement this hook for server rendering. +// If a mutation occurs during render, consider triggering a Suspense boundary +// and falling back to client rendering. + +function useMutableSource(source, getSnapshot, subscribe) { + resolveCurrentlyRenderingComponent(); + return getSnapshot(source._source); +} + +function useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + if (getServerSnapshot === undefined) { + throw new Error('Missing getServerSnapshot, which is required for ' + 'server-rendered content. Will revert to client rendering.'); + } + + return getServerSnapshot(); +} + +function useDeferredValue(value) { + resolveCurrentlyRenderingComponent(); + return value; +} + +function unsupportedStartTransition() { + throw new Error('startTransition cannot be called during server rendering.'); +} + +function useTransition() { + resolveCurrentlyRenderingComponent(); + return [false, unsupportedStartTransition]; +} + +function useId() { + var task = currentlyRenderingTask; + var treeId = getTreeId(task.treeContext); + var responseState = currentResponseState; + + if (responseState === null) { + throw new Error('Invalid hook call. Hooks can only be called inside of the body of a function component.'); + } + + var localId = localIdCounter++; + return makeId(responseState, treeId, localId); +} + +function noop() {} + +var Dispatcher = { + readContext: readContext$1, + useContext: useContext, + useMemo: useMemo, + useReducer: useReducer, + useRef: useRef, + useState: useState, + useInsertionEffect: noop, + useLayoutEffect: useLayoutEffect, + useCallback: useCallback, + // useImperativeHandle is not run in the server environment + useImperativeHandle: noop, + // Effects are not run in the server environment. + useEffect: noop, + // Debugging effect + useDebugValue: noop, + useDeferredValue: useDeferredValue, + useTransition: useTransition, + useId: useId, + // Subscriptions are not setup in a server environment. + useMutableSource: useMutableSource, + useSyncExternalStore: useSyncExternalStore +}; + +var currentResponseState = null; +function setCurrentResponseState(responseState) { + currentResponseState = responseState; +} + +function getStackByComponentStackNode(componentStack) { + try { + var info = ''; + var node = componentStack; + + do { + switch (node.tag) { + case 0: + info += describeBuiltInComponentFrame(node.type, null, null); + break; + + case 1: + info += describeFunctionComponentFrame(node.type, null, null); + break; + + case 2: + info += describeClassComponentFrame(node.type, null, null); + break; + } + + node = node.parent; + } while (node); + + return info; + } catch (x) { + return '\nError generating stack: ' + x.message + '\n' + x.stack; + } +} + +var ReactCurrentDispatcher$1 = ReactSharedInternals.ReactCurrentDispatcher; +var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; +var PENDING = 0; +var COMPLETED = 1; +var FLUSHED = 2; +var ABORTED = 3; +var ERRORED = 4; +var OPEN = 0; +var CLOSING = 1; +var CLOSED = 2; +// This is a default heuristic for how to split up the HTML content into progressive +// loading. Our goal is to be able to display additional new content about every 500ms. +// Faster than that is unnecessary and should be throttled on the client. It also +// adds unnecessary overhead to do more splits. We don't know if it's a higher or lower +// end device but higher end suffer less from the overhead than lower end does from +// not getting small enough pieces. We error on the side of low end. +// We base this on low end 3G speeds which is about 500kbits per second. We assume +// that there can be a reasonable drop off from max bandwidth which leaves you with +// as little as 80%. We can receive half of that each 500ms - at best. In practice, +// a little bandwidth is lost to processing and contention - e.g. CSS and images that +// are downloaded along with the main content. So we estimate about half of that to be +// the lower end throughput. In other words, we expect that you can at least show +// about 12.5kb of content per 500ms. Not counting starting latency for the first +// paint. +// 500 * 1024 / 8 * .8 * 0.5 / 2 +var DEFAULT_PROGRESSIVE_CHUNK_SIZE = 12800; + +function defaultErrorHandler(error) { + console['error'](error); // Don't transform to our wrapper + + return null; +} + +function noop$1() {} + +function createRequest(children, responseState, rootFormatContext, progressiveChunkSize, onError, onAllReady, onShellReady, onShellError, onFatalError) { + var pingedTasks = []; + var abortSet = new Set(); + var request = { + destination: null, + responseState: responseState, + progressiveChunkSize: progressiveChunkSize === undefined ? DEFAULT_PROGRESSIVE_CHUNK_SIZE : progressiveChunkSize, + status: OPEN, + fatalError: null, + nextSegmentId: 0, + allPendingTasks: 0, + pendingRootTasks: 0, + completedRootSegment: null, + abortableTasks: abortSet, + pingedTasks: pingedTasks, + clientRenderedBoundaries: [], + completedBoundaries: [], + partialBoundaries: [], + onError: onError === undefined ? defaultErrorHandler : onError, + onAllReady: onAllReady === undefined ? noop$1 : onAllReady, + onShellReady: onShellReady === undefined ? noop$1 : onShellReady, + onShellError: onShellError === undefined ? noop$1 : onShellError, + onFatalError: onFatalError === undefined ? noop$1 : onFatalError + }; // This segment represents the root fallback. + + var rootSegment = createPendingSegment(request, 0, null, rootFormatContext, // Root segments are never embedded in Text on either edge + false, false); // There is no parent so conceptually, we're unblocked to flush this segment. + + rootSegment.parentFlushed = true; + var rootTask = createTask(request, children, null, rootSegment, abortSet, emptyContextObject, rootContextSnapshot, emptyTreeContext); + pingedTasks.push(rootTask); + return request; +} + +function pingTask(request, task) { + var pingedTasks = request.pingedTasks; + pingedTasks.push(task); + + if (pingedTasks.length === 1) { + scheduleWork(function () { + return performWork(request); + }); + } +} + +function createSuspenseBoundary(request, fallbackAbortableTasks) { + return { + id: UNINITIALIZED_SUSPENSE_BOUNDARY_ID, + rootSegmentID: -1, + parentFlushed: false, + pendingTasks: 0, + forceClientRender: false, + completedSegments: [], + byteSize: 0, + fallbackAbortableTasks: fallbackAbortableTasks, + errorDigest: null + }; +} + +function createTask(request, node, blockedBoundary, blockedSegment, abortSet, legacyContext, context, treeContext) { + request.allPendingTasks++; + + if (blockedBoundary === null) { + request.pendingRootTasks++; + } else { + blockedBoundary.pendingTasks++; + } + + var task = { + node: node, + ping: function () { + return pingTask(request, task); + }, + blockedBoundary: blockedBoundary, + blockedSegment: blockedSegment, + abortSet: abortSet, + legacyContext: legacyContext, + context: context, + treeContext: treeContext + }; + + { + task.componentStack = null; + } + + abortSet.add(task); + return task; +} + +function createPendingSegment(request, index, boundary, formatContext, lastPushedText, textEmbedded) { + return { + status: PENDING, + id: -1, + // lazily assigned later + index: index, + parentFlushed: false, + chunks: [], + children: [], + formatContext: formatContext, + boundary: boundary, + lastPushedText: lastPushedText, + textEmbedded: textEmbedded + }; +} // DEV-only global reference to the currently executing task + + +var currentTaskInDEV = null; + +function getCurrentStackInDEV() { + { + if (currentTaskInDEV === null || currentTaskInDEV.componentStack === null) { + return ''; + } + + return getStackByComponentStackNode(currentTaskInDEV.componentStack); + } +} + +function pushBuiltInComponentStackInDEV(task, type) { + { + task.componentStack = { + tag: 0, + parent: task.componentStack, + type: type + }; + } +} + +function pushFunctionComponentStackInDEV(task, type) { + { + task.componentStack = { + tag: 1, + parent: task.componentStack, + type: type + }; + } +} + +function pushClassComponentStackInDEV(task, type) { + { + task.componentStack = { + tag: 2, + parent: task.componentStack, + type: type + }; + } +} + +function popComponentStackInDEV(task) { + { + if (task.componentStack === null) { + error('Unexpectedly popped too many stack frames. This is a bug in React.'); + } else { + task.componentStack = task.componentStack.parent; + } + } +} // stash the component stack of an unwinding error until it is processed + + +var lastBoundaryErrorComponentStackDev = null; + +function captureBoundaryErrorDetailsDev(boundary, error) { + { + var errorMessage; + + if (typeof error === 'string') { + errorMessage = error; + } else if (error && typeof error.message === 'string') { + errorMessage = error.message; + } else { + // eslint-disable-next-line react-internal/safe-string-coercion + errorMessage = String(error); + } + + var errorComponentStack = lastBoundaryErrorComponentStackDev || getCurrentStackInDEV(); + lastBoundaryErrorComponentStackDev = null; + boundary.errorMessage = errorMessage; + boundary.errorComponentStack = errorComponentStack; + } +} + +function logRecoverableError(request, error) { + // If this callback errors, we intentionally let that error bubble up to become a fatal error + // so that someone fixes the error reporting instead of hiding it. + var errorDigest = request.onError(error); + + if (errorDigest != null && typeof errorDigest !== 'string') { + // eslint-disable-next-line react-internal/prod-error-codes + throw new Error("onError returned something with a type other than \"string\". onError should return a string and may return null or undefined but must not return anything else. It received something of type \"" + typeof errorDigest + "\" instead"); + } + + return errorDigest; +} + +function fatalError(request, error) { + // This is called outside error handling code such as if the root errors outside + // a suspense boundary or if the root suspense boundary's fallback errors. + // It's also called if React itself or its host configs errors. + var onShellError = request.onShellError; + onShellError(error); + var onFatalError = request.onFatalError; + onFatalError(error); + + if (request.destination !== null) { + request.status = CLOSED; + closeWithError(request.destination, error); + } else { + request.status = CLOSING; + request.fatalError = error; + } +} + +function renderSuspenseBoundary(request, task, props) { + pushBuiltInComponentStackInDEV(task, 'Suspense'); + var parentBoundary = task.blockedBoundary; + var parentSegment = task.blockedSegment; // Each time we enter a suspense boundary, we split out into a new segment for + // the fallback so that we can later replace that segment with the content. + // This also lets us split out the main content even if it doesn't suspend, + // in case it ends up generating a large subtree of content. + + var fallback = props.fallback; + var content = props.children; + var fallbackAbortSet = new Set(); + var newBoundary = createSuspenseBoundary(request, fallbackAbortSet); + var insertionIndex = parentSegment.chunks.length; // The children of the boundary segment is actually the fallback. + + var boundarySegment = createPendingSegment(request, insertionIndex, newBoundary, parentSegment.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them + false, false); + parentSegment.children.push(boundarySegment); // The parentSegment has a child Segment at this index so we reset the lastPushedText marker on the parent + + parentSegment.lastPushedText = false; // This segment is the actual child content. We can start rendering that immediately. + + var contentRootSegment = createPendingSegment(request, 0, null, parentSegment.formatContext, // boundaries never require text embedding at their edges because comment nodes bound them + false, false); // We mark the root segment as having its parent flushed. It's not really flushed but there is + // no parent segment so there's nothing to wait on. + + contentRootSegment.parentFlushed = true; // Currently this is running synchronously. We could instead schedule this to pingedTasks. + // I suspect that there might be some efficiency benefits from not creating the suspended task + // and instead just using the stack if possible. + // TODO: Call this directly instead of messing with saving and restoring contexts. + // We can reuse the current context and task to render the content immediately without + // context switching. We just need to temporarily switch which boundary and which segment + // we're writing to. If something suspends, it'll spawn new suspended task with that context. + + task.blockedBoundary = newBoundary; + task.blockedSegment = contentRootSegment; + + try { + // We use the safe form because we don't handle suspending here. Only error handling. + renderNode(request, task, content); + pushSegmentFinale$1(contentRootSegment.chunks, request.responseState, contentRootSegment.lastPushedText, contentRootSegment.textEmbedded); + contentRootSegment.status = COMPLETED; + queueCompletedSegment(newBoundary, contentRootSegment); + + if (newBoundary.pendingTasks === 0) { + // This must have been the last segment we were waiting on. This boundary is now complete. + // Therefore we won't need the fallback. We early return so that we don't have to create + // the fallback. + popComponentStackInDEV(task); + return; + } + } catch (error) { + contentRootSegment.status = ERRORED; + newBoundary.forceClientRender = true; + newBoundary.errorDigest = logRecoverableError(request, error); + + { + captureBoundaryErrorDetailsDev(newBoundary, error); + } // We don't need to decrement any task numbers because we didn't spawn any new task. + // We don't need to schedule any task because we know the parent has written yet. + // We do need to fallthrough to create the fallback though. + + } finally { + task.blockedBoundary = parentBoundary; + task.blockedSegment = parentSegment; + } // We create suspended task for the fallback because we don't want to actually work + // on it yet in case we finish the main content, so we queue for later. + + + var suspendedFallbackTask = createTask(request, fallback, parentBoundary, boundarySegment, fallbackAbortSet, task.legacyContext, task.context, task.treeContext); + + { + suspendedFallbackTask.componentStack = task.componentStack; + } // TODO: This should be queued at a separate lower priority queue so that we only work + // on preparing fallbacks if we don't have any more main content to task on. + + + request.pingedTasks.push(suspendedFallbackTask); + popComponentStackInDEV(task); +} + +function renderHostElement(request, task, type, props) { + pushBuiltInComponentStackInDEV(task, type); + var segment = task.blockedSegment; + var children = pushStartInstance(segment.chunks, type, props, request.responseState, segment.formatContext); + segment.lastPushedText = false; + var prevContext = segment.formatContext; + segment.formatContext = getChildFormatContext(prevContext, type, props); // We use the non-destructive form because if something suspends, we still + // need to pop back up and finish this subtree of HTML. + + renderNode(request, task, children); // We expect that errors will fatal the whole task and that we don't need + // the correct context. Therefore this is not in a finally. + + segment.formatContext = prevContext; + pushEndInstance(segment.chunks, type); + segment.lastPushedText = false; + popComponentStackInDEV(task); +} + +function shouldConstruct$1(Component) { + return Component.prototype && Component.prototype.isReactComponent; +} + +function renderWithHooks(request, task, Component, props, secondArg) { + var componentIdentity = {}; + prepareToUseHooks(task, componentIdentity); + var result = Component(props, secondArg); + return finishHooks(Component, props, result, secondArg); +} + +function finishClassComponent(request, task, instance, Component, props) { + var nextChildren = instance.render(); + + { + if (instance.props !== props) { + if (!didWarnAboutReassigningProps) { + error('It looks like %s is reassigning its own `this.props` while rendering. ' + 'This is not supported and can lead to confusing bugs.', getComponentNameFromType(Component) || 'a component'); + } + + didWarnAboutReassigningProps = true; + } + } + + { + var childContextTypes = Component.childContextTypes; + + if (childContextTypes !== null && childContextTypes !== undefined) { + var previousContext = task.legacyContext; + var mergedContext = processChildContext(instance, Component, previousContext, childContextTypes); + task.legacyContext = mergedContext; + renderNodeDestructive(request, task, nextChildren); + task.legacyContext = previousContext; + return; + } + } + + renderNodeDestructive(request, task, nextChildren); +} + +function renderClassComponent(request, task, Component, props) { + pushClassComponentStackInDEV(task, Component); + var maskedContext = getMaskedContext(Component, task.legacyContext) ; + var instance = constructClassInstance(Component, props, maskedContext); + mountClassInstance(instance, Component, props, maskedContext); + finishClassComponent(request, task, instance, Component, props); + popComponentStackInDEV(task); +} + +var didWarnAboutBadClass = {}; +var didWarnAboutModulePatternComponent = {}; +var didWarnAboutContextTypeOnFunctionComponent = {}; +var didWarnAboutGetDerivedStateOnFunctionComponent = {}; +var didWarnAboutReassigningProps = false; +var didWarnAboutGenerators = false; +var didWarnAboutMaps = false; +var hasWarnedAboutUsingContextAsConsumer = false; // This would typically be a function component but we still support module pattern +// components for some reason. + +function renderIndeterminateComponent(request, task, Component, props) { + var legacyContext; + + { + legacyContext = getMaskedContext(Component, task.legacyContext); + } + + pushFunctionComponentStackInDEV(task, Component); + + { + if (Component.prototype && typeof Component.prototype.render === 'function') { + var componentName = getComponentNameFromType(Component) || 'Unknown'; + + if (!didWarnAboutBadClass[componentName]) { + error("The <%s /> component appears to have a render method, but doesn't extend React.Component. " + 'This is likely to cause errors. Change %s to extend React.Component instead.', componentName, componentName); + + didWarnAboutBadClass[componentName] = true; + } + } + } + + var value = renderWithHooks(request, task, Component, props, legacyContext); + var hasId = checkDidRenderIdHook(); + + { + // Support for module components is deprecated and is removed behind a flag. + // Whether or not it would crash later, we want to show a good message in DEV first. + if (typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { + var _componentName = getComponentNameFromType(Component) || 'Unknown'; + + if (!didWarnAboutModulePatternComponent[_componentName]) { + error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName, _componentName, _componentName); + + didWarnAboutModulePatternComponent[_componentName] = true; + } + } + } + + if ( // Run these checks in production only if the flag is off. + // Eventually we'll delete this branch altogether. + typeof value === 'object' && value !== null && typeof value.render === 'function' && value.$$typeof === undefined) { + { + var _componentName2 = getComponentNameFromType(Component) || 'Unknown'; + + if (!didWarnAboutModulePatternComponent[_componentName2]) { + error('The <%s /> component appears to be a function component that returns a class instance. ' + 'Change %s to a class that extends React.Component instead. ' + "If you can't use a class try assigning the prototype on the function as a workaround. " + "`%s.prototype = React.Component.prototype`. Don't use an arrow function since it " + 'cannot be called with `new` by React.', _componentName2, _componentName2, _componentName2); + + didWarnAboutModulePatternComponent[_componentName2] = true; + } + } + + mountClassInstance(value, Component, props, legacyContext); + finishClassComponent(request, task, value, Component, props); + } else { + + { + validateFunctionComponentInDev(Component); + } // We're now successfully past this task, and we don't have to pop back to + // the previous task every again, so we can use the destructive recursive form. + + + if (hasId) { + // This component materialized an id. We treat this as its own level, with + // a single "child" slot. + var prevTreeContext = task.treeContext; + var totalChildren = 1; + var index = 0; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); + + try { + renderNodeDestructive(request, task, value); + } finally { + task.treeContext = prevTreeContext; + } + } else { + renderNodeDestructive(request, task, value); + } + } + + popComponentStackInDEV(task); +} + +function validateFunctionComponentInDev(Component) { + { + if (Component) { + if (Component.childContextTypes) { + error('%s(...): childContextTypes cannot be defined on a function component.', Component.displayName || Component.name || 'Component'); + } + } + + if (typeof Component.getDerivedStateFromProps === 'function') { + var _componentName3 = getComponentNameFromType(Component) || 'Unknown'; + + if (!didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3]) { + error('%s: Function components do not support getDerivedStateFromProps.', _componentName3); + + didWarnAboutGetDerivedStateOnFunctionComponent[_componentName3] = true; + } + } + + if (typeof Component.contextType === 'object' && Component.contextType !== null) { + var _componentName4 = getComponentNameFromType(Component) || 'Unknown'; + + if (!didWarnAboutContextTypeOnFunctionComponent[_componentName4]) { + error('%s: Function components do not support contextType.', _componentName4); + + didWarnAboutContextTypeOnFunctionComponent[_componentName4] = true; + } + } + } +} + +function resolveDefaultProps(Component, baseProps) { + if (Component && Component.defaultProps) { + // Resolve default props. Taken from ReactElement + var props = assign({}, baseProps); + var defaultProps = Component.defaultProps; + + for (var propName in defaultProps) { + if (props[propName] === undefined) { + props[propName] = defaultProps[propName]; + } + } + + return props; + } + + return baseProps; +} + +function renderForwardRef(request, task, type, props, ref) { + pushFunctionComponentStackInDEV(task, type.render); + var children = renderWithHooks(request, task, type.render, props, ref); + var hasId = checkDidRenderIdHook(); + + if (hasId) { + // This component materialized an id. We treat this as its own level, with + // a single "child" slot. + var prevTreeContext = task.treeContext; + var totalChildren = 1; + var index = 0; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, index); + + try { + renderNodeDestructive(request, task, children); + } finally { + task.treeContext = prevTreeContext; + } + } else { + renderNodeDestructive(request, task, children); + } + + popComponentStackInDEV(task); +} + +function renderMemo(request, task, type, props, ref) { + var innerType = type.type; + var resolvedProps = resolveDefaultProps(innerType, props); + renderElement(request, task, innerType, resolvedProps, ref); +} + +function renderContextConsumer(request, task, context, props) { + // The logic below for Context differs depending on PROD or DEV mode. In + // DEV mode, we create a separate object for Context.Consumer that acts + // like a proxy to Context. This proxy object adds unnecessary code in PROD + // so we use the old behaviour (Context.Consumer references Context) to + // reduce size and overhead. The separate object references context via + // a property called "_context", which also gives us the ability to check + // in DEV mode if this property exists or not and warn if it does not. + { + if (context._context === undefined) { + // This may be because it's a Context (rather than a Consumer). + // Or it may be because it's older React where they're the same thing. + // We only want to warn if we're sure it's a new React. + if (context !== context.Consumer) { + if (!hasWarnedAboutUsingContextAsConsumer) { + hasWarnedAboutUsingContextAsConsumer = true; + + error('Rendering directly is not supported and will be removed in ' + 'a future major release. Did you mean to render instead?'); + } + } + } else { + context = context._context; + } + } + + var render = props.children; + + { + if (typeof render !== 'function') { + error('A context consumer was rendered with multiple children, or a child ' + "that isn't a function. A context consumer expects a single child " + 'that is a function. If you did pass a function, make sure there ' + 'is no trailing or leading whitespace around it.'); + } + } + + var newValue = readContext(context); + var newChildren = render(newValue); + renderNodeDestructive(request, task, newChildren); +} + +function renderContextProvider(request, task, type, props) { + var context = type._context; + var value = props.value; + var children = props.children; + var prevSnapshot; + + { + prevSnapshot = task.context; + } + + task.context = pushProvider(context, value); + renderNodeDestructive(request, task, children); + task.context = popProvider(context); + + { + if (prevSnapshot !== task.context) { + error('Popping the context provider did not return back to the original snapshot. This is a bug in React.'); + } + } +} + +function renderLazyComponent(request, task, lazyComponent, props, ref) { + pushBuiltInComponentStackInDEV(task, 'Lazy'); + var payload = lazyComponent._payload; + var init = lazyComponent._init; + var Component = init(payload); + var resolvedProps = resolveDefaultProps(Component, props); + renderElement(request, task, Component, resolvedProps, ref); + popComponentStackInDEV(task); +} + +function renderElement(request, task, type, props, ref) { + if (typeof type === 'function') { + if (shouldConstruct$1(type)) { + renderClassComponent(request, task, type, props); + return; + } else { + renderIndeterminateComponent(request, task, type, props); + return; + } + } + + if (typeof type === 'string') { + renderHostElement(request, task, type, props); + return; + } + + switch (type) { + // TODO: LegacyHidden acts the same as a fragment. This only works + // because we currently assume that every instance of LegacyHidden is + // accompanied by a host component wrapper. In the hidden mode, the host + // component is given a `hidden` attribute, which ensures that the + // initial HTML is not visible. To support the use of LegacyHidden as a + // true fragment, without an extra DOM node, we would have to hide the + // initial HTML in some other way. + // TODO: Add REACT_OFFSCREEN_TYPE here too with the same capability. + case REACT_LEGACY_HIDDEN_TYPE: + case REACT_DEBUG_TRACING_MODE_TYPE: + case REACT_STRICT_MODE_TYPE: + case REACT_PROFILER_TYPE: + case REACT_FRAGMENT_TYPE: + { + renderNodeDestructive(request, task, props.children); + return; + } + + case REACT_SUSPENSE_LIST_TYPE: + { + pushBuiltInComponentStackInDEV(task, 'SuspenseList'); // TODO: SuspenseList should control the boundaries. + + renderNodeDestructive(request, task, props.children); + popComponentStackInDEV(task); + return; + } + + case REACT_SCOPE_TYPE: + { + + throw new Error('ReactDOMServer does not yet support scope components.'); + } + // eslint-disable-next-line-no-fallthrough + + case REACT_SUSPENSE_TYPE: + { + { + renderSuspenseBoundary(request, task, props); + } + + return; + } + } + + if (typeof type === 'object' && type !== null) { + switch (type.$$typeof) { + case REACT_FORWARD_REF_TYPE: + { + renderForwardRef(request, task, type, props, ref); + return; + } + + case REACT_MEMO_TYPE: + { + renderMemo(request, task, type, props, ref); + return; + } + + case REACT_PROVIDER_TYPE: + { + renderContextProvider(request, task, type, props); + return; + } + + case REACT_CONTEXT_TYPE: + { + renderContextConsumer(request, task, type, props); + return; + } + + case REACT_LAZY_TYPE: + { + renderLazyComponent(request, task, type, props); + return; + } + } + } + + var info = ''; + + { + if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { + info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and " + 'named imports.'; + } + } + + throw new Error('Element type is invalid: expected a string (for built-in ' + 'components) or a class/function (for composite components) ' + ("but got: " + (type == null ? type : typeof type) + "." + info)); +} + +function validateIterable(iterable, iteratorFn) { + { + // We don't support rendering Generators because it's a mutation. + // See https://github.com/facebook/react/issues/12995 + if (typeof Symbol === 'function' && // $FlowFixMe Flow doesn't know about toStringTag + iterable[Symbol.toStringTag] === 'Generator') { + if (!didWarnAboutGenerators) { + error('Using Generators as children is unsupported and will likely yield ' + 'unexpected results because enumerating a generator mutates it. ' + 'You may convert it to an array with `Array.from()` or the ' + '`[...spread]` operator before rendering. Keep in mind ' + 'you might need to polyfill these features for older browsers.'); + } + + didWarnAboutGenerators = true; + } // Warn about using Maps as children + + + if (iterable.entries === iteratorFn) { + if (!didWarnAboutMaps) { + error('Using Maps as children is not supported. ' + 'Use an array of keyed ReactElements instead.'); + } + + didWarnAboutMaps = true; + } + } +} + +function renderNodeDestructive(request, task, node) { + { + // In Dev we wrap renderNodeDestructiveImpl in a try / catch so we can capture + // a component stack at the right place in the tree. We don't do this in renderNode + // becuase it is not called at every layer of the tree and we may lose frames + try { + return renderNodeDestructiveImpl(request, task, node); + } catch (x) { + if (typeof x === 'object' && x !== null && typeof x.then === 'function') ; else { + // This is an error, stash the component stack if it is null. + lastBoundaryErrorComponentStackDev = lastBoundaryErrorComponentStackDev !== null ? lastBoundaryErrorComponentStackDev : getCurrentStackInDEV(); + } // rethrow so normal suspense logic can handle thrown value accordingly + + + throw x; + } + } +} // This function by it self renders a node and consumes the task by mutating it +// to update the current execution state. + + +function renderNodeDestructiveImpl(request, task, node) { + // Stash the node we're working on. We'll pick up from this task in case + // something suspends. + task.node = node; // Handle object types + + if (typeof node === 'object' && node !== null) { + switch (node.$$typeof) { + case REACT_ELEMENT_TYPE: + { + var element = node; + var type = element.type; + var props = element.props; + var ref = element.ref; + renderElement(request, task, type, props, ref); + return; + } + + case REACT_PORTAL_TYPE: + throw new Error('Portals are not currently supported by the server renderer. ' + 'Render them conditionally so that they only appear on the client render.'); + // eslint-disable-next-line-no-fallthrough + + case REACT_LAZY_TYPE: + { + var lazyNode = node; + var payload = lazyNode._payload; + var init = lazyNode._init; + var resolvedNode; + + { + try { + resolvedNode = init(payload); + } catch (x) { + if (typeof x === 'object' && x !== null && typeof x.then === 'function') { + // this Lazy initializer is suspending. push a temporary frame onto the stack so it can be + // popped off in spawnNewSuspendedTask. This aligns stack behavior between Lazy in element position + // vs Component position. We do not want the frame for Errors so we exclusively do this in + // the wakeable branch + pushBuiltInComponentStackInDEV(task, 'Lazy'); + } + + throw x; + } + } + + renderNodeDestructive(request, task, resolvedNode); + return; + } + } + + if (isArray(node)) { + renderChildrenArray(request, task, node); + return; + } + + var iteratorFn = getIteratorFn(node); + + if (iteratorFn) { + { + validateIterable(node, iteratorFn); + } + + var iterator = iteratorFn.call(node); + + if (iterator) { + // We need to know how many total children are in this set, so that we + // can allocate enough id slots to acommodate them. So we must exhaust + // the iterator before we start recursively rendering the children. + // TODO: This is not great but I think it's inherent to the id + // generation algorithm. + var step = iterator.next(); // If there are not entries, we need to push an empty so we start by checking that. + + if (!step.done) { + var children = []; + + do { + children.push(step.value); + step = iterator.next(); + } while (!step.done); + + renderChildrenArray(request, task, children); + return; + } + + return; + } + } + + var childString = Object.prototype.toString.call(node); + throw new Error("Objects are not valid as a React child (found: " + (childString === '[object Object]' ? 'object with keys {' + Object.keys(node).join(', ') + '}' : childString) + "). " + 'If you meant to render a collection of children, use an array ' + 'instead.'); + } + + if (typeof node === 'string') { + var segment = task.blockedSegment; + segment.lastPushedText = pushTextInstance$1(task.blockedSegment.chunks, node, request.responseState, segment.lastPushedText); + return; + } + + if (typeof node === 'number') { + var _segment = task.blockedSegment; + _segment.lastPushedText = pushTextInstance$1(task.blockedSegment.chunks, '' + node, request.responseState, _segment.lastPushedText); + return; + } + + { + if (typeof node === 'function') { + error('Functions are not valid as a React child. This may happen if ' + 'you return a Component instead of from render. ' + 'Or maybe you meant to call this function rather than return it.'); + } + } +} + +function renderChildrenArray(request, task, children) { + var totalChildren = children.length; + + for (var i = 0; i < totalChildren; i++) { + var prevTreeContext = task.treeContext; + task.treeContext = pushTreeContext(prevTreeContext, totalChildren, i); + + try { + // We need to use the non-destructive form so that we can safely pop back + // up and render the sibling if something suspends. + renderNode(request, task, children[i]); + } finally { + task.treeContext = prevTreeContext; + } + } +} + +function spawnNewSuspendedTask(request, task, x) { + // Something suspended, we'll need to create a new segment and resolve it later. + var segment = task.blockedSegment; + var insertionIndex = segment.chunks.length; + var newSegment = createPendingSegment(request, insertionIndex, null, segment.formatContext, // Adopt the parent segment's leading text embed + segment.lastPushedText, // Assume we are text embedded at the trailing edge + true); + segment.children.push(newSegment); // Reset lastPushedText for current Segment since the new Segment "consumed" it + + segment.lastPushedText = false; + var newTask = createTask(request, task.node, task.blockedBoundary, newSegment, task.abortSet, task.legacyContext, task.context, task.treeContext); + + { + if (task.componentStack !== null) { + // We pop one task off the stack because the node that suspended will be tried again, + // which will add it back onto the stack. + newTask.componentStack = task.componentStack.parent; + } + } + + var ping = newTask.ping; + x.then(ping, ping); +} // This is a non-destructive form of rendering a node. If it suspends it spawns +// a new task and restores the context of this task to what it was before. + + +function renderNode(request, task, node) { + // TODO: Store segment.children.length here and reset it in case something + // suspended partially through writing something. + // Snapshot the current context in case something throws to interrupt the + // process. + var previousFormatContext = task.blockedSegment.formatContext; + var previousLegacyContext = task.legacyContext; + var previousContext = task.context; + var previousComponentStack = null; + + { + previousComponentStack = task.componentStack; + } + + try { + return renderNodeDestructive(request, task, node); + } catch (x) { + resetHooksState(); + + if (typeof x === 'object' && x !== null && typeof x.then === 'function') { + spawnNewSuspendedTask(request, task, x); // Restore the context. We assume that this will be restored by the inner + // functions in case nothing throws so we don't use "finally" here. + + task.blockedSegment.formatContext = previousFormatContext; + task.legacyContext = previousLegacyContext; + task.context = previousContext; // Restore all active ReactContexts to what they were before. + + switchContext(previousContext); + + { + task.componentStack = previousComponentStack; + } + + return; + } else { + // Restore the context. We assume that this will be restored by the inner + // functions in case nothing throws so we don't use "finally" here. + task.blockedSegment.formatContext = previousFormatContext; + task.legacyContext = previousLegacyContext; + task.context = previousContext; // Restore all active ReactContexts to what they were before. + + switchContext(previousContext); + + { + task.componentStack = previousComponentStack; + } // We assume that we don't need the correct context. + // Let's terminate the rest of the tree and don't render any siblings. + + + throw x; + } + } +} + +function erroredTask(request, boundary, segment, error) { + // Report the error to a global handler. + var errorDigest = logRecoverableError(request, error); + + if (boundary === null) { + fatalError(request, error); + } else { + boundary.pendingTasks--; + + if (!boundary.forceClientRender) { + boundary.forceClientRender = true; + boundary.errorDigest = errorDigest; + + { + captureBoundaryErrorDetailsDev(boundary, error); + } // Regardless of what happens next, this boundary won't be displayed, + // so we can flush it, if the parent already flushed. + + + if (boundary.parentFlushed) { + // We don't have a preference where in the queue this goes since it's likely + // to error on the client anyway. However, intentionally client-rendered + // boundaries should be flushed earlier so that they can start on the client. + // We reuse the same queue for errors. + request.clientRenderedBoundaries.push(boundary); + } + } + } + + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + var onAllReady = request.onAllReady; + onAllReady(); + } +} + +function abortTaskSoft(task) { + // This aborts task without aborting the parent boundary that it blocks. + // It's used for when we didn't need this task to complete the tree. + // If task was needed, then it should use abortTask instead. + var request = this; + var boundary = task.blockedBoundary; + var segment = task.blockedSegment; + segment.status = ABORTED; + finishedTask(request, boundary, segment); +} + +function abortTask(task, request, reason) { + // This aborts the task and aborts the parent that it blocks, putting it into + // client rendered mode. + var boundary = task.blockedBoundary; + var segment = task.blockedSegment; + segment.status = ABORTED; + + if (boundary === null) { + request.allPendingTasks--; // We didn't complete the root so we have nothing to show. We can close + // the request; + + if (request.status !== CLOSED) { + request.status = CLOSED; + + if (request.destination !== null) { + close(request.destination); + } + } + } else { + boundary.pendingTasks--; + + if (!boundary.forceClientRender) { + boundary.forceClientRender = true; + + var _error = reason === undefined ? new Error('The render was aborted by the server without a reason.') : reason; + + boundary.errorDigest = request.onError(_error); + + { + var errorPrefix = 'The server did not finish this Suspense boundary: '; + + if (_error && typeof _error.message === 'string') { + _error = errorPrefix + _error.message; + } else { + // eslint-disable-next-line react-internal/safe-string-coercion + _error = errorPrefix + String(_error); + } + + var previousTaskInDev = currentTaskInDEV; + currentTaskInDEV = task; + + try { + captureBoundaryErrorDetailsDev(boundary, _error); + } finally { + currentTaskInDEV = previousTaskInDev; + } + } + + if (boundary.parentFlushed) { + request.clientRenderedBoundaries.push(boundary); + } + } // If this boundary was still pending then we haven't already cancelled its fallbacks. + // We'll need to abort the fallbacks, which will also error that parent boundary. + + + boundary.fallbackAbortableTasks.forEach(function (fallbackTask) { + return abortTask(fallbackTask, request, reason); + }); + boundary.fallbackAbortableTasks.clear(); + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + var onAllReady = request.onAllReady; + onAllReady(); + } + } +} + +function queueCompletedSegment(boundary, segment) { + if (segment.chunks.length === 0 && segment.children.length === 1 && segment.children[0].boundary === null) { + // This is an empty segment. There's nothing to write, so we can instead transfer the ID + // to the child. That way any existing references point to the child. + var childSegment = segment.children[0]; + childSegment.id = segment.id; + childSegment.parentFlushed = true; + + if (childSegment.status === COMPLETED) { + queueCompletedSegment(boundary, childSegment); + } + } else { + var completedSegments = boundary.completedSegments; + completedSegments.push(segment); + } +} + +function finishedTask(request, boundary, segment) { + if (boundary === null) { + if (segment.parentFlushed) { + if (request.completedRootSegment !== null) { + throw new Error('There can only be one root segment. This is a bug in React.'); + } + + request.completedRootSegment = segment; + } + + request.pendingRootTasks--; + + if (request.pendingRootTasks === 0) { + // We have completed the shell so the shell can't error anymore. + request.onShellError = noop$1; + var onShellReady = request.onShellReady; + onShellReady(); + } + } else { + boundary.pendingTasks--; + + if (boundary.forceClientRender) ; else if (boundary.pendingTasks === 0) { + // This must have been the last segment we were waiting on. This boundary is now complete. + if (segment.parentFlushed) { + // Our parent segment already flushed, so we need to schedule this segment to be emitted. + // If it is a segment that was aborted, we'll write other content instead so we don't need + // to emit it. + if (segment.status === COMPLETED) { + queueCompletedSegment(boundary, segment); + } + } + + if (boundary.parentFlushed) { + // The segment might be part of a segment that didn't flush yet, but if the boundary's + // parent flushed, we need to schedule the boundary to be emitted. + request.completedBoundaries.push(boundary); + } // We can now cancel any pending task on the fallback since we won't need to show it anymore. + // This needs to happen after we read the parentFlushed flags because aborting can finish + // work which can trigger user code, which can start flushing, which can change those flags. + + + boundary.fallbackAbortableTasks.forEach(abortTaskSoft, request); + boundary.fallbackAbortableTasks.clear(); + } else { + if (segment.parentFlushed) { + // Our parent already flushed, so we need to schedule this segment to be emitted. + // If it is a segment that was aborted, we'll write other content instead so we don't need + // to emit it. + if (segment.status === COMPLETED) { + queueCompletedSegment(boundary, segment); + var completedSegments = boundary.completedSegments; + + if (completedSegments.length === 1) { + // This is the first time since we last flushed that we completed anything. + // We can schedule this boundary to emit its partially completed segments early + // in case the parent has already been flushed. + if (boundary.parentFlushed) { + request.partialBoundaries.push(boundary); + } + } + } + } + } + } + + request.allPendingTasks--; + + if (request.allPendingTasks === 0) { + // This needs to be called at the very end so that we can synchronously write the result + // in the callback if needed. + var onAllReady = request.onAllReady; + onAllReady(); + } +} + +function retryTask(request, task) { + var segment = task.blockedSegment; + + if (segment.status !== PENDING) { + // We completed this by other means before we had a chance to retry it. + return; + } // We restore the context to what it was when we suspended. + // We don't restore it after we leave because it's likely that we'll end up + // needing a very similar context soon again. + + + switchContext(task.context); + var prevTaskInDEV = null; + + { + prevTaskInDEV = currentTaskInDEV; + currentTaskInDEV = task; + } + + try { + // We call the destructive form that mutates this task. That way if something + // suspends again, we can reuse the same task instead of spawning a new one. + renderNodeDestructive(request, task, task.node); + pushSegmentFinale$1(segment.chunks, request.responseState, segment.lastPushedText, segment.textEmbedded); + task.abortSet.delete(task); + segment.status = COMPLETED; + finishedTask(request, task.blockedBoundary, segment); + } catch (x) { + resetHooksState(); + + if (typeof x === 'object' && x !== null && typeof x.then === 'function') { + // Something suspended again, let's pick it back up later. + var ping = task.ping; + x.then(ping, ping); + } else { + task.abortSet.delete(task); + segment.status = ERRORED; + erroredTask(request, task.blockedBoundary, segment, x); + } + } finally { + { + currentTaskInDEV = prevTaskInDEV; + } + } +} + +function performWork(request) { + if (request.status === CLOSED) { + return; + } + + var prevContext = getActiveContext(); + var prevDispatcher = ReactCurrentDispatcher$1.current; + ReactCurrentDispatcher$1.current = Dispatcher; + var prevGetCurrentStackImpl; + + { + prevGetCurrentStackImpl = ReactDebugCurrentFrame$1.getCurrentStack; + ReactDebugCurrentFrame$1.getCurrentStack = getCurrentStackInDEV; + } + + var prevResponseState = currentResponseState; + setCurrentResponseState(request.responseState); + + try { + var pingedTasks = request.pingedTasks; + var i; + + for (i = 0; i < pingedTasks.length; i++) { + var task = pingedTasks[i]; + retryTask(request, task); + } + + pingedTasks.splice(0, i); + + if (request.destination !== null) { + flushCompletedQueues(request, request.destination); + } + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } finally { + setCurrentResponseState(prevResponseState); + ReactCurrentDispatcher$1.current = prevDispatcher; + + { + ReactDebugCurrentFrame$1.getCurrentStack = prevGetCurrentStackImpl; + } + + if (prevDispatcher === Dispatcher) { + // This means that we were in a reentrant work loop. This could happen + // in a renderer that supports synchronous work like renderToString, + // when it's called from within another renderer. + // Normally we don't bother switching the contexts to their root/default + // values when leaving because we'll likely need the same or similar + // context again. However, when we're inside a synchronous loop like this + // we'll to restore the context to what it was before returning. + switchContext(prevContext); + } + } +} + +function flushSubtree(request, destination, segment) { + segment.parentFlushed = true; + + switch (segment.status) { + case PENDING: + { + // We're emitting a placeholder for this segment to be filled in later. + // Therefore we'll need to assign it an ID - to refer to it by. + var segmentID = segment.id = request.nextSegmentId++; // When this segment finally completes it won't be embedded in text since it will flush separately + + segment.lastPushedText = false; + segment.textEmbedded = false; + return writePlaceholder(destination, request.responseState, segmentID); + } + + case COMPLETED: + { + segment.status = FLUSHED; + var r = true; + var chunks = segment.chunks; + var chunkIdx = 0; + var children = segment.children; + + for (var childIdx = 0; childIdx < children.length; childIdx++) { + var nextChild = children[childIdx]; // Write all the chunks up until the next child. + + for (; chunkIdx < nextChild.index; chunkIdx++) { + writeChunk(destination, chunks[chunkIdx]); + } + + r = flushSegment(request, destination, nextChild); + } // Finally just write all the remaining chunks + + + for (; chunkIdx < chunks.length - 1; chunkIdx++) { + writeChunk(destination, chunks[chunkIdx]); + } + + if (chunkIdx < chunks.length) { + r = writeChunkAndReturn(destination, chunks[chunkIdx]); + } + + return r; + } + + default: + { + throw new Error('Aborted, errored or already flushed boundaries should not be flushed again. This is a bug in React.'); + } + } +} + +function flushSegment(request, destination, segment) { + var boundary = segment.boundary; + + if (boundary === null) { + // Not a suspense boundary. + return flushSubtree(request, destination, segment); + } + + boundary.parentFlushed = true; // This segment is a Suspense boundary. We need to decide whether to + // emit the content or the fallback now. + + if (boundary.forceClientRender) { + // Emit a client rendered suspense boundary wrapper. + // We never queue the inner boundary so we'll never emit its content or partial segments. + writeStartClientRenderedSuspenseBoundary$1(destination, request.responseState, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack); // Flush the fallback. + + flushSubtree(request, destination, segment); + return writeEndClientRenderedSuspenseBoundary$1(destination, request.responseState); + } else if (boundary.pendingTasks > 0) { + // This boundary is still loading. Emit a pending suspense boundary wrapper. + // Assign an ID to refer to the future content by. + boundary.rootSegmentID = request.nextSegmentId++; + + if (boundary.completedSegments.length > 0) { + // If this is at least partially complete, we can queue it to be partially emitted early. + request.partialBoundaries.push(boundary); + } /// This is the first time we should have referenced this ID. + + + var id = boundary.id = assignSuspenseBoundaryID(request.responseState); + writeStartPendingSuspenseBoundary(destination, request.responseState, id); // Flush the fallback. + + flushSubtree(request, destination, segment); + return writeEndPendingSuspenseBoundary(destination, request.responseState); + } else if (boundary.byteSize > request.progressiveChunkSize) { + // This boundary is large and will be emitted separately so that we can progressively show + // other content. We add it to the queue during the flush because we have to ensure that + // the parent flushes first so that there's something to inject it into. + // We also have to make sure that it's emitted into the queue in a deterministic slot. + // I.e. we can't insert it here when it completes. + // Assign an ID to refer to the future content by. + boundary.rootSegmentID = request.nextSegmentId++; + request.completedBoundaries.push(boundary); // Emit a pending rendered suspense boundary wrapper. + + writeStartPendingSuspenseBoundary(destination, request.responseState, boundary.id); // Flush the fallback. + + flushSubtree(request, destination, segment); + return writeEndPendingSuspenseBoundary(destination, request.responseState); + } else { + // We can inline this boundary's content as a complete boundary. + writeStartCompletedSuspenseBoundary$1(destination, request.responseState); + var completedSegments = boundary.completedSegments; + + if (completedSegments.length !== 1) { + throw new Error('A previously unvisited boundary must have exactly one root segment. This is a bug in React.'); + } + + var contentSegment = completedSegments[0]; + flushSegment(request, destination, contentSegment); + return writeEndCompletedSuspenseBoundary$1(destination, request.responseState); + } +} + +function flushClientRenderedBoundary(request, destination, boundary) { + return writeClientRenderBoundaryInstruction(destination, request.responseState, boundary.id, boundary.errorDigest, boundary.errorMessage, boundary.errorComponentStack); +} + +function flushSegmentContainer(request, destination, segment) { + writeStartSegment(destination, request.responseState, segment.formatContext, segment.id); + flushSegment(request, destination, segment); + return writeEndSegment(destination, segment.formatContext); +} + +function flushCompletedBoundary(request, destination, boundary) { + var completedSegments = boundary.completedSegments; + var i = 0; + + for (; i < completedSegments.length; i++) { + var segment = completedSegments[i]; + flushPartiallyCompletedSegment(request, destination, boundary, segment); + } + + completedSegments.length = 0; + return writeCompletedBoundaryInstruction(destination, request.responseState, boundary.id, boundary.rootSegmentID); +} + +function flushPartialBoundary(request, destination, boundary) { + var completedSegments = boundary.completedSegments; + var i = 0; + + for (; i < completedSegments.length; i++) { + var segment = completedSegments[i]; + + if (!flushPartiallyCompletedSegment(request, destination, boundary, segment)) { + i++; + completedSegments.splice(0, i); // Only write as much as the buffer wants. Something higher priority + // might want to write later. + + return false; + } + } + + completedSegments.splice(0, i); + return true; +} + +function flushPartiallyCompletedSegment(request, destination, boundary, segment) { + if (segment.status === FLUSHED) { + // We've already flushed this inline. + return true; + } + + var segmentID = segment.id; + + if (segmentID === -1) { + // This segment wasn't previously referred to. This happens at the root of + // a boundary. We make kind of a leap here and assume this is the root. + var rootSegmentID = segment.id = boundary.rootSegmentID; + + if (rootSegmentID === -1) { + throw new Error('A root segment ID must have been assigned by now. This is a bug in React.'); + } + + return flushSegmentContainer(request, destination, segment); + } else { + flushSegmentContainer(request, destination, segment); + return writeCompletedSegmentInstruction(destination, request.responseState, segmentID); + } +} + +function flushCompletedQueues(request, destination) { + + try { + // The structure of this is to go through each queue one by one and write + // until the sink tells us to stop. When we should stop, we still finish writing + // that item fully and then yield. At that point we remove the already completed + // items up until the point we completed them. + // TODO: Emit preloading. + // TODO: It's kind of unfortunate to keep checking this array after we've already + // emitted the root. + var completedRootSegment = request.completedRootSegment; + + if (completedRootSegment !== null && request.pendingRootTasks === 0) { + flushSegment(request, destination, completedRootSegment); + request.completedRootSegment = null; + writeCompletedRoot(destination, request.responseState); + } // We emit client rendering instructions for already emitted boundaries first. + // This is so that we can signal to the client to start client rendering them as + // soon as possible. + + + var clientRenderedBoundaries = request.clientRenderedBoundaries; + var i; + + for (i = 0; i < clientRenderedBoundaries.length; i++) { + var boundary = clientRenderedBoundaries[i]; + + if (!flushClientRenderedBoundary(request, destination, boundary)) { + request.destination = null; + i++; + clientRenderedBoundaries.splice(0, i); + return; + } + } + + clientRenderedBoundaries.splice(0, i); // Next we emit any complete boundaries. It's better to favor boundaries + // that are completely done since we can actually show them, than it is to emit + // any individual segments from a partially complete boundary. + + var completedBoundaries = request.completedBoundaries; + + for (i = 0; i < completedBoundaries.length; i++) { + var _boundary = completedBoundaries[i]; + + if (!flushCompletedBoundary(request, destination, _boundary)) { + request.destination = null; + i++; + completedBoundaries.splice(0, i); + return; + } + } + + completedBoundaries.splice(0, i); // Allow anything written so far to flush to the underlying sink before + // we continue with lower priorities. + + completeWriting(destination); + beginWriting(destination); // TODO: Here we'll emit data used by hydration. + // Next we emit any segments of any boundaries that are partially complete + // but not deeply complete. + + var partialBoundaries = request.partialBoundaries; + + for (i = 0; i < partialBoundaries.length; i++) { + var _boundary2 = partialBoundaries[i]; + + if (!flushPartialBoundary(request, destination, _boundary2)) { + request.destination = null; + i++; + partialBoundaries.splice(0, i); + return; + } + } + + partialBoundaries.splice(0, i); // Next we check the completed boundaries again. This may have had + // boundaries added to it in case they were too larged to be inlined. + // New ones might be added in this loop. + + var largeBoundaries = request.completedBoundaries; + + for (i = 0; i < largeBoundaries.length; i++) { + var _boundary3 = largeBoundaries[i]; + + if (!flushCompletedBoundary(request, destination, _boundary3)) { + request.destination = null; + i++; + largeBoundaries.splice(0, i); + return; + } + } + + largeBoundaries.splice(0, i); + } finally { + + if (request.allPendingTasks === 0 && request.pingedTasks.length === 0 && request.clientRenderedBoundaries.length === 0 && request.completedBoundaries.length === 0 // We don't need to check any partially completed segments because + // either they have pending task or they're complete. + ) { + { + if (request.abortableTasks.size !== 0) { + error('There was still abortable task at the root when we closed. This is a bug in React.'); + } + } // We're done. + + + close(destination); + } + } +} + +function startWork(request) { + scheduleWork(function () { + return performWork(request); + }); +} +function startFlowing(request, destination) { + if (request.status === CLOSING) { + request.status = CLOSED; + closeWithError(destination, request.fatalError); + return; + } + + if (request.status === CLOSED) { + return; + } + + if (request.destination !== null) { + // We're already flowing. + return; + } + + request.destination = destination; + + try { + flushCompletedQueues(request, destination); + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } +} // This is called to early terminate a request. It puts all pending boundaries in client rendered state. + +function abort(request, reason) { + try { + var abortableTasks = request.abortableTasks; + abortableTasks.forEach(function (task) { + return abortTask(task, request, reason); + }); + abortableTasks.clear(); + + if (request.destination !== null) { + flushCompletedQueues(request, request.destination); + } + } catch (error) { + logRecoverableError(request, error); + fatalError(request, error); + } +} + +function onError() {// Non-fatal errors are ignored. +} + +function renderToStringImpl(children, options, generateStaticMarkup, abortReason) { + var didFatal = false; + var fatalError = null; + var result = ''; + var destination = { + push: function (chunk) { + if (chunk !== null) { + result += chunk; + } + + return true; + }, + destroy: function (error) { + didFatal = true; + fatalError = error; + } + }; + var readyToStream = false; + + function onShellReady() { + readyToStream = true; + } + + var request = createRequest(children, createResponseState$1(generateStaticMarkup, options ? options.identifierPrefix : undefined), createRootFormatContext(), Infinity, onError, undefined, onShellReady, undefined, undefined); + startWork(request); // If anything suspended and is still pending, we'll abort it before writing. + // That way we write only client-rendered boundaries from the start. + + abort(request, abortReason); + startFlowing(request, destination); + + if (didFatal) { + throw fatalError; + } + + if (!readyToStream) { + // Note: This error message is the one we use on the client. It doesn't + // really make sense here. But this is the legacy server renderer, anyway. + // We're going to delete it soon. + throw new Error('A component suspended while responding to synchronous input. This ' + 'will cause the UI to be replaced with a loading indicator. To fix, ' + 'updates that suspend should be wrapped with startTransition.'); + } + + return result; +} + +function renderToString(children, options) { + return renderToStringImpl(children, options, false, 'The server used "renderToString" which does not support Suspense. If you intended for this Suspense boundary to render the fallback content on the server consider throwing an Error somewhere within the Suspense boundary. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'); +} + +function renderToStaticMarkup(children, options) { + return renderToStringImpl(children, options, true, 'The server used "renderToStaticMarkup" which does not support Suspense. If you intended to have the server wait for the suspended component please switch to "renderToReadableStream" which supports Suspense on the server'); +} + +function renderToNodeStream() { + throw new Error('ReactDOMServer.renderToNodeStream(): The streaming API is not available ' + 'in the browser. Use ReactDOMServer.renderToString() instead.'); +} + +function renderToStaticNodeStream() { + throw new Error('ReactDOMServer.renderToStaticNodeStream(): The streaming API is not available ' + 'in the browser. Use ReactDOMServer.renderToStaticMarkup() instead.'); +} + +exports.renderToNodeStream = renderToNodeStream; +exports.renderToStaticMarkup = renderToStaticMarkup; +exports.renderToStaticNodeStream = renderToStaticNodeStream; +exports.renderToString = renderToString; +exports.version = ReactVersion; + })(); +} diff --git a/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js b/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js new file mode 100644 index 00000000..eca01a04 --- /dev/null +++ b/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.min.js @@ -0,0 +1,93 @@ +/** + * @license React + * react-dom-server-legacy.browser.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +'use strict';var aa=require("react");function l(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c