From f315bb228e7a2054ae4a65c98a7a31be00978664 Mon Sep 17 00:00:00 2001 From: mnsinri Date: Sat, 21 Sep 2024 06:32:31 +0900 Subject: [PATCH 1/5] init --- .vscode/settings.json | 11 + firebase.json | 3 +- functions/.eslintrc.js | 16 +- functions/.gitignore | 1 - functions/package-lock.json | 3627 ++++++++++++++++++++--------------- functions/package.json | 13 +- functions/tsconfig.json | 5 +- 7 files changed, 2121 insertions(+), 1555 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d99432f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "editor.formatOnSave": false, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit" + }, + "files.eol": "\n", + "cSpell.words": [ + "Firestore", + "vssdb" + ] +} diff --git a/firebase.json b/firebase.json index 3ef6894..951df83 100644 --- a/firebase.json +++ b/firebase.json @@ -11,8 +11,7 @@ "env.d.ts", "*.log", ".secret.local", - "*.http", - "test.mjs" + "*.http" ] }, "hosting": { diff --git a/functions/.eslintrc.js b/functions/.eslintrc.js index b16341a..6df1fb5 100644 --- a/functions/.eslintrc.js +++ b/functions/.eslintrc.js @@ -9,24 +9,20 @@ module.exports = { "plugin:import/errors", "plugin:import/warnings", "plugin:import/typescript", - "google", "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", ], parser: "@typescript-eslint/parser", parserOptions: { + tsconfigRootDir: __dirname, project: ["tsconfig.json", "tsconfig.dev.json"], sourceType: "module", }, - ignorePatterns: [ - "/lib/**/*", // Ignore built files. - ], - plugins: [ - "@typescript-eslint", - "import", - ], + ignorePatterns: ["/lib/**/*"], + plugins: ["@typescript-eslint", "import"], rules: { - "quotes": ["error", "double"], + quotes: ["error", "double"], "import/no-unresolved": 0, - "indent": ["error", 2], + indent: ["error", 2], }, }; diff --git a/functions/.gitignore b/functions/.gitignore index d3257d2..26450e5 100644 --- a/functions/.gitignore +++ b/functions/.gitignore @@ -11,4 +11,3 @@ node_modules/ .env .secret.local *.http -test.mjs diff --git a/functions/package-lock.json b/functions/package-lock.json index 3d9e959..10dd66a 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -6,64 +6,57 @@ "": { "name": "functions", "dependencies": { - "axios": "^1.4.0", "firebase-admin": "^11.8.0", - "firebase-functions": "^4.3.1", - "googleapis": "^118.0.0" + "firebase-functions": "^4.3.1" }, "devDependencies": { + "@types/node": "^22.5.5", "@typescript-eslint/eslint-plugin": "^5.12.0", "@typescript-eslint/parser": "^5.12.0", "eslint": "^8.9.0", - "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.25.4", + "eslint-plugin-prettier": "^5.2.1", "firebase-functions-test": "^3.1.0", - "typescript": "^4.9.0" + "prettier": "^3.3.3", + "typescript": "^5.6.2" }, "engines": { "node": "18" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "peer": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", - "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "dev": true, "peer": true, "engines": { @@ -71,27 +64,27 @@ } }, "node_modules/@babel/core": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz", - "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dev": true, "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-module-transforms": "^7.22.5", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -101,23 +94,26 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/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/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "peer": true + "peer": true, + "bin": { + "semver": "bin/semver.js" + } }, "node_modules/@babel/generator": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", - "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.22.5", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.25.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { @@ -125,23 +121,20 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz", - "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dev": true, "peer": true, "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-validator-option": "^7.22.5", - "@nicolo-ribaudo/semver-v6": "^6.3.3", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1" + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { @@ -154,6 +147,16 @@ "yallist": "^3.0.2" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -161,80 +164,43 @@ "dev": true, "peer": true }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz", - "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, "peer": true, "engines": { @@ -242,55 +208,41 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "peer": true, "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "peer": true, + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "devOptional": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", - "dev": true, - "peer": true, + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "devOptional": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "peer": true, "engines": { @@ -298,30 +250,30 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dev": true, "peer": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -406,10 +358,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "devOptional": true, + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -456,6 +411,38 @@ "@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==", + "dev": true, + "peer": true, + "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-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "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", @@ -483,13 +470,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -576,6 +563,22 @@ "@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==", + "dev": true, + "peer": true, + "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", @@ -593,13 +596,13 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz", + "integrity": "sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==", "dev": true, "peer": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -609,36 +612,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "peer": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "peer": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", - "debug": "^4.1.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -656,14 +656,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", - "dev": true, - "peer": true, + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", + "devOptional": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -693,23 +692,23 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -725,9 +724,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -815,15 +814,15 @@ } }, "node_modules/@google-cloud/firestore": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.6.1.tgz", - "integrity": "sha512-Z41j2h0mrgBH9qNIVmbRLqGKc6XmdJtWipeKwdnGa/bPTP1gn2SGTrYyWnpfsLMEtzKSYieHPSkAFp5kduF2RA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-6.8.0.tgz", + "integrity": "sha512-JRpk06SmZXLGz0pNx1x7yU3YhkUXheKgH5hbDZ4kMsdhtfV5qPLJLRI4wv69K0cZorIk+zTMOwptue7hizo0eA==", "optional": true, "dependencies": { "fast-deep-equal": "^3.1.1", "functional-red-black-tree": "^1.0.1", "google-gax": "^3.5.7", - "protobufjs": "^7.0.0" + "protobufjs": "^7.2.5" }, "engines": { "node": ">=12.0.0" @@ -861,9 +860,9 @@ } }, "node_modules/@google-cloud/storage": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.10.1.tgz", - "integrity": "sha512-EtLlT0YbXtrbUxaNbEfTyTytrjELtl4i42flf8COg+Hu5+apdNjsFO9XEY39wshxAuVjLf4fCSm7GTSW+BD3gQ==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.12.0.tgz", + "integrity": "sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==", "optional": true, "dependencies": { "@google-cloud/paginator": "^3.0.7", @@ -875,6 +874,7 @@ "duplexify": "^4.0.0", "ent": "^2.2.0", "extend": "^3.0.2", + "fast-xml-parser": "^4.2.2", "gaxios": "^5.0.0", "google-auth-library": "^8.0.1", "mime": "^3.0.0", @@ -898,9 +898,9 @@ } }, "node_modules/@grpc/grpc-js": { - "version": "1.8.14", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.14.tgz", - "integrity": "sha512-w84maJ6CKl5aApCMzFll0hxtFNT6or9WwMslobKaqWUEf1K+zhlL43bSQhFreyYWIWR+Z0xnVFC1KtLm4ZpM/A==", + "version": "1.8.22", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz", + "integrity": "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA==", "optional": true, "dependencies": { "@grpc/proto-loader": "^0.7.0", @@ -911,15 +911,14 @@ } }, "node_modules/@grpc/proto-loader": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.7.tgz", - "integrity": "sha512-1TIeXOi8TuSCQprPItwoMymZXxWT0CPxUhkrkeCUH+D8U7QDwQ6b7SUz2MaLuWM2llT+J/TVFLmQI5KtML3BhQ==", + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", "optional": true, "dependencies": { - "@types/long": "^4.0.1", "lodash.camelcase": "^4.3.0", - "long": "^4.0.0", - "protobufjs": "^7.0.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", "yargs": "^17.7.2" }, "bin": { @@ -930,13 +929,14 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -957,9 +957,10 @@ } }, "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -1080,17 +1081,17 @@ } }, "node_modules/@jest/console": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", - "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1098,38 +1099,38 @@ } }, "node_modules/@jest/core": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", - "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/reporters": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-resolve-dependencies": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "jest-watcher": "^29.6.1", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -1146,94 +1147,94 @@ } }, "node_modules/@jest/environment": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", - "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "peer": true, "dependencies": { - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.1" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "peer": true, "dependencies": { - "expect": "^29.6.1", - "jest-snapshot": "^29.6.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", - "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "peer": true, "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", - "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", - "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/types": "^29.6.1", - "jest-mock": "^29.6.1" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", - "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, "peer": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", @@ -1242,13 +1243,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1267,9 +1268,9 @@ } }, "node_modules/@jest/schemas": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", - "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "peer": true, "dependencies": { @@ -1280,9 +1281,9 @@ } }, "node_modules/@jest/source-map": { - "version": "29.6.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", - "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "peer": true, "dependencies": { @@ -1295,14 +1296,14 @@ } }, "node_modules/@jest/test-result": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", - "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1311,15 +1312,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", - "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "peer": true, "dependencies": { - "@jest/test-result": "^29.6.1", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1327,23 +1328,23 @@ } }, "node_modules/@jest/transform": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", - "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "peer": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1354,13 +1355,13 @@ } }, "node_modules/@jest/types": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", - "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "peer": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1372,24 +1373,24 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/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==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "peer": true, "engines": { @@ -1397,9 +1398,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "peer": true, "engines": { @@ -1407,34 +1408,27 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "peer": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "peer": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/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==", - "dev": true, - "peer": true - }, "node_modules/@jsdoc/salty": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", - "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.8.tgz", + "integrity": "sha512-5e+SFVavj1ORKlKaKr2BmTOekmXbelU7dC0cDkQLqag7xfuTPuGMUFx7KWJuv4bYZrTsoL2Z18VVCOKYxzoHcg==", "optional": true, "dependencies": { "lodash": "^4.17.21" @@ -1443,16 +1437,6 @@ "node": ">=v12.0.0" } }, - "node_modules/@nicolo-ribaudo/semver-v6": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz", - "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1488,6 +1472,18 @@ "node": ">= 8" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1542,6 +1538,12 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1550,9 +1552,9 @@ "peer": true }, "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "peer": true, "dependencies": { @@ -1579,9 +1581,9 @@ } }, "node_modules/@types/babel__core": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", - "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "peer": true, "dependencies": { @@ -1593,9 +1595,9 @@ } }, "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==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "peer": true, "dependencies": { @@ -1603,9 +1605,9 @@ } }, "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==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "peer": true, "dependencies": { @@ -1614,9 +1616,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", - "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, "peer": true, "dependencies": { @@ -1624,26 +1626,26 @@ } }, "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==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dependencies": { "@types/connect": "*", "@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==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dependencies": { "@types/node": "*" } @@ -1659,9 +1661,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.35", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", - "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -1680,26 +1682,31 @@ } }, "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==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "peer": true, "dependencies": { "@types/node": "*" } }, - "node_modules/@types/istanbul-lib-coverage": { + "node_modules/@types/http-errors": { "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==", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true, "peer": true }, "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==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "peer": true, "dependencies": { @@ -1707,9 +1714,9 @@ } }, "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==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "peer": true, "dependencies": { @@ -1717,9 +1724,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/json5": { @@ -1729,23 +1736,23 @@ "dev": true }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "optional": true }, "node_modules/@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", "dev": true }, "node_modules/@types/long": { @@ -1755,25 +1762,25 @@ "optional": true }, "node_modules/@types/markdown-it": { - "version": "12.2.3", - "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", - "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "optional": true, "dependencies": { - "@types/linkify-it": "*", - "@types/mdurl": "*" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "optional": true }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" }, "node_modules/@types/minimatch": { "version": "5.1.2", @@ -1782,26 +1789,22 @@ "optional": true }, "node_modules/@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" - }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true, - "peer": true + "version": "22.5.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.5.tgz", + "integrity": "sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==", + "dependencies": { + "undici-types": "~6.19.2" + } }, "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==" + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==" }, "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==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/rimraf": { "version": "3.0.2", @@ -1814,40 +1817,41 @@ } }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "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==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "dependencies": { - "@types/mime": "*", - "@types/node": "*" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" } }, "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true, "peer": true }, "node_modules/@types/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "peer": true, "dependencies": { @@ -1855,24 +1859,24 @@ } }, "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==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true, "peer": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz", - "integrity": "sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.8", - "@typescript-eslint/type-utils": "5.59.8", - "@typescript-eslint/utils": "5.59.8", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -1895,15 +1899,54 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "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/eslint-plugin/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.8.tgz", - "integrity": "sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.8", - "@typescript-eslint/types": "5.59.8", - "@typescript-eslint/typescript-estree": "5.59.8", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" }, "engines": { @@ -1923,13 +1966,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", - "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.8", - "@typescript-eslint/visitor-keys": "5.59.8" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1940,13 +1983,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz", - "integrity": "sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.8", - "@typescript-eslint/utils": "5.59.8", + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -1966,60 +2009,71 @@ } } }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", - "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "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/typescript-estree": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", - "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", + "node_modules/@typescript-eslint/type-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==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.8", - "@typescript-eslint/visitor-keys": "5.59.8", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, "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.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", - "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.8", - "@typescript-eslint/types": "5.59.8", - "@typescript-eslint/typescript-estree": "5.59.8", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.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" @@ -2028,17 +2082,19 @@ "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/visitor-keys": { - "version": "5.59.8", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", - "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2049,6 +2105,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2074,9 +2136,9 @@ } }, "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==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "devOptional": true, "bin": { "acorn": "bin/acorn" @@ -2098,6 +2160,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, "dependencies": { "debug": "4" }, @@ -2195,13 +2258,16 @@ "devOptional": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2213,15 +2279,16 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "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==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -2240,15 +2307,35 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -2259,14 +2346,14 @@ } }, "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==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -2276,10 +2363,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "optional": true, "engines": { "node": ">=8" } @@ -2293,16 +2403,14 @@ "retry": "0.13.1" } }, - "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/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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2310,27 +2418,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/babel-jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", - "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "peer": true, "dependencies": { - "@jest/transform": "^29.6.1", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -2359,10 +2457,37 @@ "node": ">=8" } }, + "node_modules/babel-plugin-istanbul/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==", + "dev": true, + "peer": true, + "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/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "peer": true, "dependencies": { @@ -2376,37 +2501,40 @@ } }, "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==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "peer": true, "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-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^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.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-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "peer": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2439,12 +2567,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true }, "node_modules/bignumber.js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", - "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "optional": true, "engines": { "node": "*" } @@ -2456,20 +2586,20 @@ "optional": true }, "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==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "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", + "qs": "6.13.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -2495,28 +2625,28 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -2534,10 +2664,10 @@ ], "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -2577,12 +2707,18 @@ } }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2608,9 +2744,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001514", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001514.tgz", - "integrity": "sha512-ENcIpYBmwAAOm/V2cXgM7rZUrKKaqisZl4ZAI520FIkqGXUxJjmaIssbRW5HVVR5tyV6ygTLIm15aU8LUmQSaQ==", + "version": "1.0.30001662", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz", + "integrity": "sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==", "dev": true, "funding": [ { @@ -2667,9 +2803,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -2683,9 +2819,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", "dev": true, "peer": true }, @@ -2739,17 +2875,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "devOptional": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -2766,7 +2891,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true + "dev": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -2795,9 +2920,9 @@ "peer": true }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -2819,6 +2944,28 @@ "node": ">= 0.10" } }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2833,12 +2980,63 @@ "node": ">= 8" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2850,11 +3048,19 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, - "peer": true + "peer": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deep-is": { "version": "0.1.4", @@ -2872,12 +3078,29 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-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==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -2888,14 +3111,6 @@ "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", @@ -2924,9 +3139,9 @@ } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "peer": true, "engines": { @@ -2958,15 +3173,15 @@ } }, "node_modules/duplexify": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", - "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", "optional": true, "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", - "stream-shift": "^1.0.0" + "stream-shift": "^1.0.2" } }, "node_modules/ecdsa-sig-formatter": { @@ -2983,9 +3198,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.454", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.454.tgz", - "integrity": "sha512-pmf1rbAStw8UEQ0sr2cdJtWl48ZMuPD9Sto8HVQOq9vx9j2WgDEN6lYoaqFvqEHYOmGA9oRGn7LqWI9ta0YugQ==", + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.25.tgz", + "integrity": "sha512-kMb204zvK3PsSlgvvwzI3wBIcAw15tRkYk+NQdsjdDtcQWTp2RABbMQ9rUBy8KNEOM+/E6ep+XC3AykiWZld4g==", "dev": true, "peer": true }, @@ -3009,9 +3224,9 @@ "devOptional": true }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } @@ -3026,16 +3241,25 @@ } }, "node_modules/ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "optional": true + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.1.tgz", + "integrity": "sha512-QHuXVeZx9d+tIQAz/XztU0ZwZf2Agg9CcXcgE1rurqvdBeDBrpSwjl8/6XUqMg7tw2Y7uAdKb2sRv+bSEFqQ5A==", + "optional": true, + "dependencies": { + "punycode": "^1.4.1" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/entities": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", - "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "optional": true, + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -3051,45 +3275,57 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -3098,27 +3334,58 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -3139,9 +3406,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "devOptional": true, "engines": { "node": ">=6" @@ -3238,27 +3505,28 @@ } }, "node_modules/eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3268,7 +3536,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -3278,9 +3545,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -3293,27 +3559,27 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-google": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", - "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "eslint": ">=5.16.0" + "eslint": ">=7.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==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -3326,9 +3592,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", + "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -3352,26 +3618,29 @@ } }, "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==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", "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" + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -3402,43 +3671,48 @@ } }, "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==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" }, "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", - "devOptional": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -3451,7 +3725,7 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { + "node_modules/eslint-scope/node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -3460,13 +3734,25 @@ "node": ">=4.0" } }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "devOptional": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "devOptional": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -3491,9 +3777,9 @@ } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -3602,54 +3888,53 @@ } }, "node_modules/expect": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", - "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "peer": true, "dependencies": { - "@jest/expect-utils": "^29.6.1", - "@types/node": "*", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.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==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -3676,7 +3961,8 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -3684,10 +3970,16 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "devOptional": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -3727,12 +4019,35 @@ "node_modules/fast-text-encoding": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", - "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "optional": true + }, + "node_modules/fast-xml-parser": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz", + "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } }, "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==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3772,9 +4087,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -3784,12 +4099,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -3830,9 +4145,9 @@ } }, "node_modules/firebase-admin": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.9.0.tgz", - "integrity": "sha512-My7qrInVZFmImX8aTulrp9kgY6d88Wn+ie8UIXKzZ3SJqQQhDwFT7Q3pgQXK9RfdsUtcxJJ3rCK7MWBm4GGtuw==", + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-11.11.1.tgz", + "integrity": "sha512-UyEbq+3u6jWzCYbUntv/HuJiTixwh36G1R9j0v71mSvGAx/YZEWEW7uSGLYxBYE6ckVRQoKMr40PYUEzrm/4dg==", "dependencies": { "@fastify/busboy": "^1.2.1", "@firebase/database-compat": "^0.3.4", @@ -3847,20 +4162,19 @@ "node": ">=14" }, "optionalDependencies": { - "@google-cloud/firestore": "^6.6.0", + "@google-cloud/firestore": "^6.8.0", "@google-cloud/storage": "^6.9.5" } }, "node_modules/firebase-functions": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-4.4.0.tgz", - "integrity": "sha512-Vdkr9/y/UKQez//cPm2Iu/9CeayqQ2tQF6o3KXozDDBokK9AOlAalVHImCpKo6nWptT/ncZ8djJFk5cR8l+E+A==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-4.9.0.tgz", + "integrity": "sha512-IqxOEsVAWGcRv9KRGzWQR5mOFuNsil3vsfkRPPiaV1U/ATC27/jbahh4z8I4rW8Xqa6cQE5xqnw0ueyMH7i7Ag==", "dependencies": { "@types/cors": "^2.8.5", "@types/express": "4.17.3", "cors": "^2.8.5", "express": "^4.17.1", - "node-fetch": "^2.6.7", "protobufjs": "^7.2.2" }, "bin": { @@ -3870,13 +4184,13 @@ "node": ">=14.10.0" }, "peerDependencies": { - "firebase-admin": "^10.0.0 || ^11.0.0" + "firebase-admin": "^10.0.0 || ^11.0.0 || ^12.0.0" } }, "node_modules/firebase-functions-test": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/firebase-functions-test/-/firebase-functions-test-3.1.0.tgz", - "integrity": "sha512-yfm9ToguShxmRXb7TINN88zE2bM9gsBbs7vMWVKJAxGcl/n1f/U0sT5k2yho676QIcSqXVSjCONU8W4cUEL+Sw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/firebase-functions-test/-/firebase-functions-test-3.3.0.tgz", + "integrity": "sha512-X+OOA34MGrsTimFXTDnWT0psAqnmBkJ85bGCoLMwjgei5Prfkqh3bv5QASnXC/cmIVBSF2Qw9uW1+mF/t3kFlw==", "dev": true, "dependencies": { "@types/lodash": "^4.14.104", @@ -3887,18 +4201,19 @@ "node": ">=14.0.0" }, "peerDependencies": { - "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0", - "firebase-functions": ">=4.3.0", + "firebase-admin": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", + "firebase-functions": ">=4.9.0", "jest": ">=28.0.0" } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -3906,30 +4221,11 @@ } }, "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==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3939,19 +4235,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3975,9 +4258,9 @@ "devOptional": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -3990,20 +4273,23 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "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==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -4028,23 +4314,25 @@ } }, "node_modules/gaxios": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.0.tgz", - "integrity": "sha512-aezGIjb+/VfsJtIcHGcBSerNEDdfdHeMros+RbYbGpmonKWQCOVOes0LVZhn1lDtIgq55qq0HaxymIoae3Fl/A==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" + "node-fetch": "^2.6.9" }, "engines": { "node": ">=12" } }, "node_modules/gcp-metadata": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.2.0.tgz", - "integrity": "sha512-aFhhvvNycky2QyhG+dcfEdHBF0FRbYcf39s6WNHUDysKSrbJ5vuFbjydxBcmewtXeV248GP8dWT3ByPNxsyHCw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, "dependencies": { "gaxios": "^5.0.0", "json-bigint": "^1.0.0" @@ -4073,14 +4361,18 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4110,13 +4402,14 @@ } }, "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==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -4129,7 +4422,8 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "devOptional": true, + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4158,9 +4452,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -4173,12 +4467,13 @@ } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -4208,16 +4503,17 @@ } }, "node_modules/google-auth-library": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.8.0.tgz", - "integrity": "sha512-0iJn7IDqObDG5Tu9Tn2WemmJ31ksEa96IyK0J0OZCpTh6CrC6FrattwKX87h3qKVuprCJpdOGKc1Xi8V0kMh8Q==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.9.0.tgz", + "integrity": "sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg==", + "optional": true, "dependencies": { "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", "gaxios": "^5.0.0", - "gcp-metadata": "^5.2.0", + "gcp-metadata": "^5.3.0", "gtoken": "^6.1.0", "jws": "^4.0.0", "lru-cache": "^6.0.0" @@ -4227,9 +4523,9 @@ } }, "node_modules/google-gax": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.0.tgz", - "integrity": "sha512-2fyb61vWxUonHiArRNJQmE4tx5oY1ni8VPo08fzII409vDSCWG7apDX4qNOQ2GXXT82gLBn3d3P1Dydh7pWjyw==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-3.6.1.tgz", + "integrity": "sha512-g/lcUjGcB6DSw2HxgEmCDOrI/CByOwqRvsuUvNalHUK2iPPPlmAIpbMbl62u0YufGMr8zgE3JL7th6dCb1Ry+w==", "optional": true, "dependencies": { "@grpc/grpc-js": "~1.8.0", @@ -4244,7 +4540,7 @@ "node-fetch": "^2.6.1", "object-hash": "^3.0.0", "proto3-json-serializer": "^1.0.0", - "protobufjs": "7.2.3", + "protobufjs": "7.2.4", "protobufjs-cli": "1.1.1", "retry-request": "^5.0.0" }, @@ -4256,10 +4552,36 @@ "node": ">=12" } }, + "node_modules/google-gax/node_modules/protobufjs": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/google-p12-pem": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", + "deprecated": "Package is no longer maintained", + "optional": true, "dependencies": { "node-forge": "^1.3.1" }, @@ -4270,39 +4592,10 @@ "node": ">=12.0.0" } }, - "node_modules/googleapis": { - "version": "118.0.0", - "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-118.0.0.tgz", - "integrity": "sha512-Ny6zJOGn5P/YDT6GQbJU6K0lSzEu4Yuxnsn45ZgBIeSQ1RM0FolEjUToLXquZd89DU9wUfqA5XYHPEctk1TFWg==", - "dependencies": { - "google-auth-library": "^8.0.2", - "googleapis-common": "^6.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/googleapis-common": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-6.0.4.tgz", - "integrity": "sha512-m4ErxGE8unR1z0VajT6AYk3s6a9gIMM6EkDZfkPnES8joeOlEtFEJeF8IyZkb0tjPXkktUfYrE4b3Li1DNyOwA==", - "dependencies": { - "extend": "^3.0.2", - "gaxios": "^5.0.1", - "google-auth-library": "^8.0.2", - "qs": "^6.7.0", - "url-template": "^2.0.8", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -4316,12 +4609,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "devOptional": true }, - "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==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -4332,6 +4619,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", + "optional": true, "dependencies": { "gaxios": "^5.0.1", "google-p12-pem": "^4.0.0", @@ -4341,17 +4629,6 @@ "node": ">=12.0.0" } }, - "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", @@ -4371,21 +4648,20 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "engines": { "node": ">= 0.4" }, @@ -4405,12 +4681,12 @@ } }, "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==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -4419,6 +4695,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -4464,6 +4751,7 @@ "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==", + "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -4494,9 +4782,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -4519,9 +4807,9 @@ } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "peer": true, "dependencies": { @@ -4551,6 +4839,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "devOptional": true, "dependencies": { "once": "^1.3.0", @@ -4563,13 +4852,13 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "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==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -4585,14 +4874,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4646,12 +4937,30 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4713,9 +5022,9 @@ } }, "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==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -4774,12 +5083,15 @@ } }, "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4789,6 +5101,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "devOptional": true, "engines": { "node": ">=8" }, @@ -4833,16 +5146,12 @@ } }, "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==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "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" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4863,6 +5172,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4870,9 +5185,9 @@ "dev": true }, "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==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "peer": true, "engines": { @@ -4880,45 +5195,35 @@ } }, "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==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "peer": true, "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "semver": "^7.5.4" }, "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==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "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==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "peer": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { @@ -4937,9 +5242,9 @@ } }, "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==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "peer": true, "dependencies": { @@ -4951,16 +5256,16 @@ } }, "node_modules/jest": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", - "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "peer": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.6.1" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -4978,13 +5283,14 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "peer": true, "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -4992,29 +5298,29 @@ } }, "node_modules/jest-circus": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", - "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/expect": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.6.1", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -5024,23 +5330,22 @@ } }, "node_modules/jest-cli": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", - "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, "peer": true, "dependencies": { - "@jest/core": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -5059,32 +5364,32 @@ } }, "node_modules/jest-config": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", - "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "peer": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.6.1", - "@jest/types": "^29.6.1", - "babel-jest": "^29.6.1", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.6.1", - "jest-environment-node": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-runner": "^29.6.1", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -5105,25 +5410,25 @@ } }, "node_modules/jest-diff": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", - "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "peer": true, "dependencies": { @@ -5134,44 +5439,44 @@ } }, "node_modules/jest-each": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", - "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.6.1", - "pretty-format": "^29.6.1" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", - "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.6.1", - "jest-util": "^29.6.1" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "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==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "peer": true, "engines": { @@ -5179,21 +5484,21 @@ } }, "node_modules/jest-haste-map": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", - "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -5205,49 +5510,49 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", - "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "peer": true, "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", - "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.6.1" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", - "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.6.1", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -5256,15 +5561,15 @@ } }, "node_modules/jest-mock": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", - "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.6.1" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5289,9 +5594,9 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "peer": true, "engines": { @@ -5299,18 +5604,18 @@ } }, "node_modules/jest-resolve": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", - "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "peer": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.6.1", - "jest-validate": "^29.6.1", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -5320,45 +5625,45 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", - "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "peer": true, "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.6.1" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", - "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, "peer": true, "dependencies": { - "@jest/console": "^29.6.1", - "@jest/environment": "^29.6.1", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.6.1", - "jest-haste-map": "^29.6.1", - "jest-leak-detector": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-resolve": "^29.6.1", - "jest-runtime": "^29.6.1", - "jest-util": "^29.6.1", - "jest-watcher": "^29.6.1", - "jest-worker": "^29.6.1", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -5367,32 +5672,32 @@ } }, "node_modules/jest-runtime": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", - "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "peer": true, "dependencies": { - "@jest/environment": "^29.6.1", - "@jest/fake-timers": "^29.6.1", - "@jest/globals": "^29.6.1", - "@jest/source-map": "^29.6.0", - "@jest/test-result": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-mock": "^29.6.1", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.6.1", - "jest-snapshot": "^29.6.1", - "jest-util": "^29.6.1", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -5401,9 +5706,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", - "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "peer": true, "dependencies": { @@ -5412,21 +5717,20 @@ "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.6.1", - "@jest/transform": "^29.6.1", - "@jest/types": "^29.6.1", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.6.1", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.6.1", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.6.1", - "jest-message-util": "^29.6.1", - "jest-util": "^29.6.1", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.6.1", + "pretty-format": "^29.7.0", "semver": "^7.5.3" }, "engines": { @@ -5434,13 +5738,13 @@ } }, "node_modules/jest-util": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", - "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -5452,18 +5756,18 @@ } }, "node_modules/jest-validate": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", - "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "peer": true, "dependencies": { - "@jest/types": "^29.6.1", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.6.1" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5483,19 +5787,19 @@ } }, "node_modules/jest-watcher": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", - "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "peer": true, "dependencies": { - "@jest/test-result": "^29.6.1", - "@jest/types": "^29.6.1", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.6.1", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -5503,14 +5807,14 @@ } }, "node_modules/jest-worker": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", - "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "peer": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.6.1", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -5535,9 +5839,9 @@ } }, "node_modules/jose": { - "version": "4.14.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", - "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", "funding": { "url": "https://github.com/sponsors/panva" } @@ -5571,21 +5875,21 @@ } }, "node_modules/jsdoc": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", - "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.3.tgz", + "integrity": "sha512-Nu7Sf35kXJ1MWDZIMAuATRQTg1iIPdzh7tqJ6jjvaU/GfDf+qi5UV8zJR3Mo+/pYFvm8mzay4+6O5EWigaQBQw==", "optional": true, "dependencies": { "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", - "@types/markdown-it": "^12.2.3", + "@types/markdown-it": "^14.1.1", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^3.0.0", - "markdown-it": "^12.3.2", - "markdown-it-anchor": "^8.4.1", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", @@ -5625,10 +5929,17 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "optional": true, "dependencies": { "bignumber.js": "^9.0.0" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-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", @@ -5662,14 +5973,20 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">=12", @@ -5699,6 +6016,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "optional": true, "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -5706,25 +6024,25 @@ } }, "node_modules/jwks-rsa": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.0.1.tgz", - "integrity": "sha512-UUOZ0CVReK1QVU3rbi9bC7N5/le8ziUj0A2ef1Q0M7OPD2KvjEYizptqIxGIo6fSLYDkqBrazILS18tYuRc8gw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-3.1.0.tgz", + "integrity": "sha512-v7nqlfezb9YfHHzYII3ef2a2j1XnGeSE/bK3WfumaYCqONAIstJbrEGapz4kadScZzEt7zYCN7bucj8C0Mv/Rg==", "dependencies": { - "@types/express": "^4.17.14", - "@types/jsonwebtoken": "^9.0.0", + "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", "debug": "^4.3.4", - "jose": "^4.10.4", + "jose": "^4.14.6", "limiter": "^1.1.5", - "lru-memoizer": "^2.1.4" + "lru-memoizer": "^2.2.0" }, "engines": { "node": ">=14" } }, "node_modules/jwks-rsa/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==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -5736,11 +6054,21 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "optional": true, "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -5796,12 +6124,12 @@ "peer": true }, "node_modules/linkify-it": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", - "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "optional": true, "dependencies": { - "uc.micro": "^1.0.1" + "uc.micro": "^2.0.0" } }, "node_modules/locate-path": { @@ -5822,7 +6150,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "devOptional": true }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -5835,17 +6164,51 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "optional": true + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "node_modules/lru-cache": { "version": "6.0.0", @@ -5859,52 +6222,28 @@ } }, "node_modules/lru-memoizer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.2.0.tgz", - "integrity": "sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.3.0.tgz", + "integrity": "sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug==", "dependencies": { "lodash.clonedeep": "^4.5.0", - "lru-cache": "~4.0.0" - } - }, - "node_modules/lru-memoizer/node_modules/lru-cache": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", - "integrity": "sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==", - "dependencies": { - "pseudomap": "^1.0.1", - "yallist": "^2.0.0" + "lru-cache": "6.0.0" } }, - "node_modules/lru-memoizer/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" - }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "peer": true, "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "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==", - "dev": true, - "peer": true, - "bin": { - "semver": "bin/semver.js" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/makeerror": { @@ -5918,19 +6257,20 @@ } }, "node_modules/markdown-it": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", - "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "optional": true, "dependencies": { "argparse": "^2.0.1", - "entities": "~2.1.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, "bin": { - "markdown-it": "bin/markdown-it.js" + "markdown-it": "bin/markdown-it.mjs" } }, "node_modules/markdown-it-anchor": { @@ -5956,9 +6296,9 @@ } }, "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "optional": true }, "node_modules/media-typer": { @@ -5970,9 +6310,12 @@ } }, "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==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -5999,12 +6342,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -6024,9 +6367,10 @@ } }, "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==", + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "optional": true, "engines": { "node": ">= 0.6" } @@ -6042,6 +6386,14 @@ "node": ">= 0.6" } }, + "node_modules/mime-types/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/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -6056,7 +6408,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6086,9 +6438,9 @@ } }, "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==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -6111,9 +6463,10 @@ } }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -6145,9 +6498,9 @@ "peer": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, "peer": true }, @@ -6192,9 +6545,12 @@ } }, "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==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6209,13 +6565,13 @@ } }, "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==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -6226,15 +6582,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6280,17 +6668,17 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -6388,7 +6776,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6409,9 +6797,9 @@ "dev": true }, "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==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==" }, "node_modules/path-type": { "version": "4.0.0", @@ -6423,9 +6811,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "peer": true }, @@ -6520,6 +6908,15 @@ "node": ">=8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6529,14 +6926,41 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { - "version": "29.6.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", - "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "peer": true, "dependencies": { - "@jest/schemas": "^29.6.0", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -6584,9 +7008,9 @@ } }, "node_modules/protobufjs": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.3.tgz", - "integrity": "sha512-TtpvOqwB5Gdz/PQmOjgsrGH1nHjAQVCN7JG4A6r1sXRWESL5rNMAiRcBQlCAdKxZcAbstExQePYG8xof/JVRgg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -6656,6 +7080,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "optional": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -6683,11 +7108,6 @@ "node": ">=10" } }, - "node_modules/protobufjs/node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -6700,29 +7120,25 @@ "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/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" - }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "optional": true + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "optional": true, "engines": { "node": ">=6" } }, "node_modules/pure-rand": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", - "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, "funding": [ { @@ -6737,11 +7153,11 @@ "peer": true }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -6779,9 +7195,9 @@ } }, "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==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6793,9 +7209,9 @@ } }, "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==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, "peer": true }, @@ -6814,14 +7230,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -6849,12 +7266,12 @@ } }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -6943,7 +7360,8 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "devOptional": true, + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -6977,6 +7395,24 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6997,15 +7433,18 @@ ] }, "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==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7016,12 +7455,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -7030,9 +7466,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -7065,6 +7501,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/send/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/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -7076,25 +7520,51 @@ "node": ">=4" } }, - "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/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==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -7122,13 +7592,17 @@ } }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7225,9 +7699,9 @@ } }, "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "optional": true }, "node_modules/string_decoder": { @@ -7268,14 +7742,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7285,28 +7760,31 @@ } }, "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==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7356,6 +7834,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", @@ -7386,6 +7870,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/teeny-request": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", @@ -7429,15 +7929,12 @@ "dev": true }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "optional": true, - "dependencies": { - "rimraf": "^3.0.0" - }, "engines": { - "node": ">=8.17.0" + "node": ">=14.14" } }, "node_modules/tmpl": { @@ -7451,8 +7948,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "peer": true, + "devOptional": true, "engines": { "node": ">=4" } @@ -7480,7 +7976,8 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true }, "node_modules/ts-deepmerge": { "version": "2.0.7", @@ -7489,9 +7986,9 @@ "dev": true }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -7522,9 +8019,9 @@ } }, "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -7593,43 +8090,102 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "optional": true }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -7654,11 +8210,16 @@ } }, "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", "optional": true }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7668,9 +8229,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -7688,8 +8249,8 @@ ], "peer": true, "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -7707,10 +8268,14 @@ "punycode": "^2.1.0" } }, - "node_modules/url-template": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } }, "node_modules/util-deprecate": { "version": "1.0.2", @@ -7727,35 +8292,32 @@ } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/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==", - "dev": true, - "peer": true - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -7777,7 +8339,8 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true }, "node_modules/websocket-driver": { "version": "0.7.4", @@ -7804,6 +8367,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -7841,17 +8405,16 @@ } }, "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==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7861,10 +8424,10 @@ } }, "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==", - "optional": true, + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "devOptional": true, "engines": { "node": ">=0.10.0" } diff --git a/functions/package.json b/functions/package.json index dfdcd66..e46a2da 100644 --- a/functions/package.json +++ b/functions/package.json @@ -7,7 +7,7 @@ "serve": "npm run build && firebase emulators:start --only functions", "shell": "npm run build && firebase functions:shell", "start": "npm run shell", - "deploy": "firebase deploy --only functions", + "deploy": "npm run build && firebase deploy --only functions", "logs": "firebase functions:log" }, "engines": { @@ -15,19 +15,20 @@ }, "main": "lib/index.js", "dependencies": { - "axios": "^1.4.0", "firebase-admin": "^11.8.0", - "firebase-functions": "^4.3.1", - "googleapis": "^118.0.0" + "firebase-functions": "^4.3.1" }, "devDependencies": { + "@types/node": "^22.5.5", "@typescript-eslint/eslint-plugin": "^5.12.0", "@typescript-eslint/parser": "^5.12.0", "eslint": "^8.9.0", - "eslint-config-google": "^0.14.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.25.4", + "eslint-plugin-prettier": "^5.2.1", "firebase-functions-test": "^3.1.0", - "typescript": "^4.9.0" + "prettier": "^3.3.3", + "typescript": "^5.6.2" }, "private": true } diff --git a/functions/tsconfig.json b/functions/tsconfig.json index eb16f65..cfc5818 100644 --- a/functions/tsconfig.json +++ b/functions/tsconfig.json @@ -11,8 +11,5 @@ "esModuleInterop": true, }, "compileOnSave": true, - "include": [ - "src" - ], - "files": ["./env.d.ts"], + "include": ["src/**/*"], } From 94159b9bd95c9e586807bfd6fe9873f91f18178d Mon Sep 17 00:00:00 2001 From: mnsinri Date: Mon, 23 Sep 2024 21:19:05 +0900 Subject: [PATCH 2/5] feat: v2 functions --- firebase.json | 2 + functions/.gitignore | 4 +- functions/env.d.ts | 17 -- functions/src/api/baseClient.ts | 52 +++++ functions/src/api/index.ts | 4 + functions/src/api/twitCasting.ts | 137 ++++++++++++ functions/src/api/twitch.ts | 135 ++++++++++++ functions/src/api/youtube.ts | 145 +++++++++++++ functions/src/createMater.ts | 12 ++ functions/src/demo.ts | 73 ------- functions/src/index.ts | 260 +++++++++++------------ functions/src/streamerMaster.format.json | 10 + functions/src/twitCasting.ts | 60 ------ functions/src/twitch.ts | 95 --------- functions/src/types.ts | 22 -- functions/src/utils/defineConfig.ts | 25 +++ functions/src/utils/index.ts | 8 + functions/src/utils/sortStreams.ts | 34 +++ functions/src/youtube.ts | 103 --------- functions/types/config.d.ts | 26 +++ functions/types/index.d.ts | 29 +++ 21 files changed, 751 insertions(+), 502 deletions(-) delete mode 100644 functions/env.d.ts create mode 100644 functions/src/api/baseClient.ts create mode 100644 functions/src/api/index.ts create mode 100644 functions/src/api/twitCasting.ts create mode 100644 functions/src/api/twitch.ts create mode 100644 functions/src/api/youtube.ts create mode 100644 functions/src/createMater.ts delete mode 100644 functions/src/demo.ts create mode 100644 functions/src/streamerMaster.format.json delete mode 100644 functions/src/twitCasting.ts delete mode 100644 functions/src/twitch.ts delete mode 100644 functions/src/types.ts create mode 100644 functions/src/utils/defineConfig.ts create mode 100644 functions/src/utils/index.ts create mode 100644 functions/src/utils/sortStreams.ts delete mode 100644 functions/src/youtube.ts create mode 100644 functions/types/config.d.ts create mode 100644 functions/types/index.d.ts diff --git a/firebase.json b/firebase.json index 951df83..5d98b3c 100644 --- a/firebase.json +++ b/firebase.json @@ -4,6 +4,8 @@ "ignore": [ "**/node_modules/**", "**/src/**", + "**/types/**", + "**/arc/**", ".eslintrc.js", ".gitignore", "tsconfig.dev.json", diff --git a/functions/.gitignore b/functions/.gitignore index 26450e5..cbe70e8 100644 --- a/functions/.gitignore +++ b/functions/.gitignore @@ -8,6 +8,8 @@ typings/ # Node.js dependency directory node_modules/ -.env +.env* .secret.local *.http +*.log +streamerMaster.json \ No newline at end of file diff --git a/functions/env.d.ts b/functions/env.d.ts deleted file mode 100644 index af77aa2..0000000 --- a/functions/env.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -declare module "process" { - global { - namespace NodeJS { - interface ProcessEnv { - YOUTUBE_API: string; - TWITCH_API: string; - TWITCH_CLIENT_ID: string; - TWITCH_CLIENT_SECRET: string; - TWIT_CASTING_TOKEN: string; - YOUTUBE_CHANNELIDS_PATH: string; - TWITCH_CHANNELIDS_PATH: string; - TWIT_CASTING_USERIDS_PATH: string; - DATA_URI: string; - } - } - } -} diff --git a/functions/src/api/baseClient.ts b/functions/src/api/baseClient.ts new file mode 100644 index 0000000..9d416fb --- /dev/null +++ b/functions/src/api/baseClient.ts @@ -0,0 +1,52 @@ +import { DocumentReference, DocumentData } from "firebase-admin/firestore"; +import { Platform, Channel, BaseStream } from "../../types"; + +export abstract class Client { + private token = ""; + + constructor( + protected tokenDoc: DocumentReference, + private platform: Platform, + ) {} + + protected abstract generateToken(): Promise; + abstract getChannels(userIds: string[]): Promise; + abstract getStreams(userIds: string[]): Promise; + + protected async getToken(): Promise { + if (this.token) return this.token; + + const doc = await this.tokenDoc.get(); + this.token = doc.data()?.[this.platform]; + + if (!this.token) this.token = await this.generateToken(); + + return this.token; + } + + protected async setToken(token: string): Promise { + this.token = token; + await this.tokenDoc.update({ [this.platform]: token }); + } + + protected async request( + createRequest: (token: string) => Request, + ): Promise { + const token = await this.getToken(); + + const req = createRequest(token); + const response = await fetch(req); + + if (response.ok) return response.json(); + + if (response.status === 401) { + const newToken = await this.generateToken(); + const secondResponse = await fetch(createRequest(newToken)); + return secondResponse.json(); + } + + throw new Error( + `request failed.\n${response.url}\n${response.status}:${response.statusText}`, + ); + } +} diff --git a/functions/src/api/index.ts b/functions/src/api/index.ts new file mode 100644 index 0000000..d462bf8 --- /dev/null +++ b/functions/src/api/index.ts @@ -0,0 +1,4 @@ +export * from "./baseClient"; +export * from "./youtube"; +export * from "./twitch"; +export * from "./twitCasting"; diff --git a/functions/src/api/twitCasting.ts b/functions/src/api/twitCasting.ts new file mode 100644 index 0000000..8d96e0c --- /dev/null +++ b/functions/src/api/twitCasting.ts @@ -0,0 +1,137 @@ +import { DocumentReference, DocumentData } from "firebase-admin/firestore"; +import { Client } from "./baseClient"; +import { BaseStream, Channel, Config } from "../../types"; +import { calcTTL } from "../utils"; + +export class TwitCastingClient extends Client { + private clientId: string; + private clientCode: string; + private clientSecret: string; + + constructor( + tokenDoc: DocumentReference, + config: Config["twitCasting"], + ) { + super(tokenDoc, "twitCasting"); + this.clientId = config.clientId.value(); + this.clientCode = config.clientCode.value(); + this.clientSecret = config.clientSecret.value(); + } + + // codeの更新がCFからできないので、機能しない + protected override async generateToken(): Promise { + const params = new URLSearchParams({ + code: this.clientCode, + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "authorization_code", + redirect_uri: "https://vspo-stream-schedule.web.app/", + }); + const request = new Request( + "https://apiv2.twitcasting.tv/oauth2/access_token", + { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: params, + }, + ); + + const response = await fetch(request); + + if (!response.ok) + throw new Error( + `generateToken request failed. ${response.status}:${response.statusText}`, + ); + + const { ["access_token"]: token } = await response.json(); + + await this.setToken(token); + return token; + } + + override async getChannels(userIds: string[]): Promise { + if (!userIds.length) return []; + + const token = await this.getToken(); + + const requests = userIds.map((id) => { + const createRequest = (token: string) => { + return new Request(`https://apiv2.twitcasting.tv/users/${id}`, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + Accept: "application/json", + "X-Api-Version": "2.0", + }, + }); + }; + + // return this.request(createRequest); + + return fetch(createRequest(token)); + }); + + const responses = await Promise.all(requests); + + if (responses.some((r) => !r.ok)) return []; + + const bodies = await Promise.all(responses.map((r) => r.json())); + + return bodies.map((v) => ({ + id: v.user.screen_id, + name: v.user.name, + icon: v.user.image, + platform: "twitCasting", + })); + } + + override async getStreams(userIds: string[]): Promise { + if (!userIds.length) return []; + + const token = await this.getToken(); + + const requests = userIds.map((id) => { + const createRequest = (token: string) => { + return new Request( + `https://apiv2.twitcasting.tv/users/${id}/current_live`, + { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + Accept: "application/json", + "X-Api-Version": "2.0", + }, + }, + ); + }; + + // return this.request(createRequest); + + return fetch(createRequest(token)); + }); + + const responses = await Promise.all(requests); + + if (responses.some((r) => !r.ok)) return []; + + const bodies = await Promise.all(responses.map((r) => r.json())); + + return bodies.map((v) => { + const startTime = new Date(v.movie.created * 1000).toISOString(); + + return { + id: v.movie.id, + channelId: v.movie.user_id, + title: v.movie.title, + thumbnail: v.movie.large_thumbnail, + url: v.movie.link, + scheduledStartTime: startTime, + startTime, + platform: "twitCasting", + ttl: calcTTL(startTime, 7), + }; + }); + } +} diff --git a/functions/src/api/twitch.ts b/functions/src/api/twitch.ts new file mode 100644 index 0000000..2b955f9 --- /dev/null +++ b/functions/src/api/twitch.ts @@ -0,0 +1,135 @@ +import { DocumentReference, DocumentData } from "firebase-admin/firestore"; +import { Client } from "./baseClient"; +import { BaseStream, Channel, Config } from "../../types"; +import { calcTTL } from "../utils"; + +export class TwitchClient extends Client { + private clientId: string; + private clientSecret: string; + + constructor( + tokenDoc: DocumentReference, + config: Config["twitch"], + ) { + super(tokenDoc, "twitch"); + this.clientId = config.clientId.value(); + this.clientSecret = config.clientSecret.value(); + } + + setThumbnailSize(url: string) { + return url.replace(/%?{width}/, "320").replace(/%?{height}/, "180"); + } + + protected override async generateToken(): Promise { + const query = new URLSearchParams({ + client_id: this.clientId, + client_secret: this.clientSecret, + grant_type: "client_credentials", + }); + const request = new Request(`https://id.twitch.tv/oauth2/token?${query}`, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }); + + const response = await fetch(request); + + if (!response.ok) + throw new Error( + `generateToken request failed. ${response.status}:${response.statusText}`, + ); + + const { ["access_token"]: token } = await response.json(); + + await this.setToken(token); + return token; + } + + override async getChannels(userIds: string[]): Promise { + if (!userIds.length) return []; + + const createRequest = (token: string) => { + const query = new URLSearchParams(userIds.map((id) => ["id", id])); + return new Request(`https://api.twitch.tv/helix/users?${query}`, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + "Client-Id": this.clientId, + "Content-Type": "application/json", + }, + }); + }; + + const bodies = await this.request(createRequest); + + return bodies.data.map((v: any) => ({ + id: v.id, + name: v.display_name, + icon: v.profile_image_url, + platform: "twitch", + })); + } + + override async getStreams(userIds: string[]): Promise { + if (!userIds.length) return []; + + const createRequest = (token: string) => { + const query = new URLSearchParams([ + ["first", `${userIds.length}`], + ...userIds.map((id) => ["user_id", id]), + ]); + return new Request(`https://api.twitch.tv/helix/streams?${query}`, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + "Client-Id": this.clientId, + "Content-Type": "application/json", + }, + }); + }; + + const body = await this.request(createRequest); + + return body.data.map((v: any) => ({ + id: v.id, + channelId: v.user_id, + title: v.title, + thumbnail: this.setThumbnailSize(v.thumbnail_url), + url: `https://www.twitch.tv/${v.user_login}`, + scheduledStartTime: v.started_at, + startTime: v.started_at, + platform: "twitch", + ttl: calcTTL(v.started_at, 7), + })); + } + + async updateStreamToVideo(stream: T): Promise { + const createRequest = (token: string) => { + const query = new URLSearchParams([ + ["user_id", stream.channelId], + ["type", "archive"], + ["first", "1"], + ]); + return new Request(`https://api.twitch.tv/helix/videos?${query}`, { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + "Client-Id": this.clientId, + "Content-Type": "application/json", + }, + }); + }; + + const result = await this.request(createRequest); + const video = result.data.shift(); + + if (stream.id !== video.stream_id) throw new Error("can not updated."); + + return { + ...stream, + url: video.url, + thumbnail: this.setThumbnailSize(video.thumbnail_url), + }; + } +} diff --git a/functions/src/api/youtube.ts b/functions/src/api/youtube.ts new file mode 100644 index 0000000..b6ee7dc --- /dev/null +++ b/functions/src/api/youtube.ts @@ -0,0 +1,145 @@ +import { DocumentReference, DocumentData } from "firebase-admin/firestore"; +import { Client } from "./baseClient"; +import { Channel, BaseStream } from "../../types"; +import { calcTTL } from "../utils"; + +// TODO: Do not use api key +export class YoutubeClient extends Client { + constructor(tokenDoc: DocumentReference) { + super(tokenDoc, "youtube"); + } + + protected override async generateToken(): Promise { + const doc = await this.tokenDoc.get(); + const token = doc.data()?.["youtube"]; + return token; + } + + override async getChannels(userIds: string[]): Promise { + if (!userIds.length) return []; + + const createRequest = (token: string) => { + const query = new URLSearchParams({ + key: token, + part: ["snippet", "contentDetails"].join(","), + id: userIds.join(","), + }); + return new Request( + `https://www.googleapis.com/youtube/v3/channels?${query}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ); + }; + + const bodies = await this.request(createRequest); + + return bodies.items.map((v: any) => ({ + id: v.id, + name: v.snippet.title, + icon: v.snippet.thumbnails.default.url, + platform: "youtube", + })); + } + + override async getStreams(userIds: string[]): Promise { + if (!userIds.length) return []; + + const _token = await this.getToken(); + + // アップロード済み動画から最新動画10本取得 + const plRequests = userIds.map((id) => { + // ChannelIdの2文字目を'U'にするとそのチャンネルのuploadedPlaylistIdになる + const playlistId = id.replace(/(?<=^.{1})./, "U"); + const query = new URLSearchParams({ + key: _token, + part: "snippet", + playlistId, + maxResults: "10", + }); + + const request = new Request( + `https://www.googleapis.com/youtube/v3/playlistItems?${query}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ); + + return fetch(request); + }); + + const plResponses = await Promise.all(plRequests); + const plResults = await Promise.all( + plResponses.filter((r) => r.ok).map((r) => r.json()), + ); + const uploadedVideosMap = new Map( + plResults.flatMap((v: any) => + v.items.map((item: any) => [ + item.snippet.resourceId.videoId, + { + id: item.snippet.resourceId.videoId, + channelId: item.snippet.channelId, + title: item.snippet.title, + thumbnail: item.snippet.thumbnails.medium.url, + url: `https://www.youtube.com/watch?v=${item.snippet.resourceId.videoId}`, + platform: "youtube", + }, + ]), + ), + ); + + // 動画idからstatus+liveStreamDetailを取得 + const maxVideoResults = 50; + const videoIds = [...uploadedVideosMap.keys()]; + const vRequests = Array.from( + { length: Math.ceil(videoIds.length / maxVideoResults) }, + (_, i) => { + const query = new URLSearchParams([ + ["key", _token], + ...["liveStreamingDetails", "status"].map((v) => ["part", v]), + ...videoIds + .slice(i * maxVideoResults, (i + 1) * maxVideoResults) + .map((v) => ["id", v]), + ]); + + const request = new Request( + `https://www.googleapis.com/youtube/v3/videos?${query}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }, + ); + + return fetch(request); + }, + ); + + const vResponses = await Promise.all(vRequests); + const vResults = await Promise.all( + vResponses.filter((r) => r.ok).map((r) => r.json()), + ); + return vResults.flatMap((j) => + j.items + .filter( + (item: any) => + item.liveStreamingDetails?.activeLiveChatId != null && + item.liveStreamingDetails?.scheduledStartTime != null, + ) + .map((item: any) => ({ + ...uploadedVideosMap.get(item.id), + scheduledStartTime: item.liveStreamingDetails.scheduledStartTime, + startTime: item.liveStreamingDetails.actualStartTime, + endTime: item.liveStreamingDetails.actualEndTime, + ttl: calcTTL(item.liveStreamingDetails.scheduledStartTime, 7), + })), + ); + } +} diff --git a/functions/src/createMater.ts b/functions/src/createMater.ts new file mode 100644 index 0000000..0c84480 --- /dev/null +++ b/functions/src/createMater.ts @@ -0,0 +1,12 @@ +import master from "./streamerMaster.json"; +import { Firestore } from "firebase-admin/firestore"; + +export const createMaster = async (db: Firestore, collectionName: string) => { + const batch = db.batch(); + const masterRef = db.collection(collectionName); + + for (const [key, value] of Object.entries(master)) + batch.set(masterRef.doc(key), value); + + await batch.commit(); +}; diff --git a/functions/src/demo.ts b/functions/src/demo.ts deleted file mode 100644 index eadc5a4..0000000 --- a/functions/src/demo.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as youtube from "./youtube"; -import * as twitch from "./twitch"; -import * as twitCasting from "./twitCasting"; -import * as logger from "firebase-functions/logger"; -import { onRequest } from "firebase-functions/v2/https"; -import { getDatabase } from "firebase-admin/database"; - -const db = getDatabase(); - -export const getVspoYoutube = onRequest( - { secrets: ["YOUTUBE_API"] }, - async (req, res) => { - const YT_CHANNELIDS_PATH = process.env.YOUTUBE_CHANNELIDS_PATH; - const YT_API_KEY = process.env.YOUTUBE_API; - - const ytChSnap = await db.ref(YT_CHANNELIDS_PATH).get(); - if (ytChSnap.exists()) { - const ytStreams = await youtube.getStreams(YT_API_KEY, ytChSnap.val()); - res.send(ytStreams); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] youtube channels dont exist in rtdb" - ); - res.send({}); - } - } -); - -export const getVspoTwitch = onRequest( - { secrets: ["TWITCH_CLIENT_ID", "TWITCH_CLIENT_SECRET"] }, - async (req, res) => { - const TW_CLIENT_ID = process.env.TWITCH_CLIENT_ID; - const TW_CLIENT_SECRET = process.env.TWITCH_CLIENT_SECRET; - const TW_CHANNELIDS_PATH = process.env.TWITCH_CHANNELIDS_PATH; - - const twChSnap = await db.ref(TW_CHANNELIDS_PATH).get(); - if (twChSnap.exists()) { - const twStreams = await twitch.getStreams( - TW_CLIENT_ID, - TW_CLIENT_SECRET, - twChSnap.val() - ); - res.send(twStreams); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] twitch channels dont exist in rtdb" - ); - res.send({}); - } - } -); - -export const getVspoTwitCasting = onRequest( - { secrets: ["TWIT_CASTING_TOKEN"] }, - async (req, res) => { - const TWC_TOKEN = process.env.TWIT_CASTING_TOKEN; - const TWC_USERIDS_PATH = process.env.TWIT_CASTING_USERIDS_PATH; - - const twcUserIdsSnap = await db.ref(TWC_USERIDS_PATH).get(); - if (twcUserIdsSnap.exists()) { - const data = await twitCasting.getStreams( - TWC_TOKEN, - twcUserIdsSnap.val() - ); - res.send(data); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] twit casting userIds dont exist in rtdb" - ); - res.send({}); - } - } -); diff --git a/functions/src/index.ts b/functions/src/index.ts index 8c9a801..97e2115 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -1,145 +1,143 @@ -import * as admin from "firebase-admin"; -import { getDatabase } from "firebase-admin/database"; +import { initializeApp } from "firebase-admin/app"; +import { getFirestore } from "firebase-admin/firestore"; import { onSchedule } from "firebase-functions/v2/scheduler"; -import * as youtube from "./youtube"; -import * as twitch from "./twitch"; -import * as twitCasting from "./twitCasting"; -import * as logger from "firebase-functions/logger"; - -admin.initializeApp(); - -// export * from "./demo"; - -const db = getDatabase(); - -export const updateChannels = onSchedule( +import { Streamer } from "../types"; +import { YoutubeClient, TwitchClient, TwitCastingClient } from "./api"; +import { defineConfig, sortStreams } from "./utils"; + +initializeApp(); +const config = defineConfig(); +const db = getFirestore(); +db.settings({ ignoreUndefinedProperties: true }); + +const getStreamerMaster = async () => { + const youtubeChannelIdMap = new Map(); + const twitchChannelIdMap = new Map(); + const twitCastingChannelIdMap = new Map(); + + const master = await db.collection(config.collection.master.value()).get(); + master.forEach((doc) => { + const { youtube, twitch, twitCasting } = doc.data(); + + if (youtube) youtubeChannelIdMap.set(youtube, doc.id); + if (twitch) twitchChannelIdMap.set(twitch, doc.id); + if (twitCasting) twitCastingChannelIdMap.set(twitCasting, doc.id); + }); + + return { + youtube: youtubeChannelIdMap, + twitch: twitchChannelIdMap, + twitCasting: twitCastingChannelIdMap, + }; +}; + +export const getStreamers = onSchedule( { - schedule: "0 15 * * *", + schedule: "every day 23:55", secrets: [ - "YOUTUBE_API", - "TWITCH_CLIENT_ID", - "TWITCH_CLIENT_SECRET", - "TWIT_CASTING_TOKEN", + ...Object.values(config.twitch), + ...Object.values(config.twitCasting), ], + timeZone: "Asia/Tokyo", + region: "asia-northeast1", }, - async (_) => { - const DATA_URI = process.env.DATA_URI; - - //youtube - const YT_CHANNELIDS_PATH = process.env.YOUTUBE_CHANNELIDS_PATH; - const YT_API_KEY = process.env.YOUTUBE_API; - - const ytChSnap = await db.ref(YT_CHANNELIDS_PATH).get(); - if (ytChSnap.exists()) { - const ytChannels = await youtube.getChannels(YT_API_KEY, ytChSnap.val()); - db.ref(`${DATA_URI}/youtube/channels`).set(ytChannels); - } else { - logger.error( - "[vspo-stream-schedule:updateChannels] youtube channels dont exist in rtdb" - ); - } - - //twitch - const TW_CLIENT_ID = process.env.TWITCH_CLIENT_ID; - const TW_CLIENT_SECRET = process.env.TWITCH_CLIENT_SECRET; - const TW_CHANNELIDS_PATH = process.env.TWITCH_CHANNELIDS_PATH; - - const twChSnap = await db.ref(TW_CHANNELIDS_PATH).get(); - if (twChSnap.exists()) { - const twChannels = await twitch.getChannels( - TW_CLIENT_ID, - TW_CLIENT_SECRET, - twChSnap.val() - ); - db.ref(`${DATA_URI}/twitch/channels`).set(twChannels); - } else { - logger.error( - "[vspo-stream-schedule:updateChannels] twitch channels dont exist in rtdb" - ); - } - - //twit casting - const TWC_TOKEN = process.env.TWIT_CASTING_TOKEN; - const TWC_USERIDS_PATH = process.env.TWIT_CASTING_USERIDS_PATH; - - const twcUserIdsSnap = await db.ref(TWC_USERIDS_PATH).get(); - if (twcUserIdsSnap.exists()) { - const twcChannels = await twitCasting.getChannels( - TWC_TOKEN, - twcUserIdsSnap.val() - ); - db.ref(`${DATA_URI}/twitCasting/channels`).set(twcChannels); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] twit casting userIds dont exist in rtdb" - ); - } - } -); - -export const updateYoutubeStreams = onSchedule( - { - schedule: "0,10,20,30,40,50 * * * *", - secrets: ["YOUTUBE_API"], + async () => { + // init + const master = await getStreamerMaster(); + const tokenDoc = db + .collection(config.collection.secrets.value()) + .doc(config.document.token.value()); + const youtubeClient = new YoutubeClient(tokenDoc); + const twitchClient = new TwitchClient(tokenDoc, config.twitch); + const twitClient = new TwitCastingClient(tokenDoc, config.twitCasting); + + // get channels + const getChannels = [ + youtubeClient.getChannels([...master.youtube.keys()]), + twitchClient.getChannels([...master.twitch.keys()]), + twitClient.getChannels([...master.twitCasting.keys()]), + ]; + const channels = (await Promise.all(getChannels)).flat(); + + const streamers = channels.reduce( + (result, ch) => { + const key = master[ch.platform].get(ch.id); + if (!key) return result; + + result[key] = { ...result[key], [ch.platform]: ch }; + + return result; + }, + {} as Record, + ); + + // create and update db + const batch = db.batch(); + const streamerRef = db.collection(config.collection.streamers.value()); + + for (const [key, data] of Object.entries(streamers)) + batch.set(streamerRef.doc(key), data); + + await batch.commit(); }, - async (_) => { - const DATA_URI = process.env.DATA_URI; - - const YT_CHANNELIDS_PATH = process.env.YOUTUBE_CHANNELIDS_PATH; - const YT_API_KEY = process.env.YOUTUBE_API; - - const ytChSnap = await db.ref(YT_CHANNELIDS_PATH).get(); - if (ytChSnap.exists()) { - const ytStreams = await youtube.getStreams(YT_API_KEY, ytChSnap.val()); - db.ref(`${DATA_URI}/youtube/streams`).set(ytStreams); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] youtube channels dont exist in rtdb" - ); - } - } ); -export const updateTwitchAndTwitCastingStreams = onSchedule( +export const getStreams = onSchedule( { - schedule: "1,11,21,31,41,51 * * * *", - secrets: ["TWITCH_CLIENT_ID", "TWITCH_CLIENT_SECRET", "TWIT_CASTING_TOKEN"], + schedule: "every 10 minutes synchronized", + secrets: [ + ...Object.values(config.twitch), + ...Object.values(config.twitCasting), + ], + timeZone: "Asia/Tokyo", + region: "asia-northeast1", }, - async (_) => { - const DATA_URI = process.env.DATA_URI; - - const TW_CLIENT_ID = process.env.TWITCH_CLIENT_ID; - const TW_CLIENT_SECRET = process.env.TWITCH_CLIENT_SECRET; - const TW_CHANNELIDS_PATH = process.env.TWITCH_CHANNELIDS_PATH; - - const twChSnap = await db.ref(TW_CHANNELIDS_PATH).get(); - if (twChSnap.exists()) { - const twStreams = await twitch.getStreams( - TW_CLIENT_ID, - TW_CLIENT_SECRET, - twChSnap.val() - ); - db.ref(`${DATA_URI}/twitch/streams`).set(twStreams); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] twitch channels dont exist in rtdb" - ); + async () => { + // init + const master = await getStreamerMaster(); + const tokenDoc = db + .collection(config.collection.secrets.value()) + .doc(config.document.token.value()); + const youtubeClient = new YoutubeClient(tokenDoc); + const twitchClient = new TwitchClient(tokenDoc, config.twitch); + const twitClient = new TwitCastingClient(tokenDoc, config.twitCasting); + + // get streams + const getStreams = [ + youtubeClient.getStreams([...master.youtube.keys()]), + twitchClient.getStreams([...master.twitch.keys()]), + twitClient.getStreams([...master.twitCasting.keys()]), + ]; + const streams = (await Promise.all(getStreams)).flat(); + + // create and update db + const batch = db.batch(); + const streamRef = db.collection(config.collection.streams.value()); + const snap = await streamRef.get(); + const { endedStreams, newStreams } = sortStreams(streams, snap.docs); + + const endTime = new Date().toISOString(); + for await (const { id, data } of endedStreams) { + let stream = data; + + // if twitch stream, update stream info + if (data.platform === "twitch") { + try { + stream = await twitchClient.updateStreamToVideo(data); + } catch { + batch.delete(streamRef.doc(id)); + continue; + } + } + + batch.update(streamRef.doc(id), { ...stream, endTime }); } - const TWC_TOKEN = process.env.TWIT_CASTING_TOKEN; - const TWC_USERIDS_PATH = process.env.TWIT_CASTING_USERIDS_PATH; - - const twcUserIdsSnap = await db.ref(TWC_USERIDS_PATH).get(); - if (twcUserIdsSnap.exists()) { - const twcStreams = await twitCasting.getStreams( - TWC_TOKEN, - twcUserIdsSnap.val() - ); - db.ref(`${DATA_URI}/twitCasting/streams`).set(twcStreams); - } else { - logger.error( - "[vspo-stream-schedule:updateStreams] twit casting userIds dont exist in rtdb" - ); + for (const newStream of newStreams) { + const streamerId = master[newStream.platform].get(newStream.channelId); + batch.set(streamRef.doc(), { ...newStream, streamerId }); } - } + + await batch.commit(); + }, ); diff --git a/functions/src/streamerMaster.format.json b/functions/src/streamerMaster.format.json new file mode 100644 index 0000000..1bd05a7 --- /dev/null +++ b/functions/src/streamerMaster.format.json @@ -0,0 +1,10 @@ +{ + "key1": { + "youtube": "value", + "twitch": "value", + "twitCasting": "value" + }, + "key2": { + "youtube": "value" + } +} \ No newline at end of file diff --git a/functions/src/twitCasting.ts b/functions/src/twitCasting.ts deleted file mode 100644 index eb50230..0000000 --- a/functions/src/twitCasting.ts +++ /dev/null @@ -1,60 +0,0 @@ -import axios from "axios"; -import { ChannelInfo, StreamInfo } from "./types"; - -const baseURL = "https://apiv2.twitcasting.tv"; - -const doGetRequestTwitCasting = async (url: string, token: string) => { - try { - const res = await axios.get(url, { - headers: { - Authorization: `Bearer ${token}`, - Accept: "application/json", - "X-Api-Version": "2.0", - }, - }); - - return res.data; - } catch (e) { - return null; - } -}; - -export const getChannels = async (token: string, userIds: string[]) => { - const buildUrl = (userId: string) => `${baseURL}/users/${userId}`; - - const requests = userIds.map((id) => - doGetRequestTwitCasting(buildUrl(id), token) - ); - - const contents: { user: any }[] = (await Promise.all(requests)).filter( - (v) => v - ); - - return contents.map((co) => ({ - id: co.user.id, - name: co.user.name, - thumbnail: co.user.image, - })); -}; - -export const getStreams = async (token: string, userIds: string[]) => { - const buildUrl = (userId: string) => - `${baseURL}/users/${userId}/current_live`; - - const requests = userIds.map((id) => - doGetRequestTwitCasting(buildUrl(id), token) - ); - - const contents: { movie: any }[] = (await Promise.all(requests)).filter( - (v) => v && !v.movie.is_protected - ); - - return contents.map((co) => ({ - channelId: co.movie.user_id, - id: co.movie.id, - title: co.movie.title, - thumbnail: co.movie.large_thumbnail, - url: co.movie.link, - startAt: new Date(co.movie.created * 1000).toISOString(), - })); -}; diff --git a/functions/src/twitch.ts b/functions/src/twitch.ts deleted file mode 100644 index 37bca7f..0000000 --- a/functions/src/twitch.ts +++ /dev/null @@ -1,95 +0,0 @@ -import axios from "axios"; -import { ChannelInfo, StreamInfo } from "./types"; - -const authURL = "https://id.twitch.tv/oauth2/token"; -const baseURL = "https://api.twitch.tv/helix"; - -const doGetRequestTwitch = async ( - url: string, - clientId: string, - clientSecret: string -) => { - try { - // get app access token - // https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#client-credentials-grant-flow - const authRes = await axios.post( - authURL, - { - client_id: clientId, - client_secret: clientSecret, - grant_type: "client_credentials", - }, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - } - } - ); - - const res = await axios.get(url, { - headers: { - Authorization: `Bearer ${authRes.data.access_token}`, - "Client-Id": clientId, - "Content-Type": "application/json", - }, - }); - - return res.data; - } catch (e) { - return { data: [] }; - } -}; - -export const getChannels = async ( - clientId: string, - clientSecret: string, - channelIds: string[] -) => { - const url = `${baseURL}/users?${channelIds - .map((ch) => `login=${ch}`) - .join("&")}`; - - const contents: { data: any[] } = await doGetRequestTwitch( - url, - clientId, - clientSecret - ); - - return contents.data.map( - (v): ChannelInfo => ({ - id: v.id, - name: v.display_name, - thumbnail: v.profile_image_url, - }) - ); -}; - -export const getStreams = async ( - clientId: string, - clientSecret: string, - channelIds: string[] -) => { - const url = `${baseURL}/streams?first=50&${channelIds - .map((ch) => `user_login=${ch}`) - .join("&")}`; - - const contents: { data: any[] } = await doGetRequestTwitch( - url, - clientId, - clientSecret, - ); - - return contents.data.map( - (v): StreamInfo => ({ - id: v.id, - channelId: v.user_id, - title: v.title, - thumbnail: v.thumbnail_url - .replace("{width}", "320") - .replace("{height}", "180"), - url: `https://www.twitch.tv/${v.user_login}`, - startAt: v.started_at, - gameName: v.game_name, - }) - ); -}; diff --git a/functions/src/types.ts b/functions/src/types.ts deleted file mode 100644 index ee9d74e..0000000 --- a/functions/src/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type ChannelInfo = { - id: string; - name: string; - thumbnail: string; - uploads?: string; -}; - -export type VideoInfo = { - channelId: string; - id: string; - title: string; - thumbnail: string; - url: string; - gameName?: string; -}; - -export type LiveInfo = { - id: string; - startAt: string; -}; - -export type StreamInfo = VideoInfo & LiveInfo; diff --git a/functions/src/utils/defineConfig.ts b/functions/src/utils/defineConfig.ts new file mode 100644 index 0000000..fc06a00 --- /dev/null +++ b/functions/src/utils/defineConfig.ts @@ -0,0 +1,25 @@ +import { defineString, defineSecret } from "firebase-functions/params"; +import { Config } from "../../types"; + +export const defineConfig = (): Config => { + const twitch = { + clientId: defineSecret("TWITCH_CLIENT_ID"), + clientSecret: defineSecret("TWITCH_CLIENT_SECRET"), + }; + const twitCasting = { + clientId: defineSecret("TWIT_CASTING_CLIENT_ID"), + clientCode: defineSecret("TWIT_CASTING_CLIENT_CODE"), + clientSecret: defineSecret("TWIT_CASTING_CLIENT_SECRET"), + }; + const collection = { + secrets: defineString("COLLECTION_SECRETS"), + master: defineString("COLLECTION_MASTER"), + streams: defineString("COLLECTION_STREAMS"), + streamers: defineString("COLLECTION_STREAMERS"), + }; + const document = { + token: defineString("DOCUMENT_TOKEN"), + }; + + return { twitch, twitCasting, collection, document }; +}; diff --git a/functions/src/utils/index.ts b/functions/src/utils/index.ts new file mode 100644 index 0000000..80317cc --- /dev/null +++ b/functions/src/utils/index.ts @@ -0,0 +1,8 @@ +export * from "./defineConfig"; +export * from "./sortStreams"; + +export const calcTTL = (from: string, period = 7): Date => { + const date = new Date(from); + date.setDate(date.getDate() + period); + return date; +}; diff --git a/functions/src/utils/sortStreams.ts b/functions/src/utils/sortStreams.ts new file mode 100644 index 0000000..faa22b9 --- /dev/null +++ b/functions/src/utils/sortStreams.ts @@ -0,0 +1,34 @@ +import { QueryDocumentSnapshot, DocumentData } from "firebase-admin/firestore"; +import { BaseStream, Stream } from "../../types"; + +type Returns = { + endedStreams: { id: string; data: Stream }[]; // {document id, document data}[] + newStreams: T[]; +}; + +// TODO: まとも +export const sortStreams = ( + streams: T[], + snaps: QueryDocumentSnapshot[], +): Returns => { + const existingStreams = snaps.map((doc) => ({ + id: doc.id, + data: doc.data() as Stream, + })); + + const endedStreams = existingStreams.filter( + ({ data }) => + !streams.find( + ({ id, platform }) => data.id === id && data.platform === platform, + ), + ); + + const newStreams = streams.filter( + ({ id, platform }) => + !existingStreams.find( + ({ data }) => data.id === id && data.platform === platform, + ), + ); + + return { endedStreams, newStreams }; +}; diff --git a/functions/src/youtube.ts b/functions/src/youtube.ts deleted file mode 100644 index 27ce528..0000000 --- a/functions/src/youtube.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { google, youtube_v3 } from "googleapis"; -import { ChannelInfo, StreamInfo, VideoInfo, LiveInfo } from "./types"; - -export const getChannels = async (apiKey: string, channelIds: string[]) => { - const res = await google.youtube("v3").channels.list({ - key: apiKey, - part: ["snippet", "contentDetails"], - id: channelIds, - }); - - if (res.status < 200 && 300 <= res.status) { - return []; - } - - return ( - res.data.items?.map( - (item: youtube_v3.Schema$Channel): ChannelInfo => ({ - id: item.id ?? "", - name: item.snippet?.title ?? "", - thumbnail: item.snippet?.thumbnails?.default?.url ?? "", - uploads: item.contentDetails?.relatedPlaylists?.uploads, - }) - ) ?? [] - ); -}; - -//ChannelIdの2文字目を'U'にするとそのチャンネルのuploadedPlaylistIdになる -const getPlaylistIds = (channelIds: string[]) => { - return channelIds.map((id) => id.replace(/(?<=^.{1})./, "U")); -}; - -export const getStreams = async ( - apiKey: string, - channelIds: string[], - searchVideoNum: number = 10 -) => { - const playlistIds = getPlaylistIds(channelIds); - - //get uploaded video info - const plRequests = playlistIds.map((id) => - google.youtube("v3").playlistItems.list({ - key: apiKey, - part: ["snippet"], - playlistId: id, - maxResults: searchVideoNum, - }) - ); - const plResponses = await Promise.all(plRequests); - - const uploads = plResponses - .filter((res) => 200 <= res.status && res.status < 300) - .map( - (res) => - res.data.items?.map( - (item): VideoInfo => ({ - channelId: item.snippet?.channelId ?? "", - id: item.snippet?.resourceId?.videoId ?? "", - title: item.snippet?.title ?? "", - thumbnail: item.snippet?.thumbnails?.medium?.url ?? "", - url: `https://www.youtube.com/watch?v=${item.snippet?.resourceId?.videoId}`, - }) - ) ?? [] - ) - .flat(); - - //get streaming info - const maxResults = 50; - const vRequests = Array.from( - { length: Math.ceil(uploads.length / maxResults) }, - (_, i) => - google.youtube("v3").videos.list({ - key: apiKey, - part: ["liveStreamingDetails"], - id: uploads - .slice(i * maxResults, (i + 1) * maxResults) - .map((v) => v.id), - maxResults, - }) - ); - const vResponses = await Promise.all(vRequests); - - const predicate = (vi: youtube_v3.Schema$Video) => - vi.liveStreamingDetails?.activeLiveChatId != null && - vi.liveStreamingDetails?.scheduledStartTime != null; - const convertLiveInfo = (vi: youtube_v3.Schema$Video): LiveInfo => ({ - id: vi.id ?? "", - startAt: vi.liveStreamingDetails?.scheduledStartTime ?? "", - }); - const streamingVideos = vResponses - .filter((res) => 200 <= res.status && res.status < 300) - .map((res) => res.data.items?.filter(predicate).map(convertLiveInfo) ?? []) - .flat(); - - return streamingVideos - .map((liveInfo): StreamInfo | null => { - const videoInfo = uploads.find((vi) => vi.id === liveInfo.id); - - if (videoInfo === undefined) return null; - - return { ...videoInfo, ...liveInfo }; - }) - .filter((st) => st); -}; diff --git a/functions/types/config.d.ts b/functions/types/config.d.ts new file mode 100644 index 0000000..2a1b43b --- /dev/null +++ b/functions/types/config.d.ts @@ -0,0 +1,26 @@ +import { StringParam, SecretParam } from "firebase-functions/lib/params/types"; + +export type Config = { + // youtube: { + // clientId: SecretParam; + // clientSecret: SecretParam; + // }; + twitch: { + clientId: SecretParam; + clientSecret: SecretParam; + }; + twitCasting: { + clientId: SecretParam; + clientCode: SecretParam; + clientSecret: SecretParam; + }; + collection: { + secrets: StringParam; + master: StringParam; + streams: StringParam; + streamers: StringParam; + }; + document: { + token: StringParam; + }; +}; diff --git a/functions/types/index.d.ts b/functions/types/index.d.ts new file mode 100644 index 0000000..cb1b993 --- /dev/null +++ b/functions/types/index.d.ts @@ -0,0 +1,29 @@ +export { Config } from "./config"; + +export type Platform = "youtube" | "twitch" | "twitCasting"; + +export type Channel = { + id: string; + name: string; + icon: string; + platform: Platform; +}; + +export type Streamer = { [k in Platform]: Channel }; + +export type BaseStream = { + id: string; + channelId: string; + platform: Platform; + title: string; + thumbnail: string; + url: string; + scheduledStartTime: string; // date string + startTime?: string; // date string + endTime?: string; // date string + ttl: Date; +}; + +export type Stream = BaseStream & { + streamerId: string; +}; From e4c95119b325a1c677226324f1ffbf6f6d70e7fa Mon Sep 17 00:00:00 2001 From: mnsinri Date: Mon, 14 Oct 2024 21:48:45 +0900 Subject: [PATCH 3/5] feat: v2 UI --- .eslintrc.js | 28 ++ .github/workflows/firebase-hosting-merge.yml | 2 + .../firebase-hosting-pull-request.yml | 2 + .gitignore | 3 +- .vscode/settings.json | 4 + @types/index.d.ts | 18 -- firebase.json | 3 +- package-lock.json | 280 +++++++++++++++--- package.json | 20 +- src/App.tsx | 31 +- src/Firebase.ts | 4 +- src/colors/common.ts | 7 - src/colors/index.ts | 5 - src/components/Background.tsx | 14 - src/components/DateBorder.tsx | 98 ------ src/components/Header.tsx | 70 ----- src/components/MainContainer.tsx | 102 ------- src/components/StreamingTable.tsx | 88 ------ src/components/buttons/BaseButton.tsx | 42 --- src/components/buttons/GithubLinkButton.tsx | 15 - src/components/buttons/ThemeButton.tsx | 34 --- src/components/buttons/index.ts | 3 - src/components/card/ServiceIcon.tsx | 157 ---------- src/components/card/StreamingCard.tsx | 59 ---- src/components/card/ThumbnailBlock.tsx | 182 ------------ src/components/card/index.ts | 1 - .../dropdownMenu/dropdownItem/index.tsx | 30 ++ .../dropdownMenu/dropdownItem/styles.tsx | 32 ++ src/components/dropdownMenu/index.tsx | 108 +++++++ src/components/dropdownMenu/styles.tsx | 38 +++ .../dropdownMenu/toggleButtonItem/index.tsx | 59 ++++ .../dropdownMenu/toggleButtonItem/styles.tsx | 8 + src/components/header/index.tsx | 18 ++ src/components/header/styles.tsx | 51 ++++ src/components/index.ts | 16 +- src/components/mainContainer/index.tsx | 127 ++++++++ src/components/mainContainer/styles.tsx | 33 +++ src/components/marquee/Marquee.tsx | 29 -- src/components/marquee/MarqueeForMobile.tsx | 92 ------ src/components/marquee/MarqueeItem.tsx | 58 ---- src/components/marquee/MarqueeScroll.tsx | 59 ---- src/components/marquee/index.ts | 3 - src/components/marquee/index.tsx | 31 ++ src/components/marquee/styles.tsx | 40 +++ src/components/providers/ConfigProvider.tsx | 57 ---- src/components/providers/ThemeProvider.tsx | 46 --- .../providers/VspoStreamingProvider.tsx | 23 -- .../providers/WindowSizeProvider.tsx | 59 ---- src/components/providers/index.ts | 4 - src/components/settingMenu/MenuItem.tsx | 52 ---- src/components/settingMenu/SettingMenu.tsx | 145 --------- .../settingMenu/ToggleButtonItem.tsx | 56 ---- src/components/settingMenu/index.ts | 4 - src/components/settingMenu/index.tsx | 119 ++++++++ src/components/settingMenu/styles.tsx | 13 + src/components/streamCard/index.tsx | 106 +++++++ src/components/streamCard/styles.tsx | 170 +++++++++++ src/components/streamGrid/index.tsx | 41 +++ src/components/streamGrid/styles.tsx | 28 ++ src/components/streamGridHeader/index.tsx | 58 ++++ src/components/streamGridHeader/styles.tsx | 35 +++ src/components/streamerFilter/index.tsx | 113 +++++++ src/components/streamerFilter/styles.tsx | 94 ++++++ .../index.tsx} | 72 +---- src/components/toggleButton/styles.tsx | 36 +++ src/configs/breakpoints.ts | 82 ++--- src/{ => configs}/colors/blue.ts | 4 +- src/configs/colors/common.ts | 4 + src/{ => configs}/colors/grey.ts | 5 +- .../icon.ts => configs/colors/iconColor.ts} | 4 +- src/configs/colors/index.ts | 5 + src/{ => configs}/colors/pink.ts | 4 +- src/configs/index.ts | 11 +- src/configs/theme/dark.ts | 65 ++++ src/configs/theme/index.ts | 8 + src/configs/theme/light.ts | 65 ++++ src/hooks/index.ts | 10 +- src/hooks/useAnimationFrame.ts | 23 -- src/hooks/useBoolStateCache.ts | 16 - src/hooks/useConfig.ts | 12 - src/hooks/useDB.ts | 93 ------ src/hooks/useHover.ts | 7 +- src/hooks/useInterval.ts | 13 + src/hooks/useShakeAnimation.ts | 23 -- src/hooks/useStreamFilter.ts | 55 ++++ src/hooks/useStreamInfo.ts | 50 ---- src/hooks/useTheme.ts | 12 - src/hooks/useVspoStreams.ts | 12 - src/hooks/useWindowSize.ts | 12 - src/index.css | 16 +- src/index.js | 18 +- src/providers/deviceTypeProvider/context.ts | 6 + src/providers/deviceTypeProvider/index.ts | 2 + src/providers/deviceTypeProvider/provider.tsx | 47 +++ src/providers/deviceTypeProvider/use.ts | 4 + src/providers/index.ts | 4 + src/providers/settingProvider/context.ts | 22 ++ src/providers/settingProvider/index.ts | 2 + src/providers/settingProvider/provider.tsx | 98 ++++++ src/providers/settingProvider/use.ts | 5 + src/providers/themeProvider/index.tsx | 19 ++ src/providers/vspoStreamProvider/context.ts | 9 + src/providers/vspoStreamProvider/index.ts | 2 + src/providers/vspoStreamProvider/provider.tsx | 132 +++++++++ src/providers/vspoStreamProvider/use.ts | 10 + src/reportWebVitals.js | 4 +- src/setupTests.js | 2 +- src/theme/dark.ts | 23 -- src/theme/index.ts | 7 - src/theme/light.ts | 23 -- src/types/configs.ts | 33 --- src/types/frontLogic.ts | 46 --- src/types/frontUI.ts | 59 ---- src/types/index.ts | 4 - src/types/theme.ts | 25 -- src/utils/arrayUtils.ts | 3 + src/utils/dateUtils.ts | 18 ++ src/utils/deviceUtils.ts | 12 + src/utils/index.ts | 13 +- tsconfig.json | 9 +- types/config.ts | 24 ++ types/custom.ts | 9 + types/index.ts | 12 + types/setting.ts | 18 ++ types/stream.ts | 47 +++ types/theme.ts | 63 ++++ 126 files changed, 2544 insertions(+), 2336 deletions(-) create mode 100644 .eslintrc.js delete mode 100644 @types/index.d.ts delete mode 100644 src/colors/common.ts delete mode 100644 src/colors/index.ts delete mode 100644 src/components/Background.tsx delete mode 100644 src/components/DateBorder.tsx delete mode 100644 src/components/Header.tsx delete mode 100644 src/components/MainContainer.tsx delete mode 100644 src/components/StreamingTable.tsx delete mode 100644 src/components/buttons/BaseButton.tsx delete mode 100644 src/components/buttons/GithubLinkButton.tsx delete mode 100644 src/components/buttons/ThemeButton.tsx delete mode 100644 src/components/buttons/index.ts delete mode 100644 src/components/card/ServiceIcon.tsx delete mode 100644 src/components/card/StreamingCard.tsx delete mode 100644 src/components/card/ThumbnailBlock.tsx delete mode 100644 src/components/card/index.ts create mode 100644 src/components/dropdownMenu/dropdownItem/index.tsx create mode 100644 src/components/dropdownMenu/dropdownItem/styles.tsx create mode 100644 src/components/dropdownMenu/index.tsx create mode 100644 src/components/dropdownMenu/styles.tsx create mode 100644 src/components/dropdownMenu/toggleButtonItem/index.tsx create mode 100644 src/components/dropdownMenu/toggleButtonItem/styles.tsx create mode 100644 src/components/header/index.tsx create mode 100644 src/components/header/styles.tsx create mode 100644 src/components/mainContainer/index.tsx create mode 100644 src/components/mainContainer/styles.tsx delete mode 100644 src/components/marquee/Marquee.tsx delete mode 100644 src/components/marquee/MarqueeForMobile.tsx delete mode 100644 src/components/marquee/MarqueeItem.tsx delete mode 100644 src/components/marquee/MarqueeScroll.tsx delete mode 100644 src/components/marquee/index.ts create mode 100644 src/components/marquee/index.tsx create mode 100644 src/components/marquee/styles.tsx delete mode 100644 src/components/providers/ConfigProvider.tsx delete mode 100644 src/components/providers/ThemeProvider.tsx delete mode 100644 src/components/providers/VspoStreamingProvider.tsx delete mode 100644 src/components/providers/WindowSizeProvider.tsx delete mode 100644 src/components/providers/index.ts delete mode 100644 src/components/settingMenu/MenuItem.tsx delete mode 100644 src/components/settingMenu/SettingMenu.tsx delete mode 100644 src/components/settingMenu/ToggleButtonItem.tsx delete mode 100644 src/components/settingMenu/index.ts create mode 100644 src/components/settingMenu/index.tsx create mode 100644 src/components/settingMenu/styles.tsx create mode 100644 src/components/streamCard/index.tsx create mode 100644 src/components/streamCard/styles.tsx create mode 100644 src/components/streamGrid/index.tsx create mode 100644 src/components/streamGrid/styles.tsx create mode 100644 src/components/streamGridHeader/index.tsx create mode 100644 src/components/streamGridHeader/styles.tsx create mode 100644 src/components/streamerFilter/index.tsx create mode 100644 src/components/streamerFilter/styles.tsx rename src/components/{settingMenu/ToggleButton.tsx => toggleButton/index.tsx} (51%) create mode 100644 src/components/toggleButton/styles.tsx rename src/{ => configs}/colors/blue.ts (83%) create mode 100644 src/configs/colors/common.ts rename src/{ => configs}/colors/grey.ts (66%) rename src/{colors/icon.ts => configs/colors/iconColor.ts} (66%) create mode 100644 src/configs/colors/index.ts rename src/{ => configs}/colors/pink.ts (83%) create mode 100644 src/configs/theme/dark.ts create mode 100644 src/configs/theme/index.ts create mode 100644 src/configs/theme/light.ts delete mode 100644 src/hooks/useAnimationFrame.ts delete mode 100644 src/hooks/useBoolStateCache.ts delete mode 100644 src/hooks/useConfig.ts delete mode 100644 src/hooks/useDB.ts create mode 100644 src/hooks/useInterval.ts delete mode 100644 src/hooks/useShakeAnimation.ts create mode 100644 src/hooks/useStreamFilter.ts delete mode 100644 src/hooks/useStreamInfo.ts delete mode 100644 src/hooks/useTheme.ts delete mode 100644 src/hooks/useVspoStreams.ts delete mode 100644 src/hooks/useWindowSize.ts create mode 100644 src/providers/deviceTypeProvider/context.ts create mode 100644 src/providers/deviceTypeProvider/index.ts create mode 100644 src/providers/deviceTypeProvider/provider.tsx create mode 100644 src/providers/deviceTypeProvider/use.ts create mode 100644 src/providers/index.ts create mode 100644 src/providers/settingProvider/context.ts create mode 100644 src/providers/settingProvider/index.ts create mode 100644 src/providers/settingProvider/provider.tsx create mode 100644 src/providers/settingProvider/use.ts create mode 100644 src/providers/themeProvider/index.tsx create mode 100644 src/providers/vspoStreamProvider/context.ts create mode 100644 src/providers/vspoStreamProvider/index.ts create mode 100644 src/providers/vspoStreamProvider/provider.tsx create mode 100644 src/providers/vspoStreamProvider/use.ts delete mode 100644 src/theme/dark.ts delete mode 100644 src/theme/index.ts delete mode 100644 src/theme/light.ts delete mode 100644 src/types/configs.ts delete mode 100644 src/types/frontLogic.ts delete mode 100644 src/types/frontUI.ts delete mode 100644 src/types/index.ts delete mode 100644 src/types/theme.ts create mode 100644 src/utils/arrayUtils.ts create mode 100644 src/utils/dateUtils.ts create mode 100644 src/utils/deviceUtils.ts create mode 100644 types/config.ts create mode 100644 types/custom.ts create mode 100644 types/index.ts create mode 100644 types/setting.ts create mode 100644 types/stream.ts create mode 100644 types/theme.ts diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..31f9ec9 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,28 @@ +module.exports = { + root: true, + env: { + es6: true, + node: true, + }, + extends: [ + "eslint:recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + tsconfigRootDir: __dirname, + project: ["tsconfig.json"], + sourceType: "module", + }, + ignorePatterns: ["/lib/**/*"], + plugins: ["@typescript-eslint", "import"], + rules: { + quotes: ["error", "double"], + "import/no-unresolved": "off", + "no-case-declarations": "off" + }, +}; diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml index b005742..88ff350 100644 --- a/.github/workflows/firebase-hosting-merge.yml +++ b/.github/workflows/firebase-hosting-merge.yml @@ -16,6 +16,8 @@ env: REACT_APP_MESSAGING_SENDER_ID: ${{secrets.REACT_APP_MESSAGING_SENDER_ID}} REACT_APP_APP_ID: ${{secrets.REACT_APP_APP_ID}} REACT_APP_DB_DATA_PATH: ${{secrets.REACT_APP_DB_DATA_PATH}} + REACT_APP_STREAM_COLLECTION_NAME: ${{secrets.REACT_APP_STREAM_COLLECTION_NAME}} + REACT_APP_STREAMER_COLLECTION_NAME: ${{secrets.REACT_APP_STREAMER_COLLECTION_NAME}} CI: false jobs: diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index 961496b..d607c13 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -13,6 +13,8 @@ env: REACT_APP_MESSAGING_SENDER_ID: ${{secrets.REACT_APP_MESSAGING_SENDER_ID}} REACT_APP_APP_ID: ${{secrets.REACT_APP_APP_ID}} REACT_APP_DB_DATA_PATH: ${{secrets.REACT_APP_DB_DATA_PATH}} + REACT_APP_STREAM_COLLECTION_NAME: ${{secrets.REACT_APP_STREAM_COLLECTION_NAME}} + REACT_APP_STREAMER_COLLECTION_NAME: ${{secrets.REACT_APP_STREAMER_COLLECTION_NAME}} CI: false jobs: diff --git a/.gitignore b/.gitignore index a8328a2..4d91862 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,4 @@ npm-debug.log* yarn-debug.log* -yarn-error.log* -*.log \ No newline at end of file +yarn-error.log* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index d99432f..bf223ba 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,11 @@ }, "files.eol": "\n", "cSpell.words": [ + "easings", "Firestore", + "HHMM", + "hoverable", + "Vspo", "vssdb" ] } diff --git a/@types/index.d.ts b/@types/index.d.ts deleted file mode 100644 index f4b70a8..0000000 --- a/@types/index.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -declare module "*.png"; - -declare module "process" { - global { - namespace NodeJS { - interface ProcessEnv { - REACT_APP_API_KEY: string; - REACT_APP_AUTH_DOMAIN: string; - REACT_APP_DATABASE_URL: string; - REACT_APP_PROJECT_ID: string; - REACT_APP_STORAGE_BUCKET: string; - REACT_APP_MESSAGING_SENDER_ID: string; - REACT_APP_APP_ID: string; - REACT_APP_DB_DATA_PATH: string; - } - } - } -} diff --git a/firebase.json b/firebase.json index 5d98b3c..57facbc 100644 --- a/firebase.json +++ b/firebase.json @@ -21,7 +21,8 @@ "ignore": [ "firebase.json", "**/.*", - "**/node_modules/**" + "**/node_modules/**", + "**/functions/**" ] }, "emulators": { diff --git a/package-lock.json b/package-lock.json index 917cb39..5fb1ec3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,29 +1,37 @@ { "name": "vspo-stream-schedule", - "version": "1.0.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vspo-stream-schedule", - "version": "1.0.0", + "version": "2.0.0", "dependencies": { "@react-spring/web": "^9.7.2", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^13.5.0", "firebase": "^9.22.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.9.0", - "react-merge-refs": "^2.0.2", "react-scripts": "5.0.1", + "react-transition-group": "^4.4.5", + "styled-components": "^5.3.10", "web-vitals": "^2.1.4" }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@types/react-transition-group": "^4.4.11", "@types/styled-components": "^5.1.26", - "styled-components": "^5.3.10", + "@typescript-eslint/eslint-plugin": "^5.12.0", + "@typescript-eslint/parser": "^5.12.0", + "eslint": "^8.9.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-prettier": "^5.2.1", + "prettier": "^3.3.3", "user-agent-data-types": "^0.3.1" } }, @@ -38,7 +46,8 @@ "node_modules/@adobe/css-tools": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.1.tgz", - "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==" + "integrity": "sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg==", + "dev": true }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", @@ -2262,7 +2271,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", - "dev": true, "dependencies": { "@emotion/memoize": "^0.8.1" } @@ -2270,20 +2278,17 @@ "node_modules/@emotion/memoize": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "dev": true + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/stylis": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", - "dev": true + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" }, "node_modules/@emotion/unitless": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", - "dev": true + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", @@ -3297,6 +3302,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "dev": true, "dependencies": { "jest-get-type": "^29.4.3" }, @@ -3308,6 +3314,7 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -3822,6 +3829,18 @@ "node": ">= 8" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "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", @@ -4314,6 +4333,7 @@ "version": "9.3.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz", "integrity": "sha512-Dffe68pGwI6WlLRYR2I0piIkyole9cSBH5jGQKCGMRpHW5RHCqAUaqc2Kv0tUyd4dU4DLPKhJIjyKOnjv4tuUw==", + "dev": true, "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", @@ -4333,6 +4353,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "peer": true, "dependencies": { "color-convert": "^2.0.1" @@ -4348,6 +4369,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "peer": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -4364,6 +4386,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "peer": true, "dependencies": { "color-name": "~1.1.4" @@ -4376,12 +4399,14 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "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==", + "dev": true, "peer": true, "engines": { "node": ">=8" @@ -4391,6 +4416,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -4403,6 +4429,7 @@ "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==", + "dev": true, "dependencies": { "@adobe/css-tools": "^4.0.1", "@babel/runtime": "^7.9.2", @@ -4424,6 +4451,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4438,6 +4466,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4450,6 +4479,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4460,12 +4490,14 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "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==", + "dev": true, "engines": { "node": ">=8" } @@ -4474,6 +4506,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4485,6 +4518,7 @@ "version": "13.4.0", "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^8.5.0", @@ -4502,6 +4536,7 @@ "version": "8.20.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz", "integrity": "sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -4520,6 +4555,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4534,6 +4570,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4549,6 +4586,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4559,12 +4597,14 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "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==", + "dev": true, "engines": { "node": ">=8" } @@ -4573,6 +4613,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4584,6 +4625,7 @@ "version": "13.5.0", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dev": true, "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -4614,7 +4656,8 @@ "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==" + "integrity": "sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==", + "dev": true }, "node_modules/@types/babel__core": { "version": "7.20.1", @@ -4788,6 +4831,7 @@ "version": "29.5.2", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", + "dev": true, "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -4797,6 +4841,7 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, "dependencies": { "@sinclair/typebox": "^0.25.16" }, @@ -4808,6 +4853,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -4823,12 +4869,14 @@ "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==" + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true }, "node_modules/@types/jest/node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -4837,6 +4885,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4851,6 +4900,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -4866,6 +4916,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -4876,12 +4927,14 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "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==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -4890,6 +4943,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "dev": true, "dependencies": { "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", @@ -4905,6 +4959,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -4913,6 +4968,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", @@ -4927,6 +4983,7 @@ "version": "29.4.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } @@ -4935,6 +4992,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "dev": true, "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.5.0", @@ -4949,6 +5007,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.5.0", @@ -4968,6 +5027,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "dev": true, "dependencies": { "@jest/types": "^29.5.0", "@types/node": "*", @@ -4984,6 +5044,7 @@ "version": "29.5.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", @@ -4997,6 +5058,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "engines": { "node": ">=10" }, @@ -5007,12 +5069,14 @@ "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==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "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==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5058,7 +5122,8 @@ "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==" + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true }, "node_modules/@types/q": { "version": "1.5.5", @@ -5079,6 +5144,7 @@ "version": "18.2.8", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.8.tgz", "integrity": "sha512-lTyWUNrd8ntVkqycEEplasWy2OxNlShj3zqS0LuB1ENUGis5HodmhM7DtCoUGbxj3VW/WsGA0DUhpG6XrM7gPA==", + "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5089,6 +5155,16 @@ "version": "18.2.4", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz", "integrity": "sha512-G2mHoTMTL4yoydITgOGwWdWMVd8sNgyEP85xVmMKAPUBwQWm9wBPQUmvbeF4V3WBY1P7mmL4BkjQ0SqUpf1snw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", + "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -5109,7 +5185,8 @@ "node_modules/@types/scheduler": { "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", - "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", + "dev": true }, "node_modules/@types/semver": { "version": "7.5.0", @@ -5170,6 +5247,7 @@ "version": "5.14.6", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz", "integrity": "sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA==", + "dev": true, "dependencies": { "@types/jest": "*" } @@ -6208,7 +6286,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-module-imports": "^7.21.4", @@ -6223,8 +6300,7 @@ "node_modules/babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==", - "dev": true + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" }, "node_modules/babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", @@ -6547,7 +6623,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6991,7 +7066,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "dev": true, "engines": { "node": ">=4" } @@ -7181,7 +7255,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "dev": true, "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", @@ -7222,7 +7295,8 @@ "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==" + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true }, "node_modules/cssdb": { "version": "7.6.0", @@ -7630,7 +7704,8 @@ "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==" + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true }, "node_modules/dom-converter": { "version": "0.2.0", @@ -7640,6 +7715,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -8095,6 +8179,18 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "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", @@ -8296,6 +8392,36 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-react": { "version": "7.32.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", @@ -8834,6 +8960,12 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", @@ -9690,7 +9822,6 @@ "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==", - "dev": true, "dependencies": { "react-is": "^16.7.0" } @@ -9698,8 +9829,7 @@ "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==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/hoopy": { "version": "0.1.4", @@ -10035,6 +10165,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, "engines": { "node": ">=8" } @@ -12858,6 +12989,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, "bin": { "lz-string": "bin/bin.js" } @@ -13004,6 +13136,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, "engines": { "node": ">=4" } @@ -15012,6 +15145,33 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -15432,15 +15592,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, - "node_modules/react-merge-refs": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-2.0.2.tgz", - "integrity": "sha512-V5BGTwGa2r+/t0A/BZMS6L7VPXY0CU8xtAhkT3XUoI1WJJhhtvulvoiZkJ5Jt9YAW23m4xFWmhQ+C5HwjtTFhQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -15521,6 +15672,21 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -15568,6 +15734,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" @@ -16247,8 +16414,7 @@ "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "node_modules/shebang-command": { "version": "2.0.0", @@ -16619,6 +16785,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, "dependencies": { "min-indent": "^1.0.0" }, @@ -16656,7 +16823,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.10.tgz", "integrity": "sha512-3kSzSBN0TiCnGJM04UwO1HklIQQSXW7rCARUk+VyMR7clz8XVlA3jijtf5ypqoDIdNMKx3la4VvaPFR855SFcg==", - "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -16888,6 +17054,22 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tailwindcss": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", @@ -17192,9 +17374,9 @@ } }, "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/tsutils": { "version": "3.21.0", diff --git a/package.json b/package.json index ea82f01..550456a 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,16 @@ { "name": "vspo-stream-schedule", - "version": "1.0.0", + "version": "2.0.0", "private": true, "dependencies": { "@react-spring/web": "^9.7.2", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^13.5.0", "firebase": "^9.22.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^4.9.0", - "react-merge-refs": "^2.0.2", "react-scripts": "5.0.1", + "react-transition-group": "^4.4.5", + "styled-components": "^5.3.10", "web-vitals": "^2.1.4" }, "scripts": { @@ -41,8 +39,18 @@ }, "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "@types/react-transition-group": "^4.4.11", "@types/styled-components": "^5.1.26", - "styled-components": "^5.3.10", + "@typescript-eslint/eslint-plugin": "^5.12.0", + "@typescript-eslint/parser": "^5.12.0", + "eslint": "^8.9.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-prettier": "^5.2.1", + "prettier": "^3.3.3", "user-agent-data-types": "^0.3.1" } } diff --git a/src/App.tsx b/src/App.tsx index ab54022..f190635 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,25 +1,22 @@ import React from "react"; +import { MainContainer } from "./components"; import { - VspoStreamingProvider, - WindowSizeProvider, + DisplaySizeProvider, + SettingProvider, ThemeProvider, - MainContainer, - ConfigProvider, - Background, -} from "./components"; + VspoStreamProvider, +} from "./providers"; export const App: React.FC = () => { return ( - - - - - - - - - - - + + + + + + + + + ); }; diff --git a/src/Firebase.ts b/src/Firebase.ts index a291e65..b05a722 100644 --- a/src/Firebase.ts +++ b/src/Firebase.ts @@ -1,5 +1,5 @@ import { initializeApp } from "firebase/app"; -import { getDatabase } from "firebase/database"; +import { getFirestore } from "firebase/firestore"; const firebaseConfig = { apiKey: process.env.REACT_APP_API_KEY, @@ -12,4 +12,4 @@ const firebaseConfig = { }; const app = initializeApp(firebaseConfig); -export const database = getDatabase(app); +export const firestore = getFirestore(app); diff --git a/src/colors/common.ts b/src/colors/common.ts deleted file mode 100644 index a59e16d..0000000 --- a/src/colors/common.ts +++ /dev/null @@ -1,7 +0,0 @@ -// https://github.com/mui/material-ui/blob/master/packages/mui-material/src/colors/common.js -const common = { - black: "#000", - white: "#fff", -}; - -export default common; diff --git a/src/colors/index.ts b/src/colors/index.ts deleted file mode 100644 index 3416007..0000000 --- a/src/colors/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { default as common } from "./common"; -export { default as grey } from "./grey"; -export { default as pink } from "./pink"; -export { default as blue } from "./blue"; -export { default as icon } from "./icon"; diff --git a/src/components/Background.tsx b/src/components/Background.tsx deleted file mode 100644 index 61af0b0..0000000 --- a/src/components/Background.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { ChildrenNode } from "../types"; - -const Container = styled.div` - height: 100svh; - width: 100svw; - background-color: ${(p) => p.theme.bg.primary}; - transition: background-color 0.3s ease; -`; - -export const Background = React.memo(({ children, ...props }) => { - return {children}; -}); diff --git a/src/components/DateBorder.tsx b/src/components/DateBorder.tsx deleted file mode 100644 index 60dbfd2..0000000 --- a/src/components/DateBorder.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React, { useEffect } from "react"; -import styled from "styled-components"; -import { animated, useSpring, useSpringRef } from "@react-spring/web"; -import { DateBorderProps, ColorLevel } from "../types"; -import { getFormattedDate, parseToJST } from "../utils"; -import { springConfig } from "../configs"; - -const Container = styled.div` - display: flex; - height: 50px; -`; - -const Icon = styled.div` - display: flex; - gap: 5px; - margin-top: auto; - width: 30px; - aspect-ratio: 1; -`; - -const Bar = styled(animated.div)<{ type: keyof ColorLevel }>` - margin-top: auto; - width: 5px; - background-color: ${(p) => p.theme.vspo[p.type]}; - transition: background-color 0.3s ease; -`; - -const DateLabel = styled.div` - font-size: 48px; - font-family: "Itim", cursive; - letter-spacing: -0.03em; - margin-top: 5px; -`; - -export const DateBorder = React.memo( - ({ dateString, ...props }) => { - const parseToViewDate = (dateString: string) => { - const today = parseToJST(Date.now()); - if (getFormattedDate(today) === dateString) { - return "Today"; - } - - const tomorrow = new Date( - today.getFullYear(), - today.getMonth(), - today.getDate() + 1 - ); - if (getFormattedDate(tomorrow) === dateString) { - return "Tomorrow"; - } - - const yesterday = new Date( - today.getFullYear(), - today.getMonth(), - today.getDate() - 1 - ); - if (getFormattedDate(yesterday) === dateString) { - return "Yesterday"; - } - - return dateString; - }; - - const calcHeight = (max: number) => max - 7 * Math.random(); - - const animApi = useSpringRef(); - const { lh, mh, rh } = useSpring({ - ref: animApi, - from: { - lh: 0, - mh: 0, - rh: 0, - }, - to: { - lh: calcHeight(30), - mh: calcHeight(20), - rh: calcHeight(16), - }, - delay: 200, - config: springConfig, - }); - - useEffect(() => { - animApi.start(); - }, []); - - return ( - - - - - - - {parseToViewDate(dateString)} - - ); - } -); diff --git a/src/components/Header.tsx b/src/components/Header.tsx deleted file mode 100644 index 90a65f2..0000000 --- a/src/components/Header.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { SettingMenu } from "./settingMenu"; -import { breakpoints } from "../configs"; -import logo from "../logo.png"; -import { useWindowSize } from "../hooks"; - -const Container = styled.div` - width: 100%; - height: 80px; - // position: sticky; - // top: 0; - // left: 0; - display: flex; - align-items: center; - - ${breakpoints.mediaQueries.md` - height: 100px; - `} -`; - -const Title = styled.div<{ isPhone: boolean }>` - width: 100%; - display: flex; - justify-content: center; - margin-left: ${(p) => (p.isPhone ? "40px" : "0px")}; - - ${breakpoints.mediaQueries.md` - justify-content: start; - `} -`; - -const Icon = styled.img` - width: 60px; - height: 60px; - - ${breakpoints.mediaQueries.md` - width: 50px; - height: 50px; - `} -`; - -const TitleText = styled.div` - margin-left: 10px; - margin-top: 8px; - font-size: 28px; - font-family: "Itim", cursive; - letter-spacing: -0.05em; -`; - -const Wrapper = styled.div` - width: 40px; - display: flex; - justify-content: flex-end; -`; - -export const Header: React.FC = () => { - const { isPhoneSize } = useWindowSize(); - return ( - - - <Icon src={logo} alt="logo" /> - {!isPhoneSize && <TitleText>Vspo stream schedule</TitleText>} - - - - - - ); -}; diff --git a/src/components/MainContainer.tsx b/src/components/MainContainer.tsx deleted file mode 100644 index afce430..0000000 --- a/src/components/MainContainer.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { breakpoints } from "../configs"; -import { StreamingTable } from "./StreamingTable"; -import { DateBorder } from "./DateBorder"; -import { useConfig, useVspoStreams } from "../hooks"; -import { StreamInfo, StreamList } from "../types"; -import { Header } from "./Header"; - -const Container = styled.div` - margin: 0 auto; - background: rgba(240, 240, 240, 0.03); - box-shadow: 0px 0px 4px 4px rgba(0, 0, 0, 0.2); - color: ${(p) => p.theme.text.primary}; - transition: color 0.3s ease; - - height: 100%; - overflow: scroll; - -ms-overflow-style: none; - scrollbar-width: none; - - &::-webkit-scrollbar { - display: none; - } - - ${breakpoints.mediaQueries.sm` - width: ${breakpoints.values.sm}px; - `} - - ${breakpoints.mediaQueries.md` - width: ${breakpoints.values.md}px; - `} - - ${breakpoints.mediaQueries.lg` - width: ${breakpoints.values.lg}px; - `} - - ${breakpoints.mediaQueries.xl` - width: ${breakpoints.values.xl}px; - `} - - ${breakpoints.mediaQueries.xxl` - width: ${breakpoints.values.xxl}px; - `} -`; - -const InnerContainer = styled.div` - margin: 0 auto; - width: 90%; - - ${breakpoints.mediaQueries.sm` - width: 88%; - `} - - ${breakpoints.mediaQueries.lg` - width: 73%; - `} - - ${breakpoints.mediaQueries.xl` - width: 88%; - `} -`; - -const Spacer = styled.div` - height: 20px; -`; - -const TableContainer = styled.div` - width: 100%; - margin: 0 auto; - padding-bottom: 40px; -`; - -export const MainContainer = React.memo(() => { - const streams = useVspoStreams(); - const { config } = useConfig(); - - const parseToStreamList = (streams: StreamInfo[]): StreamList[] => { - const dateSet = new Set(streams.map((s) => s.scheduledDate)); - const streamList = [...dateSet].map((date) => ({ - date, - streams: streams.filter((s) => s.scheduledDate === date), - })); - - return streamList.sort((a, b) => (a.date > b.date ? 1 : -1)); - }; - - return ( - - -
- {parseToStreamList(streams).map((s) => ( - - - - - - ))} - - - ); -}); diff --git a/src/components/StreamingTable.tsx b/src/components/StreamingTable.tsx deleted file mode 100644 index 223b749..0000000 --- a/src/components/StreamingTable.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { useMemo, useLayoutEffect, useRef, useState } from "react"; -import styled from "styled-components"; -import { StreamingTableProps } from "../types"; -import { StreamingCard } from "./card"; -import { useWindowSize } from "../hooks"; -import { breakpoints } from "../configs"; - -const Container = styled.div<{ height: number }>` - min-height: ${(p) => p.height}px; - display: flex; - flex-direction: row; - justify-content: space-between; -`; - -const FlexBox = styled.div` - display: flex; - flex-direction: column; - gap: 20px; - - ${breakpoints.mediaQueries.md` - gap: 40px; - `} -`; - -export const StreamingTable: React.FC = React.memo( - ({ streams }) => { - const container = useRef(null!); - const { width, isPhoneSize } = useWindowSize(); - const [rowNum, setRowNum] = useState(0); - - const cardSize = useMemo( - () => ({ - width: isPhoneSize ? 160 : 320, - height: isPhoneSize ? 90 : 180, - headerHeight: isPhoneSize ? 30 : 60, - }), - [isPhoneSize] - ); - - useLayoutEffect(() => { - setRowNum( - Math.floor((container.current.offsetWidth ?? 0) / (5 + cardSize.width)) - ); - }, [width]); - - const sortedStreams = streams.sort((a, b) => - a.startAt + a.name > b.startAt + b.name ? 1 : -1 - ); - - const columnNum = Math.ceil(streams.length / rowNum); - const height = - columnNum * cardSize.height + - (columnNum - 1) * 40 + - cardSize.headerHeight; - - const streamsMatrix = [...Array(rowNum)].map((_, i) => - sortedStreams.filter((_, j) => j % rowNum === i) - ); - - return ( - - {streamsMatrix.map((st, i) => ( - - {st.length ? ( - st.map((s) => ( - - )) - ) : ( -
- )} - - ))} - - ); - }, - (prev, next) => - prev.streams.map((s) => s.id).toString() === - next.streams.map((s) => s.id).toString() -); diff --git a/src/components/buttons/BaseButton.tsx b/src/components/buttons/BaseButton.tsx deleted file mode 100644 index c2ad8b9..0000000 --- a/src/components/buttons/BaseButton.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { animated, useSpring } from "@react-spring/web"; -import { IconContext } from "react-icons"; -import { useHover, useWindowSize } from "../../hooks"; -import { BaseButtonProps } from "../../types"; - -const Container = styled.div` - width: 27px; - height: 27px; -`; - -export const BaseButton: React.FC = ({ - onClickHandler, - children, - ...props -}) => { - const { hovered, hoverSpread } = useHover(); - const { isMobile } = useWindowSize(); - - const { transform } = useSpring({ - transform: hovered ? "scale(1.1)" : "scale(1)", - config: { - duration: 100, - }, - }); - - return ( - - - - {children} - - - - ); -}; diff --git a/src/components/buttons/GithubLinkButton.tsx b/src/components/buttons/GithubLinkButton.tsx deleted file mode 100644 index 81b912a..0000000 --- a/src/components/buttons/GithubLinkButton.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from "react"; -import { FaGithub } from "react-icons/fa"; -import { BaseButton } from "./BaseButton"; - -export const GithubLinkButton: React.FC< - React.HTMLAttributes -> = ({ ...props }) => { - const url = "https://github.com/mnsinri/vspo-stream-schedule"; - - return ( - window.open(url)} {...props}> - - - ); -}; diff --git a/src/components/buttons/ThemeButton.tsx b/src/components/buttons/ThemeButton.tsx deleted file mode 100644 index a0039ed..0000000 --- a/src/components/buttons/ThemeButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from "react"; -import styled from "styled-components"; -import { animated, useTransition } from "@react-spring/web"; -import { IoMdSunny, IoMdMoon } from "react-icons/io"; -import { useTheme } from "../../hooks"; -import { BaseButton } from "./BaseButton"; -import { springConfig } from "../../configs"; - -const Wrapper = styled(animated.div)` - position: absolute; -`; - -export const ThemeButton: React.FC> = ({ - ...props -}) => { - const { themeType, setThemeDark } = useTheme(); - - const transitions = useTransition(themeType, { - from: { opacity: 0 }, - enter: { opacity: 1 }, - leave: { opacity: 0 }, - config: springConfig, - }); - - return ( - setThemeDark(true)} {...props}> - {transitions((style, themeType) => ( - - {themeType === "dark" ? : } - - ))} - - ); -}; diff --git a/src/components/buttons/index.ts b/src/components/buttons/index.ts deleted file mode 100644 index b79b4ef..0000000 --- a/src/components/buttons/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./ThemeButton"; -export * from "./BaseButton"; -export * from "./GithubLinkButton"; diff --git a/src/components/card/ServiceIcon.tsx b/src/components/card/ServiceIcon.tsx deleted file mode 100644 index 84d7111..0000000 --- a/src/components/card/ServiceIcon.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useState } from "react"; -import { ServiceIconProps } from "../../types"; -import styled from "styled-components"; -import { animated, easings, useSpring } from "@react-spring/web"; -import { IconContext } from "react-icons"; -import { FaYoutube, FaTwitch } from "react-icons/fa"; -import { TbBroadcast } from "react-icons/tb"; -import { useTheme, useWindowSize } from "../../hooks"; -import { breakpoints } from "../../configs"; -import { icon } from "../../colors"; -import { parseToJST } from "../../utils"; - -const Panel = styled(animated.div)` - display: flex; - background-color: ${(p) => p.theme.bg.secondary}; - transition: background-color 0.3s ease; - height: 18px; - border-radius: 8px; - box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.25); - - ${breakpoints.mediaQueries.md` - height: 28px; - border-radius: 15px; - box-shadow: inset 0px 3px 3px rgba(0, 0, 0, 0.25); - `} -`; - -const InnerContainer = styled(animated.div)` - display: flex; - align-items: center; - height: 14px; - margin: auto; - gap: 2px; - - ${breakpoints.mediaQueries.md` - height: 24px; - gap: 5px; - `} -`; - -const Icon = styled(animated.div)` - height: 100%; - width: 12px; - display: flex; - - ${breakpoints.mediaQueries.md` - width: 20px; - `} -`; - -const StateText = styled(animated.div)` - font-weight: bold; - font-size: 10px; - - ${breakpoints.mediaQueries.md` - font-size: 16px; - `} -`; - -const getStartTime = (timeString: string) => { - const date = parseToJST(Date.parse(timeString)); - return date.getHours() + ":" + date.getMinutes().toString().padStart(2, "0"); -}; - -export const ServiceIcon: React.FC = ({ - service, - startAt, - isExpand, - ...props -}) => { - const { isPhoneSize } = useWindowSize(); - const serviceColor = useMemo(() => { - switch (service) { - case "youtube": - return icon.youtube; - case "twitch": - return icon.twitch; - case "twitCasting": - return icon.twitCasting; - } - }, [service]); - const startDate = useMemo(() => new Date(startAt), [startAt]); - const [isLive, setLive] = useState(false); - const { theme } = useTheme(); - - const checkLive = () => startDate.getTime() < Date.now(); - - const ServiceIcon = useCallback(() => { - switch (service) { - case "youtube": - return ; - case "twitch": - return ; - case "twitCasting": - return ; - } - }, [service]); - - useEffect(() => { - const timerId = setInterval(() => { - if (checkLive()) { - setLive(true); - clearInterval(timerId); - } - }, 30000); - - if (checkLive()) { - setLive(true); - clearInterval(timerId); - } - - return () => clearInterval(timerId); - }, []); - - const baseSpringConfig = { - display: isExpand ? "block" : "none", - width: isExpand ? "85px" : "30px", - color: isLive ? serviceColor : theme.text.primary, - config: { - duration: 150, - easing: easings.easeInOutSine, - }, - }; - - const mobileSpringConfig = { - width: isExpand ? "48px" : "18px", - }; - - const { width, display, color } = useSpring({ - ...baseSpringConfig, - ...(isPhoneSize ? mobileSpringConfig : {}), - }); - const { opacity } = useSpring({ - opacity: isExpand ? 1 : 0, - config: { - duration: 250, - easing: easings.easeInQuart, - }, - }); - - return ( -
- - - - - - - - - {isLive ? "LIVE" : getStartTime(startAt)} - - - -
- ); -}; diff --git a/src/components/card/StreamingCard.tsx b/src/components/card/StreamingCard.tsx deleted file mode 100644 index 26f5a62..0000000 --- a/src/components/card/StreamingCard.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from "react"; -import { StreamingCardProps } from "../../types"; -import { ServiceIcon } from "./ServiceIcon"; -import { ThumbnailBlock } from "./ThumbnailBlock"; -import styled from "styled-components"; -import { useConfig, useHover, useWindowSize } from "../../hooks"; -import { animated } from "@react-spring/web"; -import { breakpoints } from "../../configs"; - -const Container = styled(animated.div)` - width: 160px; - - ${breakpoints.mediaQueries.md` - width: 320px; - `} -`; - -const Card = styled(animated.div)` - position: relative; - - ${breakpoints.mediaQueries.md` - min-height: 180px; - `} -`; - -export const StreamingCard = React.memo( - ({ title, thumbnail, name, icon, service, url, startAt }) => { - const { hovered, hoverSpread } = useHover(); - const { isMobile, isDesktopSize } = useWindowSize(); - const { config } = useConfig(); - - const expand = isMobile || !isDesktopSize; - - return ( - - window.open(url)} - aria-label={title} - {...hoverSpread} - > - - - - - ); - } -); diff --git a/src/components/card/ThumbnailBlock.tsx b/src/components/card/ThumbnailBlock.tsx deleted file mode 100644 index 69b399e..0000000 --- a/src/components/card/ThumbnailBlock.tsx +++ /dev/null @@ -1,182 +0,0 @@ -import React, { useMemo } from "react"; -import styled from "styled-components"; -import { animated, easings, useSpring } from "@react-spring/web"; -import { breakpoints } from "../../configs"; -import { useConfig, useWindowSize } from "../../hooks"; -import { Marquee } from "../marquee"; -import { ThumbnailBlockProps } from "../../types"; - -const Panel = styled(animated.div)` - width: 160px; - height: 90px; - background-color: white; - border-radius: 5px; - filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25)); - position: relative; - background-color: ${(p) => p.theme.bg.secondary}; - transition: background-color 0.3s ease; - - ${breakpoints.mediaQueries.md` - width: 320px; - height: 180px; - border-radius: 10px; - `} -`; - -const Thumbnail = styled(animated.img)` - width: 160px; - height: 90px; - - ${breakpoints.mediaQueries.md` - width: 320px; - height: 180px; - `} -`; - -const Header = styled.div` - width: 100%; - display: flex; - position: absolute; - left: 0; - bottom: 0; - height: 30px; - - ${breakpoints.mediaQueries.md` - height: 60px; - `} -`; - -const Icon = styled(animated.img)` - height: 25px; - aspect-ratio: 1; - margin: auto 0; - margin-left: 3px; - border-radius: 50%; - object-fit: cover; - - ${breakpoints.mediaQueries.md` - height: 50px; - margin-left: 6px; - `} -`; - -const Contents = styled(animated.div)` - margin-left: 3px; - width: 125px; - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - - ${breakpoints.mediaQueries.md` - margin-left: 6px; - width: 250px; - `} -`; - -const MarqueeTitle = styled(Marquee)` - font-family: "Zen Kaku Gothic New", sans-serif; - font-size: 10px; - width: 100%; - margin-top: 2px; - - ${breakpoints.mediaQueries.md` - font-size: 20px; - margin-top: 0; - `} -`; - -const Name = styled.div` - font-family: "Zen Kaku Gothic New", sans-serif; - font-size: 10px; - transform: scale(0.8); - transform-origin: 0 0; - width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - padding: 0 3%; - - ${breakpoints.mediaQueries.md` - font-size: 15px; - transform: scale(1); - `} -`; - -export const ThumbnailBlock: React.FC = ({ - title, - thumbnail, - name, - icon, - isExpand, - hovered, - ...props -}) => { - const { isPhoneSize, isMobile, isDesktopSize } = useWindowSize(); - const { config } = useConfig(); - - const baseSpringConfig = { - height: isExpand ? "240px" : "180px", - borderRadius: isExpand ? "10px 10px 0px 0px" : "10px 10px 10px 10px", - shadow: isExpand - ? "drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.25))" - : "drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25))", - config: { - duration: 150, - easing: easings.easeInOutSine, - }, - }; - - const mobileSpringConfig = { - height: isExpand ? "120px" : "90px", - borderRadius: isExpand ? "5px 5px 0px 0px" : "5px 5px 5px 5px", - shadow: isExpand - ? "drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.25))" - : "drop-shadow(0px 2px 2px rgba(0, 0, 0, 0.25))", - }; - - const { height, borderRadius, shadow } = useSpring({ - ...baseSpringConfig, - ...(isPhoneSize ? mobileSpringConfig : {}), - }); - - const { x } = useSpring({ - x: isExpand ? 1 : 0, - config: { - duration: 500, - easing: easings.easeOutExpo, - }, - }); - - const speed = useMemo(() => { - const speed = isPhoneSize ? 0.45 : 0.9; - if (!isMobile && (!isDesktopSize || config.isExpandAlways) && hovered) - return speed / 2; - return speed; - }, [ - !isMobile && (!isDesktopSize || config.isExpandAlways) && hovered, - isPhoneSize, - ]); - - return ( - - -
- - - - {title} - - {name} - -
-
- ); -}; diff --git a/src/components/card/index.ts b/src/components/card/index.ts deleted file mode 100644 index b383279..0000000 --- a/src/components/card/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./StreamingCard"; diff --git a/src/components/dropdownMenu/dropdownItem/index.tsx b/src/components/dropdownMenu/dropdownItem/index.tsx new file mode 100644 index 0000000..e49109d --- /dev/null +++ b/src/components/dropdownMenu/dropdownItem/index.tsx @@ -0,0 +1,30 @@ +import React, { ReactNode } from "react"; +import { IconContainer, Item, ItemText } from "./styles"; +import { CSSObject } from "styled-components"; + +type Props = { + children?: ReactNode; + contents?: { + icon?: ReactNode; + text?: string; + }; + style?: CSSObject; + onClick?: () => void; +}; + +export const DropdownItem: React.FC = ({ + children, + contents = {}, + style, + onClick, +}) => { + const { icon, text } = contents; + + return ( + + {icon && {icon}} + {text && {text}} + {children} + + ); +}; diff --git a/src/components/dropdownMenu/dropdownItem/styles.tsx b/src/components/dropdownMenu/dropdownItem/styles.tsx new file mode 100644 index 0000000..e4e0240 --- /dev/null +++ b/src/components/dropdownMenu/dropdownItem/styles.tsx @@ -0,0 +1,32 @@ +import styled, { css } from "styled-components"; + +export const Item = styled.li<{ hoverable: boolean }>` + list-style: none; + display: flex; + gap: 5px; + align-items: center; + transition: background-color 0.3s ease; + background-color: ${({ theme }) => theme.dropdown.item.default.bg.normal}; + padding: 7px 14px; + border-radius: 7px; + cursor: pointer; + + ${(p) => + p.hoverable && + css` + &:hover { + background-color: ${({ theme }) => + theme.dropdown.item.default.bg.hover}; + } + `} +`; + +export const IconContainer = styled.div` + display: flex; + justify-content: center; + align-items: center; +`; + +export const ItemText = styled.span` + line-height: 1.2; +`; diff --git a/src/components/dropdownMenu/index.tsx b/src/components/dropdownMenu/index.tsx new file mode 100644 index 0000000..d2d435d --- /dev/null +++ b/src/components/dropdownMenu/index.tsx @@ -0,0 +1,108 @@ +import React, { + FC, + memo, + ReactElement, + ReactNode, + useCallback, + useEffect, + useRef, + useState, +} from "react"; +import { useTransition } from "@react-spring/web"; +import { DropdownContainer, DropdownContainerProps } from "./styles"; + +type Direction = "top" | "right" | "bottom" | "left"; + +type Position = { + x: number; + y: number; +}; + +type EntryConfig = { + from: Direction; + dist: number; +}; + +type Props = { + trigger: ReactElement; + position?: Partial; + entry?: Partial; + children?: ReactNode; +} & DropdownContainerProps; + +const calcPosition = ({ + x = 0, + y = 10, + from = "top", + dist = 10, +}: Position & EntryConfig): Position => { + switch (from) { + case "top": + return { x, y: y - dist }; + case "bottom": + return { x, y: y + dist }; + case "right": + return { x: x + dist, y }; + case "left": + return { x: x - dist, y }; + } +}; + +export const Dropdown: FC = memo( + ({ trigger, width, position = {}, entry = {}, children }) => { + const [isOpen, setOpen] = useState(false); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const refDropdown = useRef(null!); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const refBtn = useRef(null!); + + const { x = 0, y = 30 } = position; + const { from = "top", dist = 10 } = entry; + const initPosition = calcPosition({ x, y, from, dist }); + + const checkClicksOutside = useCallback( + (e: MouseEvent) => { + if (!(e.target instanceof Node)) return; + + const isOutSideMenu = !refDropdown.current?.contains(e.target); + const isOutSideBtn = !refBtn.current?.contains(e.target); + + if (isOutSideMenu && isOutSideBtn) setOpen(false); + }, + [setOpen], + ); + + useEffect(() => { + if (isOpen) document.addEventListener("mousedown", checkClicksOutside); + return () => + document.removeEventListener("mousedown", checkClicksOutside); + }, [isOpen]); + + const config = { duration: 250 }; + const transitions = useTransition(isOpen, { + from: { opacity: 0, ...initPosition, config }, + enter: { opacity: 1, x, y, config }, + leave: { opacity: 0, ...initPosition, config }, + }); + + return ( + <> +
setOpen((o) => !o)}> + {trigger} +
+ {transitions( + (style, isOpen) => + isOpen && ( + + {children} + + ), + )} + + ); + }, +); + +export * from "./dropdownItem"; +export * from "./toggleButtonItem"; +export { Border } from "./styles"; diff --git a/src/components/dropdownMenu/styles.tsx b/src/components/dropdownMenu/styles.tsx new file mode 100644 index 0000000..0137565 --- /dev/null +++ b/src/components/dropdownMenu/styles.tsx @@ -0,0 +1,38 @@ +import styled from "styled-components"; +import { animated } from "@react-spring/web"; + +export const MenuButton = styled.div` + border: 0; + border-radius: 5px; + background-color: ${({ theme }) => theme.dropdown.input.bg.normal}; + transition: 0.3s ease; + color: ${({ theme }) => theme.dropdown.input.icon}; + + &:hover { + background-color: ${({ theme }) => theme.dropdown.input.bg.hover}; + } +`; + +export type DropdownContainerProps = { + width?: number; +}; +export const DropdownContainer = styled(animated.ol)` + box-sizing: border-box; + position: absolute; + width: ${({ width }) => width ?? 250}px; + border: 5px solid ${({ theme }) => theme.dropdown.bg}; + border-radius: 7px; + box-shadow: 0px 3px 6px 2px rgba(0, 0, 0, 0.2); + background-color: ${({ theme }) => theme.dropdown.bg}; + padding: 2px; + color: ${({ theme }) => theme.dropdown.text}; + z-index: 100; +`; + +export const Border = styled.hr` + background-color: ${({ theme }) => theme.dropdown.border}; + height: 1px; + border: none; + margin: 7px 0px; + padding: 0 5px; +`; diff --git a/src/components/dropdownMenu/toggleButtonItem/index.tsx b/src/components/dropdownMenu/toggleButtonItem/index.tsx new file mode 100644 index 0000000..b5ce7a1 --- /dev/null +++ b/src/components/dropdownMenu/toggleButtonItem/index.tsx @@ -0,0 +1,59 @@ +import React, { + ComponentProps, + ReactNode, + useCallback, + useMemo, + useState, +} from "react"; +import { ToggleButton } from "../../toggleButton"; +import { DropdownItem } from "../dropdownItem"; +import { FlexEnd } from "./styles"; + +type Contents = { + icon?: ReactNode; + text?: string; +}; + +type Props = { + contents: Contents | ((isOn: boolean) => Contents); + children?: ReactNode | ((isOn: boolean) => ReactNode); +} & ComponentProps; + +export const ToggleButtonItem: React.FC = ({ + contents: _contents, + children: _children, + onChange: _onChange, + initState = false, + disabled, +}) => { + const [isOn, setOn] = useState(initState); + const { contents, children } = useMemo( + () => ({ + contents: typeof _contents === "function" ? _contents(isOn) : _contents, + children: typeof _children === "function" ? _children(isOn) : _children, + }), + [_contents, isOn], + ); + + const onChange = useCallback( + (isOn: boolean) => { + setOn(isOn); + _onChange(isOn); + }, + [_onChange], + ); + + return ( + + {children} + + + + + ); +}; diff --git a/src/components/dropdownMenu/toggleButtonItem/styles.tsx b/src/components/dropdownMenu/toggleButtonItem/styles.tsx new file mode 100644 index 0000000..4032a7c --- /dev/null +++ b/src/components/dropdownMenu/toggleButtonItem/styles.tsx @@ -0,0 +1,8 @@ +import styled from "styled-components"; + +export const FlexEnd = styled.div` + margin-left: auto; + display: flex; + align-items: center; + justify-content: center; +`; diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx new file mode 100644 index 0000000..d398fc8 --- /dev/null +++ b/src/components/header/index.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import logo from "../../logo.png"; +import { SettingMenu } from "../settingMenu"; +import { Container, Icon, Title, TitleText, DropdownWrapper } from "./styles"; + +export const Header: React.FC = () => { + return ( + + + <Icon src={logo} alt="logo" /> + <TitleText>Vspo stream schedule</TitleText> + + + + + + ); +}; diff --git a/src/components/header/styles.tsx b/src/components/header/styles.tsx new file mode 100644 index 0000000..e919885 --- /dev/null +++ b/src/components/header/styles.tsx @@ -0,0 +1,51 @@ +import { breakpointMediaQueries } from "src/configs"; +import styled from "styled-components"; + +export const Container = styled.div` + width: 100%; + margin: 25px 0; + /* position: sticky; + top: 0; + left: 0; */ + display: flex; + align-items: center; + border-radius: 10px; + z-index: 10; +`; + +export const Title = styled.div` + width: 100%; + display: flex; + justify-content: center; + margin-left: 40px; + + ${breakpointMediaQueries.tablet` + justify-content: start; + margin-left: 0px; + `} +`; + +export const Icon = styled.img` + width: 50px; + height: 50px; +`; + +export const TitleText = styled.div` + margin-left: 10px; + margin-top: 8px; + font-size: 28px; + font-family: "Itim", cursive; + letter-spacing: -0.05em; + color: ${({ theme }) => theme.header.text}; + display: none; + + ${breakpointMediaQueries.tablet` + display: block; + `} +`; + +export const DropdownWrapper = styled.div` + width: 40px; + display: flex; + justify-content: flex-end; +`; diff --git a/src/components/index.ts b/src/components/index.ts index 3504bb0..784bb04 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,9 +1,7 @@ -export * from "./providers"; -export * from "./card"; -export * from "./buttons"; - -export * from "./MainContainer"; -export * from "./StreamingTable"; -export * from "./DateBorder"; -export * from "./Header"; -export * from "./Background"; +export * from "./dropdownMenu"; +export * from "./header"; +export * from "./mainContainer"; +export * from "./marquee"; +export * from "./streamCard"; +export * from "./streamGrid"; +export * from "./toggleButton"; diff --git a/src/components/mainContainer/index.tsx b/src/components/mainContainer/index.tsx new file mode 100644 index 0000000..c78b22e --- /dev/null +++ b/src/components/mainContainer/index.tsx @@ -0,0 +1,127 @@ +import React, { + FC, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { Stream } from "types"; +import { Background, Container, DailyStreamContainer } from "./styles"; +import { Header } from "../header"; +import { StreamGrid } from "../streamGrid"; +import { StreamGridHeader } from "../streamGridHeader"; +import { useDisplaySize, useSetting, useVspoStream } from "src/providers"; +import { toYYYYMMDD } from "src/utils"; + +type DailyStream = { + date: string; + streams: Stream[]; +}; + +const getPixel = (style: CSSStyleDeclaration, key: string): number => { + return Number(style.getPropertyValue(key).replace("px", "")); +}; + +const calcGridProperties = ( + width: number, + cardWidth: number, + { gapRange = [20, 80] } = {}, +): { + column: number; + gap: number; + options?: { + gapRange: [number, number]; + }; +} => { + const [minGap, maxGap] = gapRange; + + const column = Math.floor((width + minGap) / (cardWidth + minGap)); + if (column <= 1) return { column, gap: 0 }; + + const gap = Math.min((width - cardWidth * column) / (column - 1), maxGap); + return { column, gap }; +}; + +export const MainContainer: FC = () => { + const [gridProperties, setGridProperties] = useState<{ + column: number; + gap: number; + }>({ column: 0, gap: 0 }); + + const displaySize = useDisplaySize(); + const { isDisplayHistory } = useSetting(); + + const streams = useVspoStream(); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const containerRef = useRef(null!); + useEffect(() => { + const [cardWidth, gapRange] = displaySize.mobile + ? [160, [10, 40]] + : [320, [20, 80]]; + + const resize = () => { + const style = window.getComputedStyle(containerRef.current); + const width = getPixel(style, "width"); + setGridProperties(calcGridProperties(width, cardWidth, { gapRange })); + }; + resize(); + + window.addEventListener("resize", resize); + return () => window.removeEventListener("resize", resize); + }, [displaySize.mobile]); + + const calcStreamGridMinHeight = useCallback( + (streamNum: number) => { + const [cardHeight, expandSize, gap] = displaySize.mobile + ? [90, 30, 20] + : [180, 60, 40]; + const row = Math.ceil(streamNum / gridProperties.column); + + return row * (cardHeight + gap) - gap + expandSize; + }, + [gridProperties.column, displaySize.mobile], + ); + + const dailyStreams: DailyStream[] = useMemo(() => { + const now = Date.now(); + const isEndedStream = (s: Stream) => s.endAt && s.endAt.getTime() <= now; + + const dailyStreamObj = streams.reduce( + (result: Record, stream) => { + if (!isDisplayHistory.state && isEndedStream(stream)) return result; + + const dateStr = toYYYYMMDD(stream.startAt); + + if (result[dateStr]) result[dateStr].push(stream); + else result[dateStr] = [stream]; + + return result; + }, + {}, + ); + + return Object.entries(dailyStreamObj) + .sort((a, b) => (a[0] > b[0] ? 1 : -1)) + .map(([date, streams]) => ({ date, streams })); + }, [streams, isDisplayHistory.state]); + + return ( + + +
+ {dailyStreams.map(({ date, streams }) => ( + + + + + ))} + + + ); +}; diff --git a/src/components/mainContainer/styles.tsx b/src/components/mainContainer/styles.tsx new file mode 100644 index 0000000..82acbc8 --- /dev/null +++ b/src/components/mainContainer/styles.tsx @@ -0,0 +1,33 @@ +import { breakpointMediaQueries } from "src/configs"; +import styled from "styled-components"; + +export const Background = styled.div` + width: 100vw; + height: 100vh; + background-color: ${({ theme }) => theme.bg}; + transition: background-color 0.3s ease; +`; + +export const Container = styled.div` + width: 90%; + height: 100%; + margin: 0 auto; + padding: 0 5%; + background: rgba(240, 240, 240, 0.03); + box-shadow: 0px 0px 4px 4px rgba(0, 0, 0, 0.2); + overflow: scroll; + scrollbar-width: none; + display: flex; + flex-direction: column; + transition: width 0.3s ease-in-out; + + ${breakpointMediaQueries.desktop` + width: 85%; + `} +`; + +export const DailyStreamContainer = styled.div` + &:last-child { + padding-bottom: 30px; + } +`; diff --git a/src/components/marquee/Marquee.tsx b/src/components/marquee/Marquee.tsx deleted file mode 100644 index 3f0ad51..0000000 --- a/src/components/marquee/Marquee.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React, { ReactNode } from "react"; -import { useWindowSize } from "../../hooks"; -import { MarqueeForMobile } from "./MarqueeForMobile"; -import { MarqueeScroll } from "./MarqueeScroll"; - -type Props = { - children: ReactNode; - isAnimate?: boolean; - speed?: number; -}; - -export const Marquee: React.FC = ({ - children, - isAnimate = false, - speed = 0.05, - ...props -}) => { - const { isMobile } = useWindowSize(); - - return isMobile ? ( - - {children} - - ) : ( - - {children} - - ); -}; diff --git a/src/components/marquee/MarqueeForMobile.tsx b/src/components/marquee/MarqueeForMobile.tsx deleted file mode 100644 index 10a4b69..0000000 --- a/src/components/marquee/MarqueeForMobile.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { ReactNode, useEffect, useRef, useState } from "react"; -import styled from "styled-components"; -import { animated, useSpring, useSpringRef } from "@react-spring/web"; -import { useWindowSize } from "../../hooks"; - -const Container = styled.div` - width: 100%; - display: flex; - overflow: hidden; - mask-image: linear-gradient( - to right, - transparent, - #fff 5%, - #fff 95%, - transparent - ); -`; - -const Item = styled(animated.div)` - white-space: nowrap; - padding: 0 20% 0 3%; -`; - -type Props = { - children: ReactNode; - isAnimate: boolean; - speed?: number; -}; - -export const MarqueeForMobile: React.FC = ({ - children, - isAnimate, - speed = 0.05, - ...props -}) => { - const { isPhoneSize } = useWindowSize(); - const refParent = useRef(null!); - const refChild = useRef(null!); - const rect = useRef(null!); - const [canMarquee, setCanMarquee] = useState(false); - - const animation = useSpringRef(); - const transform = useSpring({ - ref: animation, - from: { - x: "0%", - }, - }); - - useEffect(() => { - animation.start({ - from: { - x: "0%", - }, - immediate: true, - }); - const parent = refParent.current.getBoundingClientRect(); - const child = refChild.current.getBoundingClientRect(); - rect.current = child; - setCanMarquee(parent.width < child.width); - }, [children, isPhoneSize]); - - useEffect(() => { - animation.start({ - from: { - x: "0%", - }, - ...(canMarquee && isAnimate - ? { - to: { - x: "-100%", - }, - reset: true, - loop: true, - delay: 1500, - config: { - duration: (rect.current.width * 15) / speed, - }, - } - : { immediate: true }), - }); - }, [canMarquee && isAnimate, speed]); - - return ( - - - {children} - - {canMarquee && {children}} - - ); -}; diff --git a/src/components/marquee/MarqueeItem.tsx b/src/components/marquee/MarqueeItem.tsx deleted file mode 100644 index 17b650c..0000000 --- a/src/components/marquee/MarqueeItem.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React, { ReactNode, forwardRef, useLayoutEffect, useRef } from "react"; -import styled from "styled-components"; -import { useAnimationFrame, useWindowSize } from "../../hooks"; -import { mergeRefs } from "react-merge-refs"; - -const Container = styled.div` - white-space: nowrap; - padding: 0 20% 0 3%; -`; - -type Props = { - children: ReactNode; - isAnimate: boolean; - speed?: number; - waitTime?: number; -}; - -export const MarqueeItem = forwardRef( - ({ children, isAnimate, speed = 1, waitTime = 1500 }, forwardedRef) => { - const { isPhoneSize } = useWindowSize(); - const item = useRef(null!); - const rect = useRef(null!); - const start = useRef(null); - const x = useRef(0); - - useLayoutEffect(() => { - rect.current = item.current.getBoundingClientRect(); - }, [children, isPhoneSize]); - - useLayoutEffect(() => { - item.current.style.transform = `translateX(0)`; - x.current = 0; - start.current = null; - }, [isAnimate]); - - useAnimationFrame((timestamp) => { - if (!(isAnimate && item.current && rect.current)) return; - - if (!start.current) start.current = timestamp; - - if (timestamp - start.current < waitTime) return; - - x.current -= speed; - if (x.current < -rect.current.width) { - x.current = 0; - start.current = null; - } - - item.current.style.transform = `translateX(${ - (x.current / rect.current.width) * 100 - }%)`; - }); - - return ( - {children} - ); - } -); diff --git a/src/components/marquee/MarqueeScroll.tsx b/src/components/marquee/MarqueeScroll.tsx deleted file mode 100644 index 0f005fd..0000000 --- a/src/components/marquee/MarqueeScroll.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { ReactNode, useLayoutEffect, useRef, useState } from "react"; -import { MarqueeItem } from "./MarqueeItem"; -import styled from "styled-components"; -import { useWindowSize } from "../../hooks"; - -const Container = styled.div` - width: 100%; - display: flex; - overflow: hidden; - mask-image: linear-gradient( - to right, - transparent, - #fff 5%, - #fff 95%, - transparent - ); -`; - -type Props = { - children: ReactNode; - isAnimate: boolean; - speed?: number; -}; - -export const MarqueeScroll: React.FC = ({ - children, - isAnimate, - speed = 1, - ...props -}) => { - const { isPhoneSize } = useWindowSize(); - const parentRef = useRef(null!); - const childRef = useRef(null!); - const [canMarquee, setCanMarquee] = useState(false); - - useLayoutEffect(() => { - setCanMarquee( - parentRef.current.getBoundingClientRect().width < - childRef.current.getBoundingClientRect().width - ); - }, [children, isPhoneSize]); - - return ( - - - {children} - - {canMarquee && ( - - {children} - - )} - - ); -}; diff --git a/src/components/marquee/index.ts b/src/components/marquee/index.ts deleted file mode 100644 index 198a0d0..0000000 --- a/src/components/marquee/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { MarqueeScroll } from "./MarqueeScroll"; -export { MarqueeForMobile } from "./MarqueeForMobile"; -export { Marquee } from "./Marquee"; diff --git a/src/components/marquee/index.tsx b/src/components/marquee/index.tsx new file mode 100644 index 0000000..b03626c --- /dev/null +++ b/src/components/marquee/index.tsx @@ -0,0 +1,31 @@ +import React, { FC, useLayoutEffect, useRef, useState } from "react"; +import { Container, ContainerProps, MarqueeItem } from "./styles"; + +type Props = { + children: string; +} & ContainerProps; + +export const Marquee: FC = ({ children, ...props }: Props) => { + const parentRef = useRef(null!); + const childRef = useRef(null!); + const [canMarquee, setCanMarquee] = useState(false); + + useLayoutEffect(() => { + // TODO marquee + // setCanMarquee( + // parentRef.current.getBoundingClientRect().width < + // childRef.current.getBoundingClientRect().width, + // ); + }, [children]); + + return ( + + + {children} + + {canMarquee && ( + {children} + )} + + ); +}; diff --git a/src/components/marquee/styles.tsx b/src/components/marquee/styles.tsx new file mode 100644 index 0000000..d70b33e --- /dev/null +++ b/src/components/marquee/styles.tsx @@ -0,0 +1,40 @@ +import styled, { css, CSSProperties, keyframes } from "styled-components"; + +export type ContainerProps = { + fontSize?: CSSProperties["fontSize"]; +}; +export const Container = styled.div` + display: flex; + font-size: ${({ fontSize }) => fontSize ?? "20px"}; + /* overflow: hidden; */ + mask-image: linear-gradient( + to right, + transparent, + #fff 5%, + #fff 95%, + transparent + ); +`; + +type MarqueeItemProps = { + isActive?: boolean; +}; +const marqueeAnimation = keyframes` + from { + transform: translateX(0%); + } + to { + transform: translateX(-100%); + } +`; +export const MarqueeItem = styled.div` + white-space: nowrap; + padding: 0 20% 0 0; + margin-left: 3%; + ${({ isActive }) => + isActive && + css` + animation: ${marqueeAnimation} 10s linear infinite; + animation-delay: 1.5s; + `} +`; diff --git a/src/components/providers/ConfigProvider.tsx b/src/components/providers/ConfigProvider.tsx deleted file mode 100644 index 1b61010..0000000 --- a/src/components/providers/ConfigProvider.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React, { createContext, createRef } from "react"; -import { ChildrenNode } from "../../types"; -import { useBoolStateCache } from "../../hooks"; - -type ConfigSetter = { - setExpandAlways: React.Dispatch>; - setMarquee: React.Dispatch>; -}; - -type Config = { - scrollContainerRef: React.RefObject; - isExpandAlways: boolean; - isMarquee: boolean; -}; - -type ContextType = { - config: Config; - configSetter: ConfigSetter; -}; - -const initState = { - config: { - scrollContainerRef: null!, - isExpandAlways: true, - isMarquee: true, - }, - configSetter: { - setExpandAlways: null!, - setMarquee: null!, - }, -}; - -export const ConfigContext = createContext(initState); -const scrollContainerRef = createRef(); - -export const ConfigProvider: React.FC = ({ children }) => { - const [isExpandAlways, setExpandAlways] = useBoolStateCache( - "isExpandAlways", - initState.config.isExpandAlways - ); - - const [isMarquee, setMarquee] = useBoolStateCache( - "isMarquee", - initState.config.isMarquee - ); - - return ( - - {children} - - ); -}; diff --git a/src/components/providers/ThemeProvider.tsx b/src/components/providers/ThemeProvider.tsx deleted file mode 100644 index 4e5ea84..0000000 --- a/src/components/providers/ThemeProvider.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { createContext, useEffect, useMemo, useState } from "react"; -import { - ChildrenNode, - ColorTheme, - ThemeTypes, - ThemeContextType, -} from "../../types"; -import themes from "../../theme"; -import { ThemeProvider as StyledThemeProvider } from "styled-components"; - -const cacheKey = "themeType"; - -export const ThemeContext = createContext({ - themeType: "light", - theme: {} as ColorTheme, - setThemeDark: (isOn) => {}, -}); - -export const ThemeProvider: React.FC = ({ children }) => { - const [themeType, setTheme] = useState( - (localStorage.getItem(cacheKey) as ThemeTypes) ?? "light" - ); - - useEffect(() => { - localStorage.setItem(cacheKey, themeType); - }, [themeType]); - - const context = useMemo( - () => ({ - themeType, - theme: themes[themeType], - setThemeDark: (isOn) => { - setTheme(isOn ? "dark" : "light"); - }, - }), - [themeType] - ); - - return ( - - - {children} - - - ); -}; diff --git a/src/components/providers/VspoStreamingProvider.tsx b/src/components/providers/VspoStreamingProvider.tsx deleted file mode 100644 index fbfecb8..0000000 --- a/src/components/providers/VspoStreamingProvider.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { createContext } from "react"; -import { ChildrenNode, StreamInfo } from "../../types"; -import { useStreamInfo } from "../../hooks"; - -export const VspoStreamingContext = createContext([]); - -export const VspoStreamingProvider: React.FC = ({ children }) => { - const youtubeStreamsInfo = useStreamInfo("youtube"); - const twitchStreamsInfo = useStreamInfo("twitch"); - const twitCastingStreamsInfo = useStreamInfo("twitCasting"); - - return ( - - {children} - - ); -}; diff --git a/src/components/providers/WindowSizeProvider.tsx b/src/components/providers/WindowSizeProvider.tsx deleted file mode 100644 index 0693ec1..0000000 --- a/src/components/providers/WindowSizeProvider.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/// -import React, { - createContext, - useCallback, - useEffect, - useMemo, - useState, -} from "react"; -import { ChildrenNode, WindowSize, ClientType } from "../../types"; -import { breakpoints } from "../../configs"; - -export const WindowSizeContext = createContext(null!); - -export const WindowSizeProvider: React.FC = ({ children }) => { - const [size, setSize] = useState({ width: 0, height: 0 }); - const [isMobile, setIsMobile] = useState(false); - - const handleWindowSizeChange = () => { - setSize({ - width: window.innerWidth, - height: window.innerHeight, - }); - }; - const checkMoble = useCallback(() => { - if (navigator.userAgentData) { - return navigator.userAgentData.mobile; - } else { - return ( - /android|ipod|ipad|iphone|macintosh/.test( - navigator.userAgent.toLowerCase() - ) && "ontouchend" in document - ); - } - }, []); - - useEffect(() => { - setIsMobile(checkMoble()); - - handleWindowSizeChange(); - window.addEventListener("resize", handleWindowSizeChange); - return () => window.removeEventListener("resize", handleWindowSizeChange); - }, []); - - const clientType = useMemo( - () => ({ - isMobile, - isPhoneSize: size.width < breakpoints.values.md, - isTabletSize: breakpoints.values.md <= size.width, - isDesktopSize: breakpoints.values.lg <= size.width, - }), - [size, isMobile] - ); - - return ( - - {children} - - ); -}; diff --git a/src/components/providers/index.ts b/src/components/providers/index.ts deleted file mode 100644 index 6954a10..0000000 --- a/src/components/providers/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { ThemeProvider } from "./ThemeProvider"; -export { VspoStreamingProvider } from "./VspoStreamingProvider"; -export { WindowSizeProvider } from "./WindowSizeProvider"; -export { ConfigProvider } from "./ConfigProvider"; diff --git a/src/components/settingMenu/MenuItem.tsx b/src/components/settingMenu/MenuItem.tsx deleted file mode 100644 index e6304fe..0000000 --- a/src/components/settingMenu/MenuItem.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { CSSProperties, ReactNode } from "react"; -import styled, { css } from "styled-components"; - -const Item = styled.li<{ hoverable: boolean }>` - cursor: pointer; - list-style: none; - display: flex; - transition: background-color 0.3s ease; - padding: 7px 14px; - border-radius: 7px; - - ${(p) => - p.hoverable && - css` - &:hover { - background-color: ${(p) => p.theme.hoverd.secondary}; - } - `} -`; - -const IconContainer = styled.div` - width: 20px; - display: flex; - align-items: center; - margin-right: 5px; -`; - -const ItemText = styled.span``; - -type Props = { - children?: ReactNode; - icon?: ReactNode; - text?: string; - onClick?: () => void; - style?: CSSProperties; -}; - -export const MenuItem: React.FC = ({ - children, - icon, - text, - onClick, - style, -}) => { - return ( - - {icon && {icon}} - {text && {text}} - {children} - - ); -}; diff --git a/src/components/settingMenu/SettingMenu.tsx b/src/components/settingMenu/SettingMenu.tsx deleted file mode 100644 index b4e5fe8..0000000 --- a/src/components/settingMenu/SettingMenu.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import { MenuItem } from "./MenuItem"; -import { ToggleButtonItem } from "./ToggleButtonItem"; -import { animated, useTransition } from "@react-spring/web"; -import styled from "styled-components"; -import { useConfig, useTheme, useWindowSize } from "../../hooks"; - -import { BiMenu, BiExpandAlt } from "react-icons/bi"; -import { FaGithub } from "react-icons/fa"; -import { TbMoonFilled } from "react-icons/tb"; -import { TbMarquee2 } from "react-icons/tb"; - -const MenuButton = styled(animated.button)` - border: 0; - border-radius: 5px; - background-color: transparent; - transition: 0.3s ease; - color: ${(p) => p.theme.text.primary}; - - &:hover { - background-color: ${(p) => p.theme.hoverd.primary}; - } - - &:active { - background-color: ${(p) => p.theme.hoverd.secondary}; - } -`; - -const Container = styled(animated.ol)<{ right: number }>` - position: absolute; - top: 60px; - right: ${(p) => p.right}px; - z-index: 100; - width: 250px; - border: 5px solid ${(p) => p.theme.bg.secondary}; - border-radius: 7px; - box-shadow: 0px 3px 6px 2px rgba(0, 0, 0, 0.2); - background-color: ${(p) => p.theme.bg.secondary}; - padding: 2px; -`; - -const Border = styled.hr` - border-top: 1px solid ${(p) => p.theme.border.primary}; - margin: 7px 0px; - padding: 0 5px; -`; - -export const SettingMenu: React.FC = () => { - const [isOpen, setOpen] = useState(false); - const refOl = useRef(null!); - const refBtn = useRef(null!); - const { width, isMobile, isDesktopSize } = useWindowSize(); - - const { themeType, setThemeDark } = useTheme(); - const { config, configSetter } = useConfig(); - - const right = useMemo( - () => width - refBtn.current?.getBoundingClientRect().right, - [width] - ); - - const checkIfClickedOutside = useCallback( - (e: MouseEvent) => { - if (!(e.target instanceof Node)) return; - - const isOutSideMenu = refOl.current && !refOl.current.contains(e.target); - const isOutSideBtn = refBtn.current && !refBtn.current.contains(e.target); - - if (isOutSideMenu && isOutSideBtn) setOpen(false); - }, - [setOpen] - ); - - useEffect(() => { - if (config.scrollContainerRef.current !== null) { - config.scrollContainerRef.current.style.overflow = isOpen - ? "hidden" - : "scroll"; - } - - if (isOpen) document.addEventListener("click", checkIfClickedOutside); - return () => document.removeEventListener("click", checkIfClickedOutside); - }, [isOpen]); - - const transitions = useTransition(isOpen, { - from: { opacity: 0, y: -10 }, - enter: { opacity: 1, y: 0 }, - leave: { opacity: 0, y: -10 }, - }); - - return ( - <> - setOpen((o) => !o)}> - - - {transitions( - (style, item) => - item && ( - - } - text="Github" - onClick={() => - window.open("https://github.com/mnsinri/vspo-stream-schedule") - } - /> - - - , - text: "Dark theme", - }} - onChange={(isOn) => setThemeDark(isOn)} - /> - , - text: "Expand always", - }} - onChange={(isOn) => configSetter.setExpandAlways(isOn)} - /> - , - text: "Marquee title", - }} - onChange={(isOn) => configSetter.setMarquee(isOn)} - /> - - ) - )} - - ); -}; diff --git a/src/components/settingMenu/ToggleButtonItem.tsx b/src/components/settingMenu/ToggleButtonItem.tsx deleted file mode 100644 index 1a6069e..0000000 --- a/src/components/settingMenu/ToggleButtonItem.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import React, { ReactNode, useEffect, useMemo, useState } from "react"; -import styled from "styled-components"; -import { ToggleButton } from "./ToggleButton"; -import { MenuItem } from "./MenuItem"; - -const FlexEnd = styled.div` - margin-left: auto; - display: flex; - align-items: center; -`; - -type Contents = { - children?: ReactNode; - icon?: ReactNode; - text?: string; -}; - -type FuncContents = (isOn: boolean) => Contents; - -type Props = { - contents: Contents | FuncContents; - onChange: (isOn: boolean) => void; - initState?: boolean; - disabled?: boolean; -}; - -export const ToggleButtonItem: React.FC = ({ - contents, - onChange, - initState = false, - disabled, -}) => { - const [isOn, setOn] = useState(initState); - const { children, icon, text } = useMemo( - () => (typeof contents === "function" ? contents(isOn) : contents), - [contents, isOn] - ); - - useEffect(() => { - onChange(isOn); - }, [isOn]); - - return ( - - {children} - - setOn(isOn)} - initState={initState} - disabled={disabled} - /> - - - ); -}; diff --git a/src/components/settingMenu/index.ts b/src/components/settingMenu/index.ts deleted file mode 100644 index 501d497..0000000 --- a/src/components/settingMenu/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./SettingMenu"; -export * from "./MenuItem"; -export * from "./ToggleButton"; -export * from "./ToggleButtonItem"; diff --git a/src/components/settingMenu/index.tsx b/src/components/settingMenu/index.tsx new file mode 100644 index 0000000..de79125 --- /dev/null +++ b/src/components/settingMenu/index.tsx @@ -0,0 +1,119 @@ +import React, { FC, memo } from "react"; +import { + Border, + Dropdown, + DropdownItem, + ToggleButtonItem, +} from "../dropdownMenu"; +import { Button } from "./styles"; +import { StreamerFilter } from "../streamerFilter"; +import { useDisplaySize, useSetting, useSettingDispatch } from "src/providers"; +import { BiExpandAlt, BiMenu } from "react-icons/bi"; +import { FaGithub } from "react-icons/fa"; +import { TbMoonFilled, TbMarquee2, TbHistory } from "react-icons/tb"; +import { IoIosArrowBack } from "react-icons/io"; + +export const SettingMenu: FC = memo(() => { + const setting = useSetting(); + const configDispatch = useSettingDispatch(); + const { mobile } = useDisplaySize(); + + const MenuButton = memo(() => ( + + )); + + const GithubLink = memo(() => ( + , + text: "Github", + }} + onClick={() => + window.open("https://github.com/mnsinri/vspo-stream-schedule") + } + /> + )); + + const DropdownHeader = memo(({ text }: { text: string }) => ( + + )); + + const ThemeSetting = memo(() => ( + , + text: "Dark theme", + }} + onChange={(payload) => configDispatch({ target: "isDarkTheme", payload })} + disabled={setting.isDarkTheme.isReadOnly} + /> + )); + + const ExpandSetting = memo(() => ( + , + text: "Expand always", + }} + onChange={(payload) => + configDispatch({ target: "isExpandAlways", payload }) + } + disabled={setting.isExpandAlways.isReadOnly} + /> + )); + + const MarqueeSetting = memo(() => ( + , + text: "Marquee title", + }} + onChange={(payload) => + configDispatch({ target: "isMarqueeTitle", payload }) + } + disabled={setting.isMarqueeTitle.isReadOnly} + /> + )); + + const HistorySetting = memo(() => ( + , + text: "Stream history", + }} + onChange={(payload: boolean) => + configDispatch({ target: "isDisplayHistory", payload }) + } + disabled={setting.isDisplayHistory.isReadOnly} + /> + )); + + return ( + }> + + + + + + + {!mobile && } + , + text: "Streamer", + }} + width={300} + position={{ x: -310, y: -50 }} + entry={{ from: "right" }} + /> + + + + ); +}); diff --git a/src/components/settingMenu/styles.tsx b/src/components/settingMenu/styles.tsx new file mode 100644 index 0000000..4772930 --- /dev/null +++ b/src/components/settingMenu/styles.tsx @@ -0,0 +1,13 @@ +import styled from "styled-components"; + +export const Button = styled.button` + border: 0; + border-radius: 5px; + background-color: ${({ theme }) => theme.dropdown.input.bg.normal}; + transition: 0.3s ease; + color: ${({ theme }) => theme.dropdown.input.icon}; + + &:hover { + background-color: ${({ theme }) => theme.dropdown.input.bg.hover}; + } +`; diff --git a/src/components/streamCard/index.tsx b/src/components/streamCard/index.tsx new file mode 100644 index 0000000..e54468e --- /dev/null +++ b/src/components/streamCard/index.tsx @@ -0,0 +1,106 @@ +import React, { FC, useCallback, useMemo, useState } from "react"; +import { useTheme } from "styled-components"; +import { iconColor } from "src/configs/colors"; +import { FaYoutube, FaTwitch } from "react-icons/fa"; +import { TbBroadcast } from "react-icons/tb"; +import { Stream } from "types"; + +import { useHover, useInterval } from "src/hooks"; +import { + TextContainer, + Details, + StreamerIcon, + Name, + Card, + Thumbnail, + StreamInfo, + PlatformIconContainer, + StateText, +} from "./styles"; +import { Marquee } from "../marquee"; +import { useDisplaySize, useSetting } from "src/providers"; +import { toJstHHMM } from "src/utils"; + +type Props = { + stream: Stream; +}; + +type StreamState = "upcoming" | "live" | "ended"; + +export const StreamCard: FC = ({ stream }) => { + const theme = useTheme(); + const [streamState, setStreamState] = useState("upcoming"); + const { hovered, hoverParams } = useHover(); + + const { isExpandAlways: expand } = useSetting(); + const isExpand = useMemo( + () => hovered || expand.state, + [hovered, expand.state], + ); + + const displaySize = useDisplaySize(); + const titleFontSize = useMemo( + () => (displaySize.mobile ? "11px" : "20px"), + [displaySize.mobile], + ); + + const isLive = streamState === "live"; + const isEnded = streamState === "ended"; + + const checkLiveState = (): StreamState => { + const now = Date.now(); + const { endAt, startAt } = stream; + + if (endAt && endAt.getTime() <= now) return "ended"; + if (startAt.getTime() < now) return "live"; + return "upcoming"; + }; + useInterval(() => { + const state = checkLiveState(); + if (streamState !== state) setStreamState(state); + + return state === "ended"; + }, 3000); + + const scheduledTimeText = useMemo(() => { + if (isLive) return "LIVE"; + return toJstHHMM(stream.startAt); + }, [streamState, stream.startAt.toString()]); + + const PlatformIcon = useCallback(() => { + const color = isLive ? iconColor[stream.platform] : theme.card.text; + switch (stream.platform) { + case "youtube": + return ; + case "twitch": + return ; + case "twitCasting": + return ; + } + }, [streamState, stream.platform, theme.card.text]); + + return ( + window.open(stream.url)} + > + + + + + + + {scheduledTimeText} + + +
+ + + {stream.title} + {stream.streamerName} + +
+
+ ); +}; diff --git a/src/components/streamCard/styles.tsx b/src/components/streamCard/styles.tsx new file mode 100644 index 0000000..a4347b9 --- /dev/null +++ b/src/components/streamCard/styles.tsx @@ -0,0 +1,170 @@ +import { breakpointMediaQueries } from "src/configs"; +import styled, { css, keyframes } from "styled-components"; + +const baseTransition = css` + transition: 0.2s ease; +`; + +type StyleProps = { + isExpand: boolean; +}; + +export const Card = styled.div` + width: 160px; + height: ${({ isExpand }) => (isExpand ? 120 : 90)}px; + border-radius: 5px; + background-color: ${({ theme }) => theme.card.bg}; + color: ${({ theme }) => theme.card.text}; + position: relative; + overflow: hidden; + filter: drop-shadow(0px 4px 4px rgba(0, 0, 0, 0.25)); + ${baseTransition} + + @starting-style { + opacity: 0; + } + + ${({ isExpand }) => breakpointMediaQueries.tablet` + width: 320px; + height: ${isExpand ? 240 : 180}px; + border-radius: 10px; + `} +`; + +export const Thumbnail = styled.img` + width: 100%; + aspect-ratio: 1.777777778; + position: relative; + z-index: 1; +`; + +export const StreamInfo = styled.div` + width: ${({ isExpand }) => (isExpand ? 50 : 20)}px; + height: 20px; + position: absolute; + top: 5px; + right: 5px; + display: flex; + align-items: center; + justify-content: center; + gap: 3px; + background-color: ${({ theme }) => theme.card.bg}; + border-radius: 10px; + box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.25); + z-index: 10; + ${baseTransition} + + ${({ isExpand }) => breakpointMediaQueries.tablet` + width: ${isExpand ? 85 : 30}px; + height: 28px; + gap: 4px; + border-radius: 15px; + box-shadow: inset 0px 3px 3px rgba(0, 0, 0, 0.25); + `} +`; + +export const PlatformIconContainer = styled.div` + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + + ${breakpointMediaQueries.tablet` + font-size: 20px; + `} +`; + +const stateTextFadeIn = keyframes` + 0%, 30% { + opacity: 0; + transform: translateX(10px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +`; +export const StateText = styled.div` + font-weight: bold; + font-size: 11px; + animation: ${stateTextFadeIn} 0.3s ease-in-out; + ${({ isExpand }) => + !isExpand && + css` + display: none; + `}; + + ${breakpointMediaQueries.tablet` + font-size: 16px; + `} +`; + +export const Details = styled.div` + height: 30px; + position: absolute; + left: 0; + bottom: 0; + display: flex; + align-items: center; + gap: 3px; + padding: 0 3px; + + ${breakpointMediaQueries.tablet` + height: 60px; + gap: 6px; + padding: 0 6px; + `} +`; + +export const StreamerIcon = styled.img` + height: 25px; + aspect-ratio: 1; + border-radius: 50%; + object-fit: cover; + z-index: 1; + + ${breakpointMediaQueries.tablet` + height: 50px; + `} +`; + +const textContainerFadeIn = keyframes` + 0%, + 25% { + opacity: 0; + display: none; + transform: translateY(-10px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +`; +export const TextContainer = styled.div` + width: 125px; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + ${({ isExpand }) => + isExpand && + css` + animation: ${textContainerFadeIn} 0.3s ease-in-out; + `}; + + ${breakpointMediaQueries.tablet` + width: 250px; + `} +`; + +export const Name = styled.div` + font-size: 7.5px; + transform-origin: 0 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + ${breakpointMediaQueries.tablet` + font-size: 15px; + `} +`; diff --git a/src/components/streamGrid/index.tsx b/src/components/streamGrid/index.tsx new file mode 100644 index 0000000..cd818b9 --- /dev/null +++ b/src/components/streamGrid/index.tsx @@ -0,0 +1,41 @@ +import React, { FC, useMemo } from "react"; +import { Stream } from "types"; +import { Container, ColumnContainer, DummyCard } from "./styles"; +import { StreamCard } from "../streamCard"; + +type Props = { + streams: Stream[]; + column: number; + gap: number; + minHeight: number; +}; +export const StreamGrid: FC = ({ streams, column, gap, minHeight }) => { + const streamsMatrix = useMemo(() => { + const sortedStreams = [...streams].sort( + (a, b) => + a.startAt.getTime() - b.startAt.getTime() || + a.streamerName.localeCompare(b.streamerName), + ); + + return Array.from({ length: column }, (_, i) => { + const st = sortedStreams.filter((_, j) => j % column === i); + return st.length > 0 ? st : null; + }); + }, [streams, column]); + + return ( + + {streamsMatrix.map((columnStreams, i) => ( + + {columnStreams ? ( + columnStreams.map((stream) => ( + + )) + ) : ( + + )} + + ))} + + ); +}; diff --git a/src/components/streamGrid/styles.tsx b/src/components/streamGrid/styles.tsx new file mode 100644 index 0000000..afc998b --- /dev/null +++ b/src/components/streamGrid/styles.tsx @@ -0,0 +1,28 @@ +import styled from "styled-components"; +import { breakpointMediaQueries } from "src/configs"; + +export const Container = styled.div<{ gap: number; minHeight: number }>` + min-height: ${({ minHeight }) => minHeight}px; + display: flex; + flex-direction: row; + justify-content: center; + gap: ${({ gap }) => gap}px; +`; + +export const ColumnContainer = styled.div` + display: flex; + flex-direction: column; + gap: 20px; + + ${breakpointMediaQueries.tablet` + gap: 40px; + `} +`; + +export const DummyCard = styled.div` + width: 160px; + + ${breakpointMediaQueries.tablet` + width: 320px; + `} +`; diff --git a/src/components/streamGridHeader/index.tsx b/src/components/streamGridHeader/index.tsx new file mode 100644 index 0000000..9e43352 --- /dev/null +++ b/src/components/streamGridHeader/index.tsx @@ -0,0 +1,58 @@ +import React, { FC, useMemo } from "react"; +import { useTheme } from "styled-components"; +import { Bar, Container, DateLabel, Icon } from "./styles"; +import { toYYYYMMDD } from "src/utils"; + +type Props = { + dateString: string; +}; +export const StreamGridHeader: FC = ({ dateString }) => { + const theme = useTheme(); + + const parseToViewDate = (dateString: string) => { + const today = new Date(); + if (toYYYYMMDD(today) === dateString) { + return "Today"; + } + + const tomorrow = new Date( + today.getFullYear(), + today.getMonth(), + today.getDate() + 1, + ); + if (toYYYYMMDD(tomorrow) === dateString) { + return "Tomorrow"; + } + + const yesterday = new Date( + today.getFullYear(), + today.getMonth(), + today.getDate() - 1, + ); + if (toYYYYMMDD(yesterday) === dateString) { + return "Yesterday"; + } + + return dateString; + }; + + const barParams = useMemo(() => { + const calcHeight = (max: number) => max - 7 * Math.random(); + return [ + { height: calcHeight(30), bgColor: theme.cardHeader.icon[0] }, + { height: calcHeight(20), bgColor: theme.cardHeader.icon[1] }, + { height: calcHeight(16), bgColor: theme.cardHeader.icon[2] }, + ]; + }, [theme]); + + return ( + + + {barParams.map((param) => ( + + ))} + + {parseToViewDate(dateString)} + + ); +}; diff --git a/src/components/streamGridHeader/styles.tsx b/src/components/streamGridHeader/styles.tsx new file mode 100644 index 0000000..716e200 --- /dev/null +++ b/src/components/streamGridHeader/styles.tsx @@ -0,0 +1,35 @@ +import styled from "styled-components"; + +export const Container = styled.div` + display: flex; + height: 50px; + margin: 25px 0; +`; + +export const Icon = styled.div` + display: flex; + gap: 5px; + width: 30px; + aspect-ratio: 1; +`; + +export const Bar = styled.div<{ height: number; bgColor: string }>` + width: 5px; + height: ${({ height }) => height}px; + margin-top: auto; + border-radius: 0 5px 0 3px; + background-color: ${({ bgColor }) => bgColor}; + transition: 0.5s ease-out; + + @starting-style { + height: 0px; + } +`; + +export const DateLabel = styled.div` + font-size: 48px; + font-family: "Itim", cursive; + letter-spacing: -0.02em; + margin-top: 5px; + color: ${({ theme }) => theme.cardHeader.text}; +`; diff --git a/src/components/streamerFilter/index.tsx b/src/components/streamerFilter/index.tsx new file mode 100644 index 0000000..0ab9d44 --- /dev/null +++ b/src/components/streamerFilter/index.tsx @@ -0,0 +1,113 @@ +import React, { ComponentProps, FC, memo, useMemo } from "react"; +import { + Button, + Container, + PreviewContainer, + PreviewStreamerIcon, + StreamerIcon, +} from "./styles"; +import { Dropdown, DropdownItem } from "../dropdownMenu"; +import { + useDisplaySize, + useVspoStreamer, + useVspoStreamFilter, +} from "src/providers"; +import { MdFilterListOff } from "react-icons/md"; +import { Streamer } from "types"; + +type DropdownItemContents = { + triggerContents: ComponentProps["contents"]; +}; +type Props = Omit, "trigger"> & + DropdownItemContents; +type StreamerIcons = Streamer["youtube"]["icon"][]; + +const StreamerFilterTrigger = memo( + ({ + triggerContents, + icons, + }: DropdownItemContents & { icons: StreamerIcons }) => { + return ( + + + {icons.slice(0, 7).map((src, n, arr) => ( + + ))} + + + ); + }, +); + +export const StreamerFilter: FC = ({ + triggerContents, + ...dropdownProps +}) => { + const streamers = useVspoStreamer(); + const { filter, streamerIds } = useVspoStreamFilter(); + const { mobile } = useDisplaySize(); + + const filteredStreamerIcons = streamerIds.reduce( + (result: StreamerIcons, streamerId) => { + // TODO: use Map + const streamer = streamers.find(({ id }) => id === streamerId); + return result.concat(streamer?.youtube.icon ?? []); + }, + [], + ); + + const sortedStreamers = useMemo( + () => [...streamers].sort((a, b) => a.id.localeCompare(b.id)), + [streamers], + ); + + const checkClicked = (id: string) => streamerIds.includes(id); + const onClick = (id: string) => { + const type = checkClicked(id) + ? "removeStreamerFilter" + : "addStreamerFilter"; + filter({ type, payload: [id] }); + }; + const onClear = () => { + filter({ type: "clearStreamerFilter" }); + }; + + const Contents = (isMobile: boolean) => ( + <> + + + + + {sortedStreamers.map((s) => ( + onClick(s.id)} + /> + ))} + + + ); + + if (mobile) return Contents(mobile); + + return ( + + } + > + {Contents(mobile)} + + ); +}; diff --git a/src/components/streamerFilter/styles.tsx b/src/components/streamerFilter/styles.tsx new file mode 100644 index 0000000..9a9099f --- /dev/null +++ b/src/components/streamerFilter/styles.tsx @@ -0,0 +1,94 @@ +import { breakpointMediaQueries } from "src/configs"; +import styled from "styled-components"; + +export const Container = styled.div` + display: flex; + gap: 10px; + flex-wrap: wrap; + width: auto; + padding: 7px 14px; + overflow-y: scroll; + scrollbar-width: none; + max-height: 120px; + + ${breakpointMediaQueries.tablet` + width: 254px; + overflow-y: hidden; + max-height: max-content; + `} +`; + +export const Button = styled.button` + margin-left: auto; + + border: 0; + border-radius: 10px; + background-color: ${({ theme }) => theme.dropdown.filter.clear.bg.normal}; + transition: 0.3s ease; + color: ${({ theme }) => theme.dropdown.input.icon}; + display: flex; + justify-content: center; + align-items: center; + padding: 5px; + + &:hover { + background-color: ${({ theme }) => theme.dropdown.filter.clear.bg.hover}; + } + + &:active { + background-color: ${({ theme }) => theme.dropdown.filter.clear.bg.active}; + } +`; + +export const StreamerIcon = styled.img<{ isClicked: boolean }>` + height: 40px; + aspect-ratio: 1; + border-radius: 50%; + object-fit: cover; + cursor: pointer; + transition: 0.1s ease-in-out; + border: 2px outset + ${({ theme, isClicked }) => + isClicked ? theme.cardHeader.icon[0] : "transparent"}; + box-shadow: ${({ isClicked }) => + isClicked + ? "none" + : `-1px -1px 3px rgba(240, 240, 240, 0.5), + 1.5px 1.5px 3px rgba(15, 15, 15, 0.5)`}; + + &:hover { + border-radius: 40%; + } + + ${({ theme, isClicked }) => breakpointMediaQueries.tablet` + height: 50px; + border: 3px outset ${isClicked ? theme.cardHeader.icon[0] : "transparent"}; + box-shadow: ${ + isClicked + ? "none" + : `-2px -2px 6px rgba(240, 240, 240, 0.5), + 3px 3px 6px rgba(15, 15, 15, 0.5)` + }; + `} +`; + +export const PreviewContainer = styled.div` + width: 100%; + height: 22px; + position: relative; + overflow-x: hidden; +`; + +export const PreviewStreamerIcon = styled.img<{ n: number }>` + position: absolute; + top: 0; + right: ${({ n }) => 13 * n}px; + z-index: ${({ n }) => n}; + height: calc(100% - 2px); + aspect-ratio: 1; + border: 1px solid ${({ theme }) => theme.dropdown.bg}; + border-radius: 50%; + object-fit: cover; + transition: 0.2s ease-in-out; + opacity: 1; +`; diff --git a/src/components/settingMenu/ToggleButton.tsx b/src/components/toggleButton/index.tsx similarity index 51% rename from src/components/settingMenu/ToggleButton.tsx rename to src/components/toggleButton/index.tsx index e61b5cd..ddc02c4 100644 --- a/src/components/settingMenu/ToggleButton.tsx +++ b/src/components/toggleButton/index.tsx @@ -1,36 +1,7 @@ -import { animated, useSpring } from "@react-spring/web"; import React, { useCallback, useMemo, useState } from "react"; -import { useShakeAnimation } from "../../hooks/useShakeAnimation"; -import styled from "styled-components"; -import { useTheme } from "../../hooks"; - -const Container = styled(animated.div)<{ width: number; height: number }>` - position: relative; - border-radius: ${(p) => p.height / 2 - 1}px; - height: ${(p) => p.height}px; - width: ${(p) => p.width}px; -`; - -const Feild = styled(animated.input)<{ cursor: string }>` - appearance: none; - outline: none; - border: none; - border-radius: inherit; - margin: 0; - padding: 0; - width: 100%; - height: 100%; - transition: 0.3s ease; - cursor: ${(p) => p.cursor}; -`; - -const Knob = styled(animated.label)` - position: absolute; - pointer-events: none; - background-color: #fafafa; - border-radius: inherit; - z-index: 1; -`; +import { useSpring } from "@react-spring/web"; +import { useTheme } from "styled-components"; +import { Area, Container, Knob } from "./styles"; type Props = { onChange: (on: boolean) => void; @@ -45,26 +16,14 @@ export const ToggleButton: React.FC = ({ initState = false, disabled = false, }) => { - const { theme } = useTheme(); + const theme = useTheme(); const [isOn, setOn] = useState(initState); const rect = useMemo( () => ({ width: size * 1.8, height: size, }), - [size] - ); - - const [shakeStyle, shakeAnim] = useShakeAnimation(5); - - const onClick = useCallback( - (e: React.MouseEvent) => { - if (!disabled) return; - - e.preventDefault(); - shakeAnim(); - }, - [disabled, shakeAnim] + [size], ); const onChangeStatus = useCallback( @@ -77,17 +36,19 @@ export const ToggleButton: React.FC = ({ setOn(e.target.checked); onChange(e.target.checked); }, - [disabled, onChange] + [disabled, onChange], ); - const { x, backgroundColor, opacity } = useSpring({ + const { x, btnBg, knobBg, opacity } = useSpring({ from: { x: initState ? 1 : 0, - backgroundColor: initState ? theme.vspo.primary : "#c7cbdf", + btnBg: theme.dropdown.item.toggle(initState).bg.normal, + knobBg: theme.dropdown.item.toggle(initState).icon, opacity: disabled ? 0.5 : 1, }, x: isOn ? 1 : 0, - backgroundColor: isOn ? theme.vspo.primary : "#c7cbdf", + btnBg: theme.dropdown.item.toggle(isOn).bg.normal, + knobBg: theme.dropdown.item.toggle(isOn).icon, opacity: disabled ? 0.5 : 1, config: { duration: 150, @@ -122,16 +83,15 @@ export const ToggleButton: React.FC = ({ }, [size]); return ( - - - + + ); }; diff --git a/src/components/toggleButton/styles.tsx b/src/components/toggleButton/styles.tsx new file mode 100644 index 0000000..f1f789f --- /dev/null +++ b/src/components/toggleButton/styles.tsx @@ -0,0 +1,36 @@ +import styled from "styled-components"; +import { animated } from "@react-spring/web"; + +export const Container = styled(animated.div)<{ + width: number; + height: number; +}>` + position: relative; + border-radius: ${(p) => p.height / 2 - 1}px; + height: ${(p) => p.height}px; + width: ${(p) => p.width}px; +`; + +export const Area = styled(animated.input)` + appearance: none; + outline: none; + border: none; + border-radius: inherit; + margin: 0; + padding: 0; + width: 100%; + height: 100%; + transition: 0.3s ease; + cursor: pointer; + + &:disabled { + cursor: not-allowed; + } +`; + +export const Knob = styled(animated.label)` + position: absolute; + pointer-events: none; + background-color: #fafafa; + border-radius: inherit; +`; diff --git a/src/configs/breakpoints.ts b/src/configs/breakpoints.ts index d5a9171..b05c217 100644 --- a/src/configs/breakpoints.ts +++ b/src/configs/breakpoints.ts @@ -1,74 +1,30 @@ -import { - CSSObject, - FlattenSimpleInterpolation, - SimpleInterpolation, - css, -} from "styled-components"; -import { - BreakpointMediaQueries, - BreakpointValues, - Breakpoints, -} from "../types"; +import { BreakpointMediaQueries, Breakpoints, BreakpointKey } from "types"; +import { css } from "styled-components"; -const values: BreakpointValues = { - xs: 0, - sm: 576, - md: 768, - lg: 992, - xl: 1200, - xxl: 1600, +export const breakpoints: Breakpoints = { + mobile: 0, + tablet: 768, + desktop: 1024, }; -const mediaQueries: BreakpointMediaQueries = { - xs: ( - xs: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - ${css(xs, ...interpolations)} - `, - sm: ( - sm: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - @media (min-width: ${values.sm}px) { - ${css(sm, ...interpolations)} - } - `, - md: ( - md: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - @media (min-width: ${values.md}px) { - ${css(md, ...interpolations)} - } - `, - lg: ( - lg: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - @media (min-width: ${values.lg}px) { - ${css(lg, ...interpolations)} - } +export const breakpointMediaQueries: BreakpointMediaQueries = { + mobile: (mobile, ...interpolations) => css` + ${css(mobile, ...interpolations)} `, - xl: ( - xl: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - @media (min-width: ${values.xl}px) { - ${css(xl, ...interpolations)} + tablet: (tablet, ...interpolations) => css` + @media (min-width: ${breakpoints.tablet}px) { + ${css(tablet, ...interpolations)} } `, - xxl: ( - xxl: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] - ): FlattenSimpleInterpolation => css` - @media (min-width: ${values.xxl}px) { - ${css(xxl, ...interpolations)} + desktop: (desktop, ...interpolations) => css` + @media (min-width: ${breakpoints.desktop}px) { + ${css(desktop, ...interpolations)} } `, }; -export const breakpoints: Breakpoints = { - values, - mediaQueries, +export const calcBreakPoint = (width: number): BreakpointKey => { + if (breakpoints.desktop <= width) return "desktop"; + if (breakpoints.tablet <= width) return "tablet"; + return "mobile"; }; diff --git a/src/colors/blue.ts b/src/configs/colors/blue.ts similarity index 83% rename from src/colors/blue.ts rename to src/configs/colors/blue.ts index 6d5b191..6227c0b 100644 --- a/src/colors/blue.ts +++ b/src/configs/colors/blue.ts @@ -1,4 +1,4 @@ -const blue = { +export const blue = { 50: "#ebeaf9", 100: "#ccc9ef", 200: "#aaa6e4", @@ -10,5 +10,3 @@ const blue = { 800: "#482aa2", 900: "#3d128b", }; - -export default blue; diff --git a/src/configs/colors/common.ts b/src/configs/colors/common.ts new file mode 100644 index 0000000..a7baf4e --- /dev/null +++ b/src/configs/colors/common.ts @@ -0,0 +1,4 @@ +export const common = { + black: "#000", + white: "#fff", +}; diff --git a/src/colors/grey.ts b/src/configs/colors/grey.ts similarity index 66% rename from src/colors/grey.ts rename to src/configs/colors/grey.ts index 9ae57db..2d66710 100644 --- a/src/colors/grey.ts +++ b/src/configs/colors/grey.ts @@ -1,5 +1,4 @@ -// https://github.com/mui/material-ui/blob/master/packages/mui-material/src/colors/grey.js -const grey = { +export const grey = { 50: "#fafafa", 100: "#f5f5f5", 200: "#eeeeee", @@ -15,5 +14,3 @@ const grey = { A400: "#bdbdbd", A700: "#616161", }; - -export default grey; diff --git a/src/colors/icon.ts b/src/configs/colors/iconColor.ts similarity index 66% rename from src/colors/icon.ts rename to src/configs/colors/iconColor.ts index 30ec18c..1072539 100644 --- a/src/colors/icon.ts +++ b/src/configs/colors/iconColor.ts @@ -1,7 +1,5 @@ -const icon = { +export const iconColor = { youtube: "#ff0000", twitch: "#9146FF", twitCasting: "#0092fa", }; - -export default icon; diff --git a/src/configs/colors/index.ts b/src/configs/colors/index.ts new file mode 100644 index 0000000..683473c --- /dev/null +++ b/src/configs/colors/index.ts @@ -0,0 +1,5 @@ +export { common } from "./common"; +export { grey } from "./grey"; +export { pink } from "./pink"; +export { blue } from "./blue"; +export { iconColor } from "./iconColor"; diff --git a/src/colors/pink.ts b/src/configs/colors/pink.ts similarity index 83% rename from src/colors/pink.ts rename to src/configs/colors/pink.ts index a3639d2..cd489ca 100644 --- a/src/colors/pink.ts +++ b/src/configs/colors/pink.ts @@ -1,4 +1,4 @@ -const pink = { +export const pink = { 50: "#fee6ef", 100: "#fec1d8", 200: "#fe98be", @@ -10,5 +10,3 @@ const pink = { 800: "#c02b6a", 900: "#992462", }; - -export default pink; diff --git a/src/configs/index.ts b/src/configs/index.ts index 93e0723..608e1e0 100644 --- a/src/configs/index.ts +++ b/src/configs/index.ts @@ -1,8 +1,3 @@ -import { easings, SpringConfig } from "@react-spring/web"; - -export { breakpoints } from "./breakpoints"; - -export const springConfig: SpringConfig = { - duration: 500, - easing: easings.easeInOutSine, -}; +export * from "./colors"; +export * from "./theme"; +export * from "./breakpoints"; diff --git a/src/configs/theme/dark.ts b/src/configs/theme/dark.ts new file mode 100644 index 0000000..93ffa5c --- /dev/null +++ b/src/configs/theme/dark.ts @@ -0,0 +1,65 @@ +import { DefaultTheme } from "styled-components"; +import * as colors from "../colors"; + +export const darkTheme: DefaultTheme = { + bg: colors.grey[900], + card: { + text: colors.grey[100], + bg: colors.grey[800], + }, + cardHeader: { + icon: { + 0: colors.pink[300], + 1: colors.blue[400], + 2: colors.pink[300], + }, + text: colors.grey[100], + }, + header: { + text: colors.grey[100], + }, + dropdown: { + input: { + icon: colors.grey[100], + bg: { + normal: "transparent", + hover: colors.grey[700], + }, + }, + border: colors.grey[400], + text: colors.grey[100], + bg: colors.grey[800], + item: { + default: { + bg: { + normal: "transparent", + hover: colors.grey[700], + }, + }, + toggle: (isOn) => + isOn + ? { + icon: colors.grey[200], + bg: { + normal: colors.pink[300], + }, + } + : { + icon: colors.grey[200], + bg: { + normal: colors.pink[300], + }, + }, + }, + filter: { + clear: { + icon: colors.grey[100], + bg: { + normal: "transparent", + hover: colors.grey[600], + active: colors.grey[700], + }, + }, + }, + }, +}; diff --git a/src/configs/theme/index.ts b/src/configs/theme/index.ts new file mode 100644 index 0000000..5bb219a --- /dev/null +++ b/src/configs/theme/index.ts @@ -0,0 +1,8 @@ +import { Themes } from "styled-components"; +import { lightTheme } from "./light"; +import { darkTheme } from "./dark"; + +export const themes: Themes = { + light: lightTheme, + dark: darkTheme, +}; diff --git a/src/configs/theme/light.ts b/src/configs/theme/light.ts new file mode 100644 index 0000000..db865ee --- /dev/null +++ b/src/configs/theme/light.ts @@ -0,0 +1,65 @@ +import { DefaultTheme } from "styled-components"; +import * as colors from "../colors"; + +export const lightTheme: DefaultTheme = { + bg: colors.grey[50], + card: { + text: colors.grey[900], + bg: colors.common.white, + }, + cardHeader: { + icon: { + 0: colors.blue[400], + 1: colors.pink[300], + 2: colors.blue[400], + }, + text: colors.grey[900], + }, + header: { + text: colors.grey[900], + }, + dropdown: { + input: { + icon: colors.grey[900], + bg: { + normal: "transparent", + hover: colors.grey[200], + }, + }, + border: colors.grey[500], + text: colors.grey[900], + bg: colors.grey[100], + item: { + default: { + bg: { + normal: "transparent", + hover: colors.grey[200], + }, + }, + toggle: (isOn) => + isOn + ? { + icon: colors.grey[50], + bg: { + normal: colors.blue[400], + }, + } + : { + icon: colors.grey[50], + bg: { + normal: colors.blue[100], + }, + }, + }, + filter: { + clear: { + icon: colors.grey[900], + bg: { + normal: "transparent", + hover: colors.grey[300], + active: colors.grey[200], + }, + }, + }, + }, +}; diff --git a/src/hooks/index.ts b/src/hooks/index.ts index ce1c1e3..cd64044 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,9 +1,3 @@ -export { useVspoStreams } from "./useVspoStreams"; +export { useInterval } from "./useInterval"; export { useHover } from "./useHover"; -export { useTheme } from "./useTheme"; -export { useDB } from "./useDB"; -export { useStreamInfo } from "./useStreamInfo"; -export { useWindowSize } from "./useWindowSize"; -export { useConfig } from "./useConfig"; -export { useBoolStateCache } from "./useBoolStateCache"; -export { useAnimationFrame } from "./useAnimationFrame"; +export { useStreamFilter } from "./useStreamFilter"; diff --git a/src/hooks/useAnimationFrame.ts b/src/hooks/useAnimationFrame.ts deleted file mode 100644 index 744d26c..0000000 --- a/src/hooks/useAnimationFrame.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useEffect, useRef } from "react"; - -export const useAnimationFrame = ( - callback = (timestamp: DOMHighResTimeStamp) => {} -) => { - const ref = useRef(0); - const rafCallback = useRef<(timestamp: DOMHighResTimeStamp) => void>(null!); - - useEffect(() => { - rafCallback.current = callback; - }, [callback]); - - useEffect(() => { - const loop = (timestamp: DOMHighResTimeStamp) => { - rafCallback.current(timestamp); - ref.current = requestAnimationFrame(loop); - }; - ref.current = requestAnimationFrame(loop); - return () => { - ref.current && cancelAnimationFrame(ref.current); - }; - }, []); -}; diff --git a/src/hooks/useBoolStateCache.ts b/src/hooks/useBoolStateCache.ts deleted file mode 100644 index 3791277..0000000 --- a/src/hooks/useBoolStateCache.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useEffect, useState } from "react"; - -export const useBoolStateCache = (key: string, initState: boolean) => { - const [value, setter] = useState( - (() => { - const item = localStorage.getItem(key); - return item == null ? initState : item.toLocaleLowerCase() === "true"; - })() - ); - - useEffect(() => { - localStorage.setItem(key, value.toString()); - }, [value]); - - return [value, setter] as const; -}; diff --git a/src/hooks/useConfig.ts b/src/hooks/useConfig.ts deleted file mode 100644 index e3c8a7e..0000000 --- a/src/hooks/useConfig.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react"; -import { ConfigContext } from "../components/providers/ConfigProvider"; - -export const useConfig = () => { - const context = useContext(ConfigContext); - - if (typeof context === "undefined") { - throw new Error("useConfig must be within a VspoStreamingProvider"); - } - - return context; -}; diff --git a/src/hooks/useDB.ts b/src/hooks/useDB.ts deleted file mode 100644 index 48d5b22..0000000 --- a/src/hooks/useDB.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { useEffect, useState } from "react"; -import { database } from "../Firebase"; -import { get, onValue, ref } from "firebase/database"; - -const cacheVersion = "vspo"; -const eventName = "OnUnmounted"; -const event = new CustomEvent(eventName); - -export const useDB = ( - path: string, - cacheAvailableTime: number //sec -): T[] => { - const [value, setValue] = useState([]); - const resp = ref(database, path); - cacheAvailableTime *= 1000; - - const doCache = (data: T[]) => { - const newCache = { - data, - timestamp: new Date().toString(), - }; - - caches.open(cacheVersion).then((cache) => { - cache.put(path, new Response(JSON.stringify(newCache))); - }); - - // console.log(`[useDB:${path}] Cached`); - }; - - useEffect(() => { - (async () => { - //check cache - const cache = await caches - .match(path) - .then((r) => r?.text()) - .then((r) => JSON.parse(r ?? "null")); - - //if cache is available - if ( - cache?.timestamp && - Date.now() - Date.parse(cache.timestamp) <= cacheAvailableTime - ) { - // console.log(`[useDB:${path}] Use Cache`); - setValue(cache.data); - } else { - // console.log(`[useDB:${path}] Get from DB`); - const data = await get(resp); - if (data.exists()) { - const val = data.val() as T[]; - doCache(val); - setValue([...val]); - } - } - - //subscribe DB listener after 2 min - const timerId = setTimeout(() => { - const unsubscriber = onValue(resp, (snap) => { - // console.log(`[useDB:${path}] OnValue`); - if (snap.exists()) { - const val = snap.val() as T[]; - doCache(val); - setValue([...val]); - } - }); - - //called on unmounted - const handleOnce = () => { - unsubscriber(); - document.removeEventListener(eventName, handleOnce); - // console.log(`[useDB:${path}] Remove listener onValue`); - }; - document.addEventListener(eventName, handleOnce); - }, 2 * 60 * 1000); - - //called on unmounted - const handleOnce = () => { - clearTimeout(timerId); - document.removeEventListener(eventName, handleOnce); - // console.log(`[useDB:${path}] Remove listener timeout`); - }; - document.addEventListener(eventName, handleOnce); - - // console.log(`[useDB:${path}] init`); - })(); - - return () => { - document.dispatchEvent(event); - // console.log(`[useDB:${path}] dispatch events on unmounted`); - }; - }, []); - - return value; -}; diff --git a/src/hooks/useHover.ts b/src/hooks/useHover.ts index 95fd44b..64baf17 100644 --- a/src/hooks/useHover.ts +++ b/src/hooks/useHover.ts @@ -1,11 +1,12 @@ -import { useState } from "react"; +import { useState, PointerEvent } from "react"; export const useHover = () => { const [hovered, setHover] = useState(false); + return { hovered, - hoverSpread: { - onPointerOver: (e: any) => { + hoverParams: { + onPointerOver: (e: PointerEvent) => { e.stopPropagation(); setHover(true); }, diff --git a/src/hooks/useInterval.ts b/src/hooks/useInterval.ts new file mode 100644 index 0000000..c6d4249 --- /dev/null +++ b/src/hooks/useInterval.ts @@ -0,0 +1,13 @@ +import { useEffect } from "react"; + +export const useInterval = (fn: () => boolean, ms: number) => { + useEffect(() => { + const timerId = setInterval(() => { + if (fn()) clearInterval(timerId); + }, ms); + + if (fn()) clearInterval(timerId); + + return () => clearInterval(timerId); + }, []); +}; diff --git a/src/hooks/useShakeAnimation.ts b/src/hooks/useShakeAnimation.ts deleted file mode 100644 index 4edac04..0000000 --- a/src/hooks/useShakeAnimation.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useSpring, useSpringRef } from "@react-spring/web"; - -export const useShakeAnimation = (x: number) => { - const api = useSpringRef(); - const style = useSpring({ - ref: api, - x: 0, - }); - - const shake = () => { - api.start({ - x: 0, - from: { x }, - config: { - mass: 1, - tension: 500, - friction: 15, - }, - }); - }; - - return [style, shake] as const; -}; diff --git a/src/hooks/useStreamFilter.ts b/src/hooks/useStreamFilter.ts new file mode 100644 index 0000000..f03647c --- /dev/null +++ b/src/hooks/useStreamFilter.ts @@ -0,0 +1,55 @@ +import { useCallback, useMemo, useEffect } from "react"; +import { Stream, Streamer } from "types"; +import { deduplication } from "src/utils"; +import { useSetting, useSettingDispatch } from "src/providers"; + +type StreamerFilterAction = { + type: "addStreamerFilter" | "removeStreamerFilter" | "clearStreamerFilter"; + payload?: Streamer["id"][]; +}; + +type FilterAction = StreamerFilterAction; + +export const useStreamFilter = (streams: Stream[]) => { + const { + filter: { streamerIds }, + } = useSetting(); + const settingDispatch = useSettingDispatch(); + + const filter = useCallback( + (action: FilterAction): void => { + if (action.type === "addStreamerFilter") { + const ids = deduplication(streamerIds.concat(action.payload ?? [])); + settingDispatch({ target: "streamerIds", payload: ids }); + return; + } + + if (action.type === "removeStreamerFilter") { + const ids = streamerIds.filter( + (id) => !(action.payload ?? []).includes(id), + ); + settingDispatch({ target: "streamerIds", payload: ids }); + return; + } + + if (action.type === "clearStreamerFilter") { + settingDispatch({ target: "streamerIds", payload: [] }); + return; + } + }, + [streamerIds], + ); + + useEffect(() => { + if (streamerIds.length > 0) + filter({ type: "addStreamerFilter", payload: streamerIds }); + }, []); + + const filteredStreams = useMemo(() => { + return streams.filter((s) => { + return streamerIds.length === 0 || streamerIds.includes(s.streamerId); + }); + }, [streams, streamerIds]); + + return { filteredStreams, streamerIds, filter }; +}; diff --git a/src/hooks/useStreamInfo.ts b/src/hooks/useStreamInfo.ts deleted file mode 100644 index 029e66d..0000000 --- a/src/hooks/useStreamInfo.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { useDB } from "./useDB"; -import { ChannelDTO, StreamDTO, StreamInfo, Service } from "../types"; -import { getFormattedDate, parseToJST } from "../utils"; -import { useMemo } from "react"; - -const DB_DATA_PATH = process.env.REACT_APP_DB_DATA_PATH; - -export const useStreamInfo = ( - service: Service, - channelCacheAvailableTime = 24 * 60 * 60, //sec - streamCacheAvailableTime = 5 * 60 //sec -): StreamInfo[] => { - const channels = useDB( - `${DB_DATA_PATH}/${service}/channels`, - channelCacheAvailableTime - ); - - const streams = useDB( - `${DB_DATA_PATH}/${service}/streams`, - streamCacheAvailableTime - ); - - const streamsInfo = useMemo( - () => - streams.reduce((state, s) => { - const ch = channels.find((c) => c.id === s.channelId); - - if (ch !== undefined) { - state.push({ - id: s.id, - title: s.title, - thumbnail: s.thumbnail, - url: s.url, - startAt: s.startAt, - scheduledDate: getFormattedDate(parseToJST(Date.parse(s.startAt))), - channelId: ch.id, - name: ch.name, - icon: ch.thumbnail, - gameName: s.gameName, - service, - }); - } - - return state; - }, []), - [streams] - ); - - return streamsInfo; -}; diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts deleted file mode 100644 index a1acbcd..0000000 --- a/src/hooks/useTheme.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react"; -import { ThemeContext } from "../components/providers/ThemeProvider"; - -export const useTheme = () => { - const context = useContext(ThemeContext); - - if (typeof context === "undefined") { - throw new Error("useTheme must be within a ThemeProvider"); - } - - return context; -}; diff --git a/src/hooks/useVspoStreams.ts b/src/hooks/useVspoStreams.ts deleted file mode 100644 index 69d5e0d..0000000 --- a/src/hooks/useVspoStreams.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react"; -import { VspoStreamingContext } from "../components/providers/VspoStreamingProvider"; - -export const useVspoStreams = () => { - const context = useContext(VspoStreamingContext); - - if (typeof context === "undefined") { - throw new Error("useVspoStreams must be within a VspoStreamingProvider"); - } - - return context; -}; diff --git a/src/hooks/useWindowSize.ts b/src/hooks/useWindowSize.ts deleted file mode 100644 index 48db1e6..0000000 --- a/src/hooks/useWindowSize.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useContext } from "react"; -import { WindowSizeContext } from "../components/providers/WindowSizeProvider"; - -export const useWindowSize = () => { - const context = useContext(WindowSizeContext); - - if (typeof context === "undefined") { - throw new Error("useWindowSize must be within a VspoStreamingProvider"); - } - - return context; -}; diff --git a/src/index.css b/src/index.css index 0b71428..aa57bd4 100644 --- a/src/index.css +++ b/src/index.css @@ -3,22 +3,8 @@ body { margin: 0; padding: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; + font-family: -apple-system, "Zen Kaku Gothic New", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - overflow: hidden; - -ms-overflow-style: none; - scrollbar-width: none; -} - -body::-webkit-scrollbar { - display: none; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; } diff --git a/src/index.js b/src/index.js index be0d40b..ab9a00d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,14 +1,12 @@ -import './Firebase'; -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import reportWebVitals from './reportWebVitals'; -import { App } from './App'; +import "./firebase"; +import React from "react"; +import ReactDOM from "react-dom/client"; +import "./index.css"; +import reportWebVitals from "./reportWebVitals"; +import { App } from "./app"; -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - -); +const root = ReactDOM.createRoot(document.getElementById("root")); +root.render(); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) diff --git a/src/providers/deviceTypeProvider/context.ts b/src/providers/deviceTypeProvider/context.ts new file mode 100644 index 0000000..735747e --- /dev/null +++ b/src/providers/deviceTypeProvider/context.ts @@ -0,0 +1,6 @@ +import { createContext } from "react"; +import { DisplaySizeInfo } from "types"; + +export const displaySizeContext = createContext( + {} as DisplaySizeInfo, +); diff --git a/src/providers/deviceTypeProvider/index.ts b/src/providers/deviceTypeProvider/index.ts new file mode 100644 index 0000000..1ab035b --- /dev/null +++ b/src/providers/deviceTypeProvider/index.ts @@ -0,0 +1,2 @@ +export * from "./provider"; +export * from "./use"; diff --git a/src/providers/deviceTypeProvider/provider.tsx b/src/providers/deviceTypeProvider/provider.tsx new file mode 100644 index 0000000..ea0d670 --- /dev/null +++ b/src/providers/deviceTypeProvider/provider.tsx @@ -0,0 +1,47 @@ +import React, { ReactNode, useCallback, useEffect, useReducer } from "react"; +import { displaySizeContext } from "./context"; +import { DisplaySizeInfo } from "types"; +import { calcBreakPoint } from "src/configs"; + +type Props = { + children: ReactNode; +}; + +const baseState: DisplaySizeInfo = { + mobile: false, + tablet: false, + desktop: false, +}; + +export const DisplaySizeProvider = ({ children }: Props) => { + const displaySizeReducer = useCallback( + (state: DisplaySizeInfo, width: number): DisplaySizeInfo => { + const type = calcBreakPoint(width); + if (state[type]) return state; + + return { ...baseState, [type]: true }; + }, + [], + ); + + const [displaySizeInfo, dispatch] = useReducer( + displaySizeReducer, + displaySizeReducer(baseState, window.innerWidth), + ); + + useEffect(() => { + const resize = () => { + dispatch(window.innerWidth); + }; + + resize(); + window.addEventListener("resize", resize); + return () => window.removeEventListener("resize", resize); + }, []); + + return ( + + {children} + + ); +}; diff --git a/src/providers/deviceTypeProvider/use.ts b/src/providers/deviceTypeProvider/use.ts new file mode 100644 index 0000000..72ea254 --- /dev/null +++ b/src/providers/deviceTypeProvider/use.ts @@ -0,0 +1,4 @@ +import { useContext } from "react"; +import { displaySizeContext } from "./context"; + +export const useDisplaySize = () => useContext(displaySizeContext); diff --git a/src/providers/index.ts b/src/providers/index.ts new file mode 100644 index 0000000..04ff9d5 --- /dev/null +++ b/src/providers/index.ts @@ -0,0 +1,4 @@ +export * from "./vspoStreamProvider"; +export * from "./settingProvider"; +export * from "./deviceTypeProvider"; +export * from "./themeProvider"; diff --git a/src/providers/settingProvider/context.ts b/src/providers/settingProvider/context.ts new file mode 100644 index 0000000..670dbe8 --- /dev/null +++ b/src/providers/settingProvider/context.ts @@ -0,0 +1,22 @@ +import { createContext } from "react"; +import { Setting, Streamer } from "types"; + +export type SettingAction = { + target: Extract< + keyof Setting, + "isDarkTheme" | "isExpandAlways" | "isMarqueeTitle" | "isDisplayHistory" + >; + payload: boolean; +}; + +export type StreamerFilterAction = { + target: Extract; + payload: Streamer["id"][]; +}; + +export type Action = SettingAction | StreamerFilterAction; + +export const settingContext = createContext({} as Setting); +export const settingDispatchContext = createContext>( + () => console.error("Dispatched action outside of an settingDispatchContext"), +); diff --git a/src/providers/settingProvider/index.ts b/src/providers/settingProvider/index.ts new file mode 100644 index 0000000..1ab035b --- /dev/null +++ b/src/providers/settingProvider/index.ts @@ -0,0 +1,2 @@ +export * from "./provider"; +export * from "./use"; diff --git a/src/providers/settingProvider/provider.tsx b/src/providers/settingProvider/provider.tsx new file mode 100644 index 0000000..f76f8a2 --- /dev/null +++ b/src/providers/settingProvider/provider.tsx @@ -0,0 +1,98 @@ +import React, { ReactNode, useCallback, useEffect, useReducer } from "react"; +import { DeepPartial, Setting } from "types"; +import { Action, settingContext, settingDispatchContext } from "./context"; +import { checkMobile } from "src/utils"; + +type Props = { + children: ReactNode; +}; + +const storageKey = "setting"; +const isMobile = checkMobile(); + +const getLocalSetting = (): DeepPartial => { + try { + return JSON.parse(localStorage.getItem(storageKey) ?? "{}"); + } catch { + return {}; + } +}; + +const setLocalSetting = (setting: Setting) => { + localStorage.setItem(storageKey, JSON.stringify(setting)); +}; + +export const getInitSetting = () => { + const localSetting = getLocalSetting(); + + const setting: Setting = { + isDarkTheme: { + state: localSetting.isDarkTheme?.state ?? false, + isReadOnly: false, + }, + isExpandAlways: { + state: isMobile || (localSetting.isExpandAlways?.state ?? false), + isReadOnly: isMobile, + }, + isMarqueeTitle: { + state: localSetting.isMarqueeTitle?.state ?? false, + isReadOnly: true, // TODO marquee + }, + isDisplayHistory: { + state: localSetting.isDisplayHistory?.state ?? false, + isReadOnly: false, + }, + filter: { + streamerIds: localSetting.filter?.streamerIds ?? [], + }, + }; + + return setting; +}; + +export const SettingProvider = ({ children }: Props) => { + const settingReducer = useCallback( + (prev: Setting, { target, payload }: Action) => { + if ( + "isDarkTheme" === target || + "isExpandAlways" === target || + "isMarqueeTitle" === target || + "isDisplayHistory" === target + ) { + const setting = prev[target]; + if (setting.isReadOnly) return prev; + + return { ...prev, [target]: { ...setting, state: payload } }; + } + + if ("streamerIds" === target) { + return { ...prev, filter: { [target]: payload } }; + } + + return prev; + }, + [], + ); + + const [setting, dispatch] = useReducer(settingReducer, getInitSetting()); + + useEffect(() => { + const onUnmount = () => { + setLocalSetting(setting); + }; + window.addEventListener("beforeunload", onUnmount); + + return () => { + setLocalSetting(setting); + window.removeEventListener("beforeunload", onUnmount); + }; + }, [setting]); + + return ( + + + {children} + + + ); +}; diff --git a/src/providers/settingProvider/use.ts b/src/providers/settingProvider/use.ts new file mode 100644 index 0000000..a9135af --- /dev/null +++ b/src/providers/settingProvider/use.ts @@ -0,0 +1,5 @@ +import { useContext } from "react"; +import { settingContext, settingDispatchContext } from "./context"; + +export const useSetting = () => useContext(settingContext); +export const useSettingDispatch = () => useContext(settingDispatchContext); diff --git a/src/providers/themeProvider/index.tsx b/src/providers/themeProvider/index.tsx new file mode 100644 index 0000000..c381b2a --- /dev/null +++ b/src/providers/themeProvider/index.tsx @@ -0,0 +1,19 @@ +import React, { FC, ReactNode, useMemo } from "react"; +import { ThemeProvider as TProvider } from "styled-components"; +import { themes } from "src/configs"; +import { useSetting } from "../settingProvider"; + +type Props = { + children: ReactNode; +}; + +export const ThemeProvider: FC = ({ children }) => { + const { isDarkTheme } = useSetting(); + + const theme = useMemo( + () => (isDarkTheme.state ? themes["dark"] : themes["light"]), + [isDarkTheme.state], + ); + + return {children}; +}; diff --git a/src/providers/vspoStreamProvider/context.ts b/src/providers/vspoStreamProvider/context.ts new file mode 100644 index 0000000..9208fb3 --- /dev/null +++ b/src/providers/vspoStreamProvider/context.ts @@ -0,0 +1,9 @@ +import { createContext } from "react"; +import { useStreamFilter } from "src/hooks"; +import { Stream, Streamer } from "types"; + +export const vspoStreamContext = createContext([]); +export const vspoStreamerContext = createContext([]); +export const vspoStreamFilterContext = createContext< + Pick, "filter" | "streamerIds"> +>(null!); diff --git a/src/providers/vspoStreamProvider/index.ts b/src/providers/vspoStreamProvider/index.ts new file mode 100644 index 0000000..1ab035b --- /dev/null +++ b/src/providers/vspoStreamProvider/index.ts @@ -0,0 +1,2 @@ +export * from "./provider"; +export * from "./use"; diff --git a/src/providers/vspoStreamProvider/provider.tsx b/src/providers/vspoStreamProvider/provider.tsx new file mode 100644 index 0000000..6df0774 --- /dev/null +++ b/src/providers/vspoStreamProvider/provider.tsx @@ -0,0 +1,132 @@ +import React, { ReactNode, useEffect, useMemo, useState } from "react"; +import { collection, onSnapshot } from "firebase/firestore"; +import { firestore } from "src/firebase"; +import { + vspoStreamContext, + vspoStreamerContext, + vspoStreamFilterContext, +} from "./context"; +import { + Channel, + Stream, + Streamer, + StreamerMap, + StreamerResponse, + StreamResponse, +} from "types"; +import { useStreamFilter } from "src/hooks"; + +type Props = { + children: ReactNode; +}; + +const parseToStream = ( + streamRes: StreamResponse, + streamerId: string, + channel: Channel, +): Stream => { + const endAt = streamRes.endTime ? new Date(streamRes.endTime) : undefined; + + return { + id: streamRes.id, + title: streamRes.title, + thumbnail: streamRes.thumbnail, + url: streamRes.url, + streamerId, + streamerName: channel.name, + icon: channel.icon, + platform: streamRes.platform, + startAt: new Date(streamRes.scheduledStartTime), + endAt, + }; +}; + +const parseToStreamer = (streamerRes: StreamerResponse): Streamer => { + const entries = Object.entries(streamerRes).map( + ([key, { id, name, icon }]) => [key, { id, name, icon }], + ); + + return Object.fromEntries(entries); +}; + +export const VspoStreamProvider = ({ children }: Props) => { + const [streamResponses, setStreamsResponse] = useState([]); + const [streamerMap, setStreamerMap] = useState({}); + + useEffect(() => { + const streamCollectionName = process.env.REACT_APP_STREAM_COLLECTION_NAME; + const streamerCollectionName = + process.env.REACT_APP_STREAMER_COLLECTION_NAME; + + if (!streamCollectionName || !streamerCollectionName) { + throw new Error( + "Environment variable not found: REACT_APP_STREAM_COLLECTION_NAME, REACT_APP_STREAMER_COLLECTION_NAME", + ); + } + + const unSubStream = onSnapshot( + collection(firestore, streamCollectionName), + (snapshot) => { + setStreamsResponse((prev) => { + const newStreams = snapshot.docs.map( + (doc) => doc.data() as StreamResponse, + ); + return [ + ...newStreams, + ...prev.filter((s) => !newStreams.some(({ id }) => id === s.id)), + ]; + }); + }, + ); + + const unSubStreamer = onSnapshot( + collection(firestore, streamerCollectionName), + (snapshot) => { + const map = Object.fromEntries( + snapshot.docs.map((doc) => { + return [doc.id, parseToStreamer(doc.data() as StreamerResponse)]; + }), + ); + setStreamerMap(map); + }, + ); + + return () => { + unSubStreamer(); + unSubStream(); + }; + }, []); + + const streams = useMemo(() => { + return streamResponses.reduce((results: Stream[], streamRes) => { + const streamerId = streamRes.streamerId; + const channel = streamerMap[streamerId][streamRes.platform]; + + if (!channel) { + console.error(`streamerId is not found: ${streamerId}`); + return results; + } + + return results.concat(parseToStream(streamRes, streamerId, channel)); + }, []); + }, [streamResponses, streamerMap]); + + const { filteredStreams, ...filterContext } = useStreamFilter(streams); + + const streamers = useMemo(() => { + return Object.entries(streamerMap).map(([id, channels]) => ({ + ...channels, + id, + })); + }, [streamerMap]); + + return ( + + + + {children} + + + + ); +}; diff --git a/src/providers/vspoStreamProvider/use.ts b/src/providers/vspoStreamProvider/use.ts new file mode 100644 index 0000000..f106e60 --- /dev/null +++ b/src/providers/vspoStreamProvider/use.ts @@ -0,0 +1,10 @@ +import { useContext } from "react"; +import { + vspoStreamContext, + vspoStreamerContext, + vspoStreamFilterContext, +} from "./context"; + +export const useVspoStreamFilter = () => useContext(vspoStreamFilterContext); +export const useVspoStream = () => useContext(vspoStreamContext); +export const useVspoStreamer = () => useContext(vspoStreamerContext); diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js index 5253d3a..9ecd33f 100644 --- a/src/reportWebVitals.js +++ b/src/reportWebVitals.js @@ -1,6 +1,6 @@ -const reportWebVitals = onPerfEntry => { +const reportWebVitals = (onPerfEntry) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { + import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); getFID(onPerfEntry); getFCP(onPerfEntry); diff --git a/src/setupTests.js b/src/setupTests.js index 8f2609b..1dd407a 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -2,4 +2,4 @@ // 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'; +import "@testing-library/jest-dom"; diff --git a/src/theme/dark.ts b/src/theme/dark.ts deleted file mode 100644 index 7059857..0000000 --- a/src/theme/dark.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ColorTheme } from "../types"; -import { common, grey, pink, blue } from "../colors"; - -export const dark: ColorTheme = { - text: { - primary: common.white, - }, - bg: { - primary: grey[900], - secondary: grey[800], - }, - hoverd: { - primary: grey[700], - secondary: grey[600], - }, - border: { - primary: grey[100], - }, - vspo: { - primary: pink[300], - secondary: blue[400], - }, -}; diff --git a/src/theme/index.ts b/src/theme/index.ts deleted file mode 100644 index 3d2f010..0000000 --- a/src/theme/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { dark } from "./dark"; -import { light } from "./light"; - -export default { - dark, - light, -}; diff --git a/src/theme/light.ts b/src/theme/light.ts deleted file mode 100644 index b438a3c..0000000 --- a/src/theme/light.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ColorTheme } from "../types"; -import { common, grey, pink, blue } from "../colors"; - -export const light: ColorTheme = { - text: { - primary: common.black, - }, - bg: { - primary: grey[50], - secondary: grey[100], - }, - hoverd: { - primary: grey[200], - secondary: grey[300], - }, - border: { - primary: grey[900], - }, - vspo: { - primary: blue[400], - secondary: pink[300], - }, -}; diff --git a/src/types/configs.ts b/src/types/configs.ts deleted file mode 100644 index 3dbadc2..0000000 --- a/src/types/configs.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - CSSObject, - FlattenSimpleInterpolation, - SimpleInterpolation, -} from "styled-components"; - -export type BreakpointValues = { - xs: number; - sm: number; - md: number; - lg: number; - xl: number; - xxl: number; -}; - -export type BreakpointMediaQuery = ( - base: CSSObject | TemplateStringsArray, - ...interpolations: SimpleInterpolation[] -) => FlattenSimpleInterpolation; - -export type BreakpointMediaQueries = { - xs: BreakpointMediaQuery; - sm: BreakpointMediaQuery; - md: BreakpointMediaQuery; - lg: BreakpointMediaQuery; - xl: BreakpointMediaQuery; - xxl: BreakpointMediaQuery; -}; - -export type Breakpoints = { - values: BreakpointValues; - mediaQueries: BreakpointMediaQueries; -}; diff --git a/src/types/frontLogic.ts b/src/types/frontLogic.ts deleted file mode 100644 index f4e8245..0000000 --- a/src/types/frontLogic.ts +++ /dev/null @@ -1,46 +0,0 @@ -export type Service = "youtube" | "twitch" | "twitCasting"; - -export type ChannelDTO = { - id: string; - name: string; - thumbnail: string; - uploads?: string; -}; - -export type StreamDTO = { - channelId: string; - id: string; - title: string; - thumbnail: string; - url: string; - startAt: string; - gameName?: string; -}; - -export type ChannelCache = { - channels: ChannelDTO[]; - timestamp: string; -}; - -export type StreamingCache = { - streams: StreamDTO[]; - timestamp: string; -}; - -export type ChildrenNode = { - children: React.ReactNode; -}; - -export type StreamInfo = { - id: string; - title: string; - thumbnail: string; - url: string; - startAt: string; - scheduledDate: string; - channelId: string; - name: string; - icon: string; - gameName?: string; - service: Service; -}; diff --git a/src/types/frontUI.ts b/src/types/frontUI.ts deleted file mode 100644 index b25b04a..0000000 --- a/src/types/frontUI.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { StreamInfo, Service, ChildrenNode } from "./frontLogic"; - -export type WindowSize = { - width: number; - height: number; -}; - -export type ClientType = { - isMobile: boolean; - isPhoneSize: boolean; - isTabletSize: boolean; - isDesktopSize: boolean; -}; - -export type ThumbnailBlockProps = { - title: string; - thumbnail: string; - name: string; - icon: string; - isExpand: boolean; - hovered: boolean; -} & React.HTMLAttributes; - -export type ServiceIconProps = { - startAt: string; - isExpand: boolean; - service: Service; -} & React.HTMLAttributes; - -export type StreamingHeaderProps = Omit; - -export type StreamingCardProps = Omit< - ServiceIconProps & Omit, - "isExpand" -> & { - url: string; -}; - -export type StreamingTableProps = { - streams: StreamInfo[]; -} & React.HTMLAttributes; - -export type DateBorderProps = { - dateString: string; -} & React.HTMLAttributes; - -export type BaseButtonProps = { - onClickHandler: () => void; - children: React.ReactNode; -} & React.HTMLAttributes; - -export type LinkButtonProps = { - url: string; -} & Omit; - -export type StreamList = { - date: string; - streams: StreamInfo[]; -}; diff --git a/src/types/index.ts b/src/types/index.ts deleted file mode 100644 index 051e7d1..0000000 --- a/src/types/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./frontLogic"; -export * from "./frontUI"; -export * from "./theme"; -export * from "./configs"; diff --git a/src/types/theme.ts b/src/types/theme.ts deleted file mode 100644 index b676d77..0000000 --- a/src/types/theme.ts +++ /dev/null @@ -1,25 +0,0 @@ -export type ColorLevel = { - primary: string; - secondary?: string; -}; - -export type ColorTheme = { - text: ColorLevel; - bg: ColorLevel; - hoverd: ColorLevel; - border: ColorLevel; - vspo: ColorLevel; -}; - -export type Theme = { - dark: ColorTheme; - light: ColorTheme; -}; - -export type ThemeTypes = keyof Theme; - -export type ThemeContextType = { - themeType: ThemeTypes; - theme: ColorTheme; - setThemeDark: (isOn: boolean) => void; -}; diff --git a/src/utils/arrayUtils.ts b/src/utils/arrayUtils.ts new file mode 100644 index 0000000..74dae28 --- /dev/null +++ b/src/utils/arrayUtils.ts @@ -0,0 +1,3 @@ +export const deduplication = (array: any[]) => { + return Array.from(new Set(array)); +}; diff --git a/src/utils/dateUtils.ts b/src/utils/dateUtils.ts new file mode 100644 index 0000000..7ecc85b --- /dev/null +++ b/src/utils/dateUtils.ts @@ -0,0 +1,18 @@ +export const toJST = (utcDate: Date) => { + utcDate.setHours(utcDate.getHours() + 9); + return utcDate; +}; + +export const toYYYYMMDD = (date: Date) => + date.toLocaleDateString("ja-JP", { + year: "numeric", + month: "2-digit", + day: "2-digit", + }); + +export const toJstHHMM = (date: Date) => + date.toLocaleString("ja-JP", { + timeZone: "Asia/Tokyo", + hour: "2-digit", + minute: "2-digit", + }); diff --git a/src/utils/deviceUtils.ts b/src/utils/deviceUtils.ts new file mode 100644 index 0000000..414dd44 --- /dev/null +++ b/src/utils/deviceUtils.ts @@ -0,0 +1,12 @@ +/// + +export const checkMobile = (): boolean => { + if (navigator.userAgentData) { + return navigator.userAgentData.mobile; + } else { + return ( + /android|ipod|ipad|iphone/.test(navigator.userAgent.toLowerCase()) && + "ontouchend" in document + ); + } +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index eed7dfe..6c0c937 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,10 +1,3 @@ -export const parseToJST = (utcmilisec: number) => - new Date(utcmilisec + (new Date().getTimezoneOffset() + 9 * 60) * 60 * 1000); - -export const getFormattedDate = (date: Date) => { - const y = date.getFullYear(); - const m = (date.getMonth() + 1).toString().padStart(2, "0"); - const d = date.getDate().toString().padStart(2, "0"); - - return `${y}/${m}/${d}`.replace(/\n|\r/g, ""); -}; +export * from "./dateUtils"; +export * from "./deviceUtils"; +export * from "./arrayUtils"; diff --git a/tsconfig.json b/tsconfig.json index e3642af..f31d7ae 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,12 +15,9 @@ "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, - "isolatedModules": true, "noEmit": true, - "jsx": "react" + "jsx": "react", + "baseUrl": ".", }, - "include": [ - "src", - "@types" - ] + "include": ["src", "types"] } \ No newline at end of file diff --git a/types/config.ts b/types/config.ts new file mode 100644 index 0000000..f0f6c18 --- /dev/null +++ b/types/config.ts @@ -0,0 +1,24 @@ +import { + CSSObject, + FlattenSimpleInterpolation, + SimpleInterpolation, +} from "styled-components"; + +export type BreakpointKey = "mobile" | "tablet" | "desktop"; + +export type BreakpointMediaQuery = ( + base: CSSObject | TemplateStringsArray, + ...interpolations: SimpleInterpolation[] +) => FlattenSimpleInterpolation; + +export type BreakpointMediaQueries = { + [key in BreakpointKey]: BreakpointMediaQuery; +}; + +export type Breakpoints = { + [key in BreakpointKey]: number; +}; + +export type DisplaySizeInfo = { + [key in BreakpointKey]: boolean; +}; diff --git a/types/custom.ts b/types/custom.ts new file mode 100644 index 0000000..22958bf --- /dev/null +++ b/types/custom.ts @@ -0,0 +1,9 @@ +declare module "*.png" { + const content: string; + export default content; +} + +declare module "*.svg" { + const content: string; + export default content; +} diff --git a/types/index.ts b/types/index.ts new file mode 100644 index 0000000..ecf35a1 --- /dev/null +++ b/types/index.ts @@ -0,0 +1,12 @@ +export * from "./stream"; +export * from "./setting"; +export * from "./config"; +export * from "./theme"; + +export type DeepPartial = { + [P in keyof T]?: T[P] extends (infer U)[] + ? DeepPartial[] + : T[P] extends Readonly[] + ? Readonly>[] + : DeepPartial; +}; diff --git a/types/setting.ts b/types/setting.ts new file mode 100644 index 0000000..eb8e598 --- /dev/null +++ b/types/setting.ts @@ -0,0 +1,18 @@ +import { Streamer } from "./stream"; + +export type SettingState = { + state: boolean; + isReadOnly: boolean; +}; + +export type FilterInfo = { + streamerIds: Streamer["id"][]; +}; + +export type Setting = { + isDarkTheme: SettingState; + isExpandAlways: SettingState; + isMarqueeTitle: SettingState; + isDisplayHistory: SettingState; + filter: FilterInfo; +}; diff --git a/types/stream.ts b/types/stream.ts new file mode 100644 index 0000000..79229da --- /dev/null +++ b/types/stream.ts @@ -0,0 +1,47 @@ +export type Platform = "youtube" | "twitch" | "twitCasting"; + +export type ChannelResponse = { + id: string; + name: string; + icon: string; + platform: Platform; +}; + +export type StreamerResponse = { [k in Platform]: ChannelResponse }; + +export type StreamResponse = { + id: string; + streamerId: string; + channelId: string; + platform: Platform; + title: string; + thumbnail: string; + url: string; + scheduledStartTime: string; // date string + startTime?: string; // date string + endTime?: string; // date string + ttl: Date; +}; + +export type Channel = { + id: string; + name: string; + icon: string; +}; + +export type Streamer = { [key in Platform]: Channel } & { id: string }; + +export type StreamerMap = { [id in string]: Streamer }; + +export type Stream = { + id: string; + title: string; + thumbnail: string; + url: string; + streamerId: string; + streamerName: Channel["name"]; + icon: Channel["icon"]; + platform: Platform; + startAt: Date; + endAt?: Date; +}; diff --git a/types/theme.ts b/types/theme.ts new file mode 100644 index 0000000..720c983 --- /dev/null +++ b/types/theme.ts @@ -0,0 +1,63 @@ +import "styled-components"; + +export type ThemeType = "light" | "dark"; + +export type CardTheme = { + text: string; + bg: string; +}; + +export type CardHeaderTheme = { + icon: { + 0: string; + 1: string; + 2: string; + }; + text: string; +}; + +export type HeaderTheme = { + text: string; +}; + +export type ButtonTheme = { + icon: string; + bg: { + normal: string; + hover?: string; + active?: string; + }; +}; + +export type DropdownTheme = { + input: ButtonTheme; + filter: { + clear: ButtonTheme; + }; + border: string; + text: string; + bg: string; + item: { + default: { + bg: { + normal: string; + hover: string; + }; + }; + toggle: (isOn: boolean) => ButtonTheme; + }; +}; + +declare module "styled-components" { + export interface DefaultTheme { + bg: string; + card: CardTheme; + cardHeader: CardHeaderTheme; + header: HeaderTheme; + dropdown: DropdownTheme; + } + + export type Themes = { + [key in ThemeType]: DefaultTheme; + }; +} From afde4215d9453e036b5fc6cdbbedc0bc691eb2aa Mon Sep 17 00:00:00 2001 From: mnsinri Date: Mon, 14 Oct 2024 21:59:25 +0900 Subject: [PATCH 4/5] =?UTF-8?q?build=E3=81=8C=E9=80=9A=E3=82=89=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=89=E3=81=97=E3=81=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 6 +++--- src/index.js | 2 +- src/providers/vspoStreamProvider/provider.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5fb1ec3..47c0b62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6639,9 +6639,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001514", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001514.tgz", - "integrity": "sha512-ENcIpYBmwAAOm/V2cXgM7rZUrKKaqisZl4ZAI520FIkqGXUxJjmaIssbRW5HVVR5tyV6ygTLIm15aU8LUmQSaQ==", + "version": "1.0.30001668", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001668.tgz", + "integrity": "sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==", "funding": [ { "type": "opencollective", diff --git a/src/index.js b/src/index.js index ab9a00d..6457b40 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import "./firebase"; +import "./Firebase"; import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; diff --git a/src/providers/vspoStreamProvider/provider.tsx b/src/providers/vspoStreamProvider/provider.tsx index 6df0774..058b4b5 100644 --- a/src/providers/vspoStreamProvider/provider.tsx +++ b/src/providers/vspoStreamProvider/provider.tsx @@ -1,6 +1,6 @@ import React, { ReactNode, useEffect, useMemo, useState } from "react"; import { collection, onSnapshot } from "firebase/firestore"; -import { firestore } from "src/firebase"; +import { firestore } from "src/Firebase"; import { vspoStreamContext, vspoStreamerContext, From bcc1ad97891c33222077d923f48faeddf7787185 Mon Sep 17 00:00:00 2001 From: mnsinri Date: Mon, 14 Oct 2024 22:03:49 +0900 Subject: [PATCH 5/5] =?UTF-8?q?delete:=20=E3=81=A4=E3=81=84=E3=81=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- database.rules.json | 17 ----------------- src/index.js | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 database.rules.json diff --git a/database.rules.json b/database.rules.json deleted file mode 100644 index 07cf3c2..0000000 --- a/database.rules.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */ - "rules": { - "vspo": { - ".read": false, - ".write": false - }, - "data": { - ".read": true, - ".write": false - }, - "testData": { - ".read": true, - ".write": false - } - } -} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 6457b40..dded0df 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import reportWebVitals from "./reportWebVitals"; -import { App } from "./app"; +import { App } from "./App"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render();