From 1ef2aa35e910dcc587094909dc5ff114d2252c93 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Tue, 6 Aug 2024 18:03:27 +0800 Subject: [PATCH 01/65] feat: jest --- jest.config.ts | 21 + jest.setup.ts | 2 + package.json | 156 +-- test/sum-module.test.ts | 9 + yarn.lock | 2004 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 2086 insertions(+), 106 deletions(-) create mode 100644 jest.config.ts create mode 100644 jest.setup.ts create mode 100644 test/sum-module.test.ts diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000000..cd25e8e7a5a --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,21 @@ +import type { Config } from "jest"; +import nextJest from "next/jest.js"; + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: "./", +}); + +// Add any custom config to be passed to Jest +const config: Config = { + coverageProvider: "v8", + testEnvironment: "jsdom", + testMatch: ["**/*.test.js", "**/*.test.ts", "**/*.test.jsx", "**/*.test.tsx"], + setupFilesAfterEnv: ["/jest.setup.ts"], + moduleNameMapper: { + "^@/(.*)$": "/$1", + }, +}; + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +export default createJestConfig(config); diff --git a/jest.setup.ts b/jest.setup.ts new file mode 100644 index 00000000000..ee6ccea1a85 --- /dev/null +++ b/jest.setup.ts @@ -0,0 +1,2 @@ +// Learn more: https://github.com/testing-library/jest-dom +import "@testing-library/jest-dom"; diff --git a/package.json b/package.json index eb0a5ef6735..91be0544e00 100644 --- a/package.json +++ b/package.json @@ -1,76 +1,84 @@ { - "name": "nextchat", - "private": false, - "license": "mit", - "scripts": { - "mask": "npx tsx app/masks/build.ts", - "mask:watch": "npx watch \"yarn mask\" app/masks", - "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", - "build": "yarn mask && cross-env BUILD_MODE=standalone next build", - "start": "next start", - "lint": "next lint", - "export": "yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", - "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", - "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", - "app:build": "yarn mask && yarn tauri build", - "prompts": "node ./scripts/fetch-prompts.mjs", - "prepare": "husky install", - "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev" - }, - "dependencies": { - "@fortaine/fetch-event-source": "^3.0.6", - "@hello-pangea/dnd": "^16.5.0", - "@next/third-parties": "^14.1.0", - "@svgr/webpack": "^6.5.1", - "@vercel/analytics": "^0.1.11", - "@vercel/speed-insights": "^1.0.2", - "emoji-picker-react": "^4.9.2", - "fuse.js": "^7.0.0", - "heic2any": "^0.0.4", - "html-to-image": "^1.11.11", - "lodash-es": "^4.17.21", - "mermaid": "^10.6.1", - "nanoid": "^5.0.3", - "next": "^14.1.1", - "node-fetch": "^3.3.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-markdown": "^8.0.7", - "react-router-dom": "^6.15.0", - "rehype-highlight": "^6.0.0", - "rehype-katex": "^6.0.3", - "remark-breaks": "^3.0.2", - "remark-gfm": "^3.0.1", - "remark-math": "^5.1.1", - "sass": "^1.59.2", - "spark-md5": "^3.0.2", - "use-debounce": "^9.0.4", - "zustand": "^4.3.8" - }, - "devDependencies": { - "@tauri-apps/cli": "1.5.11", - "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.30", - "@types/react": "^18.2.70", - "@types/react-dom": "^18.2.7", - "@types/react-katex": "^3.0.0", - "@types/spark-md5": "^3.0.4", - "concurrently": "^8.2.2", - "cross-env": "^7.0.3", - "eslint": "^8.49.0", - "eslint-config-next": "13.4.19", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^5.1.3", - "husky": "^8.0.0", - "lint-staged": "^13.2.2", - "prettier": "^3.0.2", - "tsx": "^4.16.0", - "typescript": "5.2.2", - "watch": "^1.0.2", - "webpack": "^5.88.1" - }, - "resolutions": { - "lint-staged/yaml": "^2.2.2" - }, - "packageManager": "yarn@1.22.19" + "name": "nextchat", + "private": false, + "license": "mit", + "scripts": { + "mask": "npx tsx app/masks/build.ts", + "mask:watch": "npx watch \"yarn mask\" app/masks", + "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", + "build": "yarn mask && cross-env BUILD_MODE=standalone next build", + "start": "next start", + "lint": "next lint", + "export": "yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", + "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", + "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", + "app:build": "yarn mask && yarn tauri build", + "prompts": "node ./scripts/fetch-prompts.mjs", + "prepare": "husky install", + "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev", + "test": "jest --watch", + "test:ci": "jest --ci" + }, + "dependencies": { + "@fortaine/fetch-event-source": "^3.0.6", + "@hello-pangea/dnd": "^16.5.0", + "@next/third-parties": "^14.1.0", + "@svgr/webpack": "^6.5.1", + "@vercel/analytics": "^0.1.11", + "@vercel/speed-insights": "^1.0.2", + "emoji-picker-react": "^4.9.2", + "fuse.js": "^7.0.0", + "heic2any": "^0.0.4", + "html-to-image": "^1.11.11", + "lodash-es": "^4.17.21", + "mermaid": "^10.6.1", + "nanoid": "^5.0.3", + "next": "^14.1.1", + "node-fetch": "^3.3.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^8.0.7", + "react-router-dom": "^6.15.0", + "rehype-highlight": "^6.0.0", + "rehype-katex": "^6.0.3", + "remark-breaks": "^3.0.2", + "remark-gfm": "^3.0.1", + "remark-math": "^5.1.1", + "sass": "^1.59.2", + "spark-md5": "^3.0.2", + "use-debounce": "^9.0.4", + "zustand": "^4.3.8" + }, + "devDependencies": { + "@tauri-apps/cli": "1.5.11", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/jest": "^29.5.12", + "@types/lodash-es": "^4.17.12", + "@types/node": "^20.11.30", + "@types/react": "^18.2.70", + "@types/react-dom": "^18.2.7", + "@types/react-katex": "^3.0.0", + "@types/spark-md5": "^3.0.4", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "eslint": "^8.49.0", + "eslint-config-next": "13.4.19", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.1.3", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^13.2.2", + "prettier": "^3.0.2", + "ts-node": "^10.9.2", + "tsx": "^4.16.0", + "typescript": "5.2.2", + "watch": "^1.0.2", + "webpack": "^5.88.1" + }, + "resolutions": { + "lint-staged/yaml": "^2.2.2" + }, + "packageManager": "yarn@1.22.19" } diff --git a/test/sum-module.test.ts b/test/sum-module.test.ts new file mode 100644 index 00000000000..4773d19eb87 --- /dev/null +++ b/test/sum-module.test.ts @@ -0,0 +1,9 @@ +function sum(a: number, b: number) { + return a + b; +} + +describe("sum module", () => { + test("adds 1 + 2 to equal 3", () => { + expect(sum(1, 2)).toBe(3); + }); +}); diff --git a/yarn.lock b/yarn.lock index 793c845d722..39dbaaeb4e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,6 +7,11 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== +"@adobe/css-tools@^4.4.0": + version "4.4.0" + resolved "https://registry.npmmirror.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" + integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== + "@ampproject/remapping@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -22,6 +27,14 @@ dependencies: "@babel/highlight" "^7.18.6" +"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + "@babel/code-frame@^7.22.13": version "7.22.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" @@ -35,6 +48,32 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== +"@babel/compat-data@^7.25.2": + version "7.25.2" + resolved "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.25.2.tgz#e41928bd33475305c586f6acbbb7e3ade7a6f7f5" + integrity sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": + version "7.25.2" + resolved "https://registry.npmmirror.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" + integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== + dependencies: + "@ampproject/remapping" "^2.2.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.3" + semver "^6.3.1" + "@babel/core@^7.19.6": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.3.tgz#cf1c877284a469da5d1ce1d1e53665253fae712e" @@ -76,6 +115,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.25.0", "@babel/generator@^7.7.2": + version "7.25.0" + resolved "https://registry.npmmirror.com/@babel/generator/-/generator-7.25.0.tgz#f858ddfa984350bc3d3b7f125073c9af6988f18e" + integrity sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw== + dependencies: + "@babel/types" "^7.25.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -102,6 +151,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== + dependencies: + "@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" + "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" @@ -197,6 +257,14 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" @@ -211,6 +279,16 @@ "@babel/traverse" "^7.21.2" "@babel/types" "^7.21.2" +"@babel/helper-module-transforms@^7.25.2": + version "7.25.2" + resolved "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== + dependencies: + "@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" + "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" @@ -223,6 +301,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.24.7": + version "7.24.8" + resolved "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" @@ -252,6 +335,14 @@ dependencies: "@babel/types" "^7.20.2" +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers@^7.20.0": version "7.20.0" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" @@ -283,6 +374,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" @@ -293,11 +389,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + "@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== +"@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + "@babel/helper-wrap-function@^7.18.9": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" @@ -317,6 +423,14 @@ "@babel/traverse" "^7.21.0" "@babel/types" "^7.21.0" +"@babel/helpers@^7.25.0": + version "7.25.0" + resolved "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" + integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + dependencies: + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.0" + "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -335,6 +449,23 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.0", "@babel/parser@^7.25.3": + version "7.25.3" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.3.tgz#91fb126768d944966263f0657ab222a642b82065" + integrity sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw== + dependencies: + "@babel/types" "^7.25.2" + "@babel/parser@^7.20.7", "@babel/parser@^7.21.3": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3" @@ -497,7 +628,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.12.13": +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== @@ -532,6 +670,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -546,7 +691,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -560,7 +712,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4": +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -595,7 +747,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-top-level-await@^7.14.5": +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -609,6 +761,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.24.7" + resolved "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551" @@ -1035,7 +1194,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.21.0": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.21.0": version "7.25.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== @@ -1060,6 +1219,15 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" +"@babel/template@^7.25.0", "@babel/template@^7.3.3": + version "7.25.0" + resolved "https://registry.npmmirror.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.3": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" @@ -1076,6 +1244,28 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.24.7", "@babel/traverse@^7.25.2": + version "7.25.3" + resolved "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.25.3.tgz#f1b901951c83eda2f3e29450ce92743783373490" + integrity sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.2" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.3.3": + version "7.25.2" + resolved "https://registry.npmmirror.com/@babel/types/-/types-7.25.2.tgz#55fb231f7dc958cd69ea141a4c2997e819646125" + integrity sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.3", "@babel/types@^7.4.4": version "7.21.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.3.tgz#4865a5357ce40f64e3400b0f3b737dc6d4f64d05" @@ -1094,11 +1284,23 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npmmirror.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@braintree/sanitize-url@^6.0.1": version "6.0.4" resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmmirror.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@esbuild/aix-ppc64@0.21.5": version "0.21.5" resolved "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" @@ -1283,6 +1485,214 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npmmirror.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.npmmirror.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@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.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.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@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" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.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.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" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.npmmirror.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.npmmirror.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.npmmirror.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@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.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" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.npmmirror.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -1309,16 +1719,35 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + "@jridgewell/source-map@^0.3.3": version "0.3.3" resolved "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda" @@ -1332,6 +1761,27 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -1440,6 +1890,25 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.npmmirror.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.npmmirror.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@svgr/babel-plugin-add-jsx-attribute@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" @@ -1619,11 +2088,90 @@ "@tauri-apps/cli-win32-ia32-msvc" "1.5.11" "@tauri-apps/cli-win32-x64-msvc" "1.5.11" +"@testing-library/jest-dom@^6.4.8": + version "6.4.8" + resolved "https://registry.npmmirror.com/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz#9c435742b20c6183d4e7034f2b329d562c079daa" + integrity sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw== + dependencies: + "@adobe/css-tools" "^4.4.0" + "@babel/runtime" "^7.9.2" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + +"@testing-library/react@^16.0.0": + version "16.0.0" + resolved "https://registry.npmmirror.com/@testing-library/react/-/react-16.0.0.tgz#0a1e0c7a3de25841c3591b8cb7fb0cf0c0a27321" + integrity sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ== + dependencies: + "@babel/runtime" "^7.12.5" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.npmmirror.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmmirror.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmmirror.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.npmmirror.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.6" + resolved "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + "@types/d3-scale-chromatic@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954" @@ -1669,6 +2217,13 @@ resolved "https://registry.npmmirror.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.npmmirror.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + "@types/hast@^2.0.0": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -1684,6 +2239,42 @@ "@types/react" "*" hoist-non-react-statics "^3.3.0" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.npmmirror.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.npmmirror.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.npmmirror.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.12": + version "29.5.12" + resolved "https://registry.npmmirror.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/jsdom@^20.0.0": + version "20.0.1" + resolved "https://registry.npmmirror.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" + integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + "@types/json-schema@*", "@types/json-schema@^7.0.8": version "7.0.12" resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" @@ -1778,6 +2369,16 @@ resolved "https://registry.yarnpkg.com/@types/spark-md5/-/spark-md5-3.0.4.tgz#c1221d63c069d95aba0c06a765b80661cacc12bf" integrity sha512-qtOaDz+IXiNndPgYb6t1YoutnGvFRtWSNzpVjkAPCfB2UzTyybuD4Tjgs7VgRawum3JnJNRwNQd4N//SvrHg1Q== +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.npmmirror.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.npmmirror.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + "@types/unist@*", "@types/unist@^2.0.0": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" @@ -1788,6 +2389,18 @@ resolved "https://registry.npmmirror.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43" integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA== +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.npmmirror.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.npmmirror.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/parser@^5.4.2 || ^6.0.0": version "6.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.4.0.tgz#47e7c6e22ff1248e8675d95f488890484de67600" @@ -1974,6 +2587,19 @@ resolved "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== + dependencies: + acorn "^8.1.0" + acorn-walk "^8.0.2" + acorn-import-assertions@^1.9.0: version "1.9.0" resolved "https://registry.npmmirror.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" @@ -1984,6 +2610,18 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== +acorn-walk@^8.0.2, acorn-walk@^8.1.1: + version "8.3.3" + resolved "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" + +acorn@^8.1.0, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.8.1: + version "8.12.1" + resolved "https://registry.npmmirror.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + acorn@^8.7.1, acorn@^8.8.2: version "8.9.0" resolved "https://registry.npmmirror.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" @@ -1994,6 +2632,13 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +agent-base@6: + version "6.0.2" + resolved "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -2017,7 +2662,7 @@ ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.3.0: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -2048,12 +2693,17 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + ansi-styles@^6.0.0: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@~3.1.2: +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -2061,11 +2711,30 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmmirror.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@^5.0.0: + version "5.3.0" + resolved "https://registry.npmmirror.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + aria-query@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" @@ -2138,6 +2807,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -2155,6 +2829,40 @@ axobject-query@^3.1.1: dependencies: deep-equal "^2.0.5" +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.npmmirror.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" @@ -2179,6 +2887,32 @@ babel-plugin-polyfill-regenerator@^0.4.1: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + bail@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" @@ -2234,6 +2968,23 @@ browserslist@^4.21.3, browserslist@^4.21.5: node-releases "^2.0.8" update-browserslist-db "^1.0.10" +browserslist@^4.23.1: + version "4.23.3" + resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== + dependencies: + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2259,6 +3010,11 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" @@ -2269,6 +3025,11 @@ caniuse-lite@^1.0.30001449, caniuse-lite@^1.0.30001503, caniuse-lite@^1.0.300015 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz#809bc25f3f5027ceb33142a7d6c40759d7a901eb" integrity sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA== +caniuse-lite@^1.0.30001646: + version "1.0.30001649" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz#3ec700309ca0da2b0d3d5fb03c411b191761c992" + integrity sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ== + ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" @@ -2288,6 +3049,14 @@ chalk@^2.0.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2296,6 +3065,11 @@ chalk@^4.0.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + character-entities@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" @@ -2321,6 +3095,16 @@ chrome-trace-event@^1.0.2: resolved "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.npmmirror.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.3.1" + resolved "https://registry.npmmirror.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" + integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2363,6 +3147,16 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmmirror.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -2392,6 +3186,13 @@ colorette@^2.0.19: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + comma-separated-tokens@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" @@ -2442,6 +3243,11 @@ convert-source-map@^1.7.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + core-js-compat@^3.25.1: version "3.29.1" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.29.1.tgz#15c0fb812ea27c973c18d425099afa50b934b41b" @@ -2474,9 +3280,27 @@ cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cross-env@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + 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" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmmirror.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== dependencies: cross-spawn "^7.0.1" @@ -2521,6 +3345,11 @@ css-what@^6.0.1: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.npmmirror.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -2528,6 +3357,23 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + csstype@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" @@ -2844,6 +3690,15 @@ data-uri-to-buffer@^4.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + date-fns@^2.30.0: version "2.30.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" @@ -2856,6 +3711,13 @@ dayjs@^1.11.7: resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== +debug@4, debug@^4.3.1: + version "4.3.6" + resolved "https://registry.npmmirror.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -2870,6 +3732,11 @@ debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" +decimal.js@^10.4.2: + version "10.4.3" + resolved "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + decode-named-character-reference@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" @@ -2877,6 +3744,11 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.npmmirror.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + deep-equal@^2.0.5: version "2.2.0" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.0.tgz#5caeace9c781028b9ff459f33b779346637c43e6" @@ -2925,11 +3797,31 @@ delaunator@5: dependencies: robust-predicates "^3.0.0" -dequal@^2.0.0: +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +dequal@^2.0.0, dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmmirror.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + diff@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" @@ -2956,6 +3848,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.npmmirror.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -2970,6 +3867,13 @@ domelementtype@^2.0.1, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + domhandler@^4.2.0, domhandler@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" @@ -3006,11 +3910,21 @@ electron-to-chromium@^1.4.431: resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.445.tgz#058d2c5f3a2981ab1a37440f5a5e42d15672aa6d" integrity sha512-++DB+9VK8SBJwC+X1zlMfJ1tMA3F0ipi39GdEp+x3cV2TyBihqAgad8cNMWtLDEkbH39nlDQP7PfGrDr3Dr7HA== +electron-to-chromium@^1.5.4: + version "1.5.5" + resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.5.tgz#03bfdf422bdd2c05ee2657efedde21264a1a566b" + integrity sha512-QR7/A7ZkMS8tZuoftC/jfqNkZLQO779SSW3YuZHP4eXpj3EffGLFcB/Xu9AAZQzLccTiCV+EmUo3ha4mQ9wnlA== + elkjs@^0.8.2: version "0.8.2" resolved "https://registry.npmmirror.com/elkjs/-/elkjs-0.8.2.tgz#c37763c5a3e24e042e318455e0147c912a7c248e" integrity sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ== +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.npmmirror.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + emoji-picker-react@^4.9.2: version "4.9.2" resolved "https://registry.yarnpkg.com/emoji-picker-react/-/emoji-picker-react-4.9.2.tgz#5118c5e1028ce4a96c94eb7c9bef09d30b08742c" @@ -3180,11 +4094,21 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -3195,6 +4119,17 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== +escodegen@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + eslint-config-next@13.4.19: version "13.4.19" resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-13.4.19.tgz#f46be9d4bd9e52755f846338456132217081d7f8" @@ -3394,6 +4329,11 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" @@ -3435,6 +4375,21 @@ exec-sh@^0.2.0: dependencies: merge "^1.2.0" +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + execa@^7.0.0: version "7.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" @@ -3450,6 +4405,22 @@ execa@^7.0.0: signal-exit "^3.0.7" strip-final-newline "^3.0.0" +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.npmmirror.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@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" + extend@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3476,7 +4447,7 @@ fast-glob@^3.2.11, fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -3500,6 +4471,13 @@ fault@^2.0.0: dependencies: format "^0.2.0" +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.npmmirror.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + fetch-blob@^3.1.2, fetch-blob@^3.1.4: version "3.2.0" resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" @@ -3522,6 +4500,14 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -3555,6 +4541,15 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + format@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" @@ -3572,21 +4567,26 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@^2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== -fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" @@ -3626,7 +4626,12 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@ has "^1.0.3" has-symbols "^1.0.3" -get-stream@^6.0.1: +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== @@ -3682,7 +4687,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3799,6 +4804,13 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hast-util-from-dom@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz#25836ddecc3cc0849d32749c2a7aec03e94b59a7" @@ -3904,11 +4916,45 @@ hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: dependencies: react-is "^16.7.0" +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmmirror.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-to-image@^1.11.11: version "1.11.11" resolved "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.11.11.tgz#c0f8a34dc9e4b97b93ff7ea286eb8562642ebbea" integrity sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA== +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + human-signals@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" @@ -3919,7 +4965,7 @@ husky@^8.0.0: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -iconv-lite@0.6: +iconv-lite@0.6, iconv-lite@0.6.3: version "0.6.3" resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -3944,6 +4990,14 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-local@^3.0.2: + version "3.2.0" + resolved "https://registry.npmmirror.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -4052,6 +5106,13 @@ is-core-module@^2.11.0, is-core-module@^2.9.0: dependencies: has "^1.0.3" +is-core-module@^2.13.0: + version "2.15.0" + resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== + dependencies: + hasown "^2.0.2" + is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -4074,6 +5135,11 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -4113,6 +5179,11 @@ is-plain-obj@^4.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -4133,6 +5204,11 @@ is-shared-array-buffer@^1.0.2: dependencies: call-bind "^1.0.2" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" @@ -4193,6 +5269,411 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.npmmirror.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.3" + resolved "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.npmmirror.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.npmmirror.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.7" + resolved "https://registry.npmmirror.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@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 "^1.0.0" + is-generator-fn "^2.0.0" + 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.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@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" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@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.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.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-jsdom@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" + integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/jsdom" "^20.0.0" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + jsdom "^20.0.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.npmmirror.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@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.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@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.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.npmmirror.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.npmmirror.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@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.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" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@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.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" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@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.7.0" + graceful-fs "^4.2.9" + 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.7.0" + semver "^7.5.3" + +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@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.7.0" + string-length "^4.0.1" + jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -4202,11 +5683,39 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4214,6 +5723,38 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.npmmirror.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== + dependencies: + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.2" + decimal.js "^10.4.2" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + ws "^8.11.0" + xml-name-validator "^4.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4246,7 +5787,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.2.2: +json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -4278,6 +5819,11 @@ khroma@^2.0.0: resolved "https://registry.npmmirror.com/khroma/-/khroma-2.0.0.tgz#7577de98aed9f36c7a474c4d453d94c0d6c6588b" integrity sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g== +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmmirror.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + kleur@^4.0.3: version "4.1.5" resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" @@ -4305,6 +5851,11 @@ layout-base@^2.0.0: resolved "https://registry.npmmirror.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -4361,6 +5912,13 @@ loader-runner@^4.2.0: resolved "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -4433,6 +5991,25 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmmirror.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmmirror.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + markdown-table@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.3.tgz#e6331d30e493127e031dd385488b5bd326e4a6bd" @@ -4937,7 +6514,7 @@ mime-db@1.52.0: resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.27: +mime-types@^2.1.12, mime-types@^2.1.27: version "2.1.35" resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -4954,6 +6531,11 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -5038,11 +6620,21 @@ node-fetch@^3.3.1: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + node-releases@^2.0.12: version "2.0.12" resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + node-releases@^2.0.8: version "2.0.10" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" @@ -5058,6 +6650,13 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + npm-run-path@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" @@ -5072,6 +6671,11 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +nwsapi@^2.2.2: + version "2.2.12" + resolved "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" + integrity sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w== + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5147,7 +6751,7 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.0: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -5173,13 +6777,27 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -p-limit@^3.0.2: +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -5194,6 +6812,11 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5201,7 +6824,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -5211,7 +6834,7 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse5@^7.0.0: +parse5@^7.0.0, parse5@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== @@ -5228,7 +6851,7 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -5253,7 +6876,12 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -5263,6 +6891,18 @@ pidtree@^0.6.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.npmmirror.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + postcss@8.4.31: version "8.4.31" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" @@ -5289,6 +6929,23 @@ prettier@^3.0.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.2.tgz#78fcecd6d870551aa5547437cdae39d4701dca5b" integrity sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ== +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.npmmirror.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.npmmirror.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + prop-types@^15.0.0, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -5303,11 +6960,31 @@ property-information@^6.0.0: resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.npmmirror.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.1.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.npmmirror.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5405,6 +7082,14 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + redux@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" @@ -5540,16 +7225,38 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-pkg-maps@^1.0.0: version "1.0.0" resolved "https://registry.npmmirror.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.npmmirror.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + resolve@^1.14.2, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -5559,6 +7266,15 @@ resolve@^1.14.2, resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + resolve@^2.0.0-next.4: version "2.0.0-next.4" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" @@ -5659,6 +7375,13 @@ sass@^1.59.2: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -5675,11 +7398,16 @@ schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: +semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== +semver@^7.5.3: + version "7.6.3" + resolved "https://registry.npmmirror.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -5720,11 +7448,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.2, signal-exit@^3.0.7: +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -5766,6 +7499,14 @@ slice-ansi@^5.0.0: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -5774,7 +7515,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5794,11 +7535,23 @@ spawn-command@0.0.2: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.npmmirror.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -5816,6 +7569,14 @@ string-argv@^0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.npmmirror.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -5894,11 +7655,28 @@ strip-bom@^3.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-final-newline@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -5967,6 +7745,11 @@ svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + synckit@^0.8.5, synckit@^0.8.6: version "0.8.8" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" @@ -6001,6 +7784,15 @@ terser@^5.16.8: commander "^2.20.0" source-map-support "~0.5.20" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -6021,6 +7813,11 @@ tiny-invariant@^1.0.6: resolved "https://registry.npmmirror.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -6033,6 +7830,23 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@^4.1.2: + version "4.1.4" + resolved "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -6058,6 +7872,25 @@ ts-dedent@^2.2.0: resolved "https://registry.npmmirror.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.npmmirror.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tsconfig-paths@^3.14.1: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" @@ -6095,6 +7928,11 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.npmmirror.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -6229,6 +8067,11 @@ unist-util-visit@^4.0.0: unist-util-is "^5.0.0" unist-util-visit-parents "^5.1.1" +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + update-browserslist-db@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" @@ -6245,6 +8088,14 @@ update-browserslist-db@^1.0.11: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -6252,6 +8103,14 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + use-debounce@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/use-debounce/-/use-debounce-9.0.4.tgz#51d25d856fbdfeb537553972ce3943b897f1ac85" @@ -6282,6 +8141,20 @@ uvu@^0.5.0: kleur "^4.0.3" sade "^1.7.3" +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.npmmirror.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + vfile-location@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.1.0.tgz#69df82fb9ef0a38d0d02b90dd84620e120050dd0" @@ -6308,6 +8181,20 @@ vfile@^5.0.0: unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== + dependencies: + xml-name-validator "^4.0.0" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + watch@^1.0.2: version "1.0.2" resolved "https://registry.npmmirror.com/watch/-/watch-1.0.2.tgz#340a717bde765726fa0aa07d721e0147a551df0c" @@ -6339,6 +8226,11 @@ web-worker@^1.2.0: resolved "https://registry.npmmirror.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da" integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" @@ -6374,6 +8266,26 @@ webpack@^5.88.1: watchpack "^2.4.0" webpack-sources "^3.2.3" +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -6437,6 +8349,29 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.npmmirror.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +ws@^8.11.0: + version "8.18.0" + resolved "https://registry.npmmirror.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -6467,7 +8402,7 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^17.7.2: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -6480,6 +8415,11 @@ yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 1287e39cc65d1e0339ec39afbccd8d4526bee9d9 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Tue, 6 Aug 2024 19:24:47 +0800 Subject: [PATCH 02/65] feat: run test before build --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 91be0544e00..3945a203f54 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,13 @@ "mask": "npx tsx app/masks/build.ts", "mask:watch": "npx watch \"yarn mask\" app/masks", "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", - "build": "yarn mask && cross-env BUILD_MODE=standalone next build", + "build": "yarn test:ci && yarn mask && cross-env BUILD_MODE=standalone next build", "start": "next start", "lint": "next lint", - "export": "yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", + "export": "yarn test:ci && yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", - "app:build": "yarn mask && yarn tauri build", + "app:build": "yarn test:ci && yarn mask && yarn tauri build", "prompts": "node ./scripts/fetch-prompts.mjs", "prepare": "husky install", "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev", @@ -81,4 +81,4 @@ "lint-staged/yaml": "^2.2.2" }, "packageManager": "yarn@1.22.19" -} +} \ No newline at end of file From d84d51b475a1a6ad18efed46121af9adbc7b98f3 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Sat, 28 Sep 2024 01:19:39 +0800 Subject: [PATCH 03/65] using sse: schema to fetch in App --- app/utils.ts | 51 +++++++++++++++++-------- src-tauri/Cargo.lock | 86 +++++++++++++++++++++++++++++++------------ src-tauri/Cargo.toml | 4 ++ src-tauri/src/main.rs | 48 ++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 40 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 9a8bebf38c7..5be7bb2d9f7 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -2,8 +2,7 @@ import { useEffect, useState } from "react"; import { showToast } from "./components/ui-lib"; import Locale from "./locales"; import { RequestMessage } from "./client/api"; -import { ServiceProvider, REQUEST_TIMEOUT_MS } from "./constant"; -import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; +import { ServiceProvider } from "./constant"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -292,30 +291,50 @@ export function fetch( options?: Record, ): Promise { if (window.__TAURI__) { - const payload = options?.body || options?.data; - return tauriFetch(url, { - ...options, - body: - payload && - ({ - type: "Text", - payload, - } as any), - timeout: ((options?.timeout as number) || REQUEST_TIMEOUT_MS) / 1000, - responseType: - options?.responseType == "text" ? ResponseType.Text : ResponseType.JSON, - } as any); + const tauriUri = window.__TAURI__.convertFileSrc(url, "sse"); + return window.fetch(tauriUri, options).then((r) => { + // 1. create response, + // TODO using event to get status and statusText and headers + const { status, statusText } = r; + const { readable, writable } = new TransformStream(); + const res = new Response(readable, { status, statusText }); + // 2. call fetch_read_body multi times, and write to Response.body + const writer = writable.getWriter(); + let unlisten; + window.__TAURI__.event + .listen("sse-response", (e) => { + const { id, payload } = e; + console.log("event", id, payload); + writer.ready.then(() => { + if (payload !== 0) { + writer.write(new Uint8Array(payload)); + } else { + writer.releaseLock(); + writable.close(); + unlisten && unlisten(); + } + }); + }) + .then((u) => (unlisten = u)); + return res; + }); } return window.fetch(url, options); } +if (undefined !== window) { + window.tauriFetch = fetch; +} + export function adapter(config: Record) { const { baseURL, url, params, ...rest } = config; const path = baseURL ? `${baseURL}${url}` : url; const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, { ...rest, responseType: "text" }); + return fetch(fetchUrl as string, rest) + .then((res) => res.text()) + .then((data) => ({ data })); } export function safeLocalStorage(): { diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 47d12e1190b..fcc06d163cd 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -348,9 +348,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] @@ -942,9 +942,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -970,9 +970,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" @@ -987,9 +987,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1008,9 +1008,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -1019,21 +1019,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-io", @@ -1555,9 +1555,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1986,6 +1986,9 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" name = "nextchat" version = "0.1.0" dependencies = [ + "futures-util", + "percent-encoding", + "reqwest", "serde", "serde_json", "tauri", @@ -2213,6 +2216,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "os_info" +version = "3.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +dependencies = [ + "log", + "serde", + "windows-sys 0.52.0", +] + [[package]] name = "overload" version = "0.1.1" @@ -2281,9 +2295,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -2545,9 +2559,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.58" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -3237,6 +3251,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sys-locale" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" +dependencies = [ + "js-sys", + "libc", + "wasm-bindgen", + "web-sys", + "windows-sys 0.45.0", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3385,6 +3412,7 @@ dependencies = [ "objc", "once_cell", "open", + "os_info", "percent-encoding", "rand 0.8.5", "raw-window-handle", @@ -3397,6 +3425,7 @@ dependencies = [ "serde_repr", "serialize-to-javascript", "state", + "sys-locale", "tar", "tauri-macros", "tauri-runtime", @@ -3889,9 +3918,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "url" -version = "2.3.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -4316,6 +4345,15 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 387584491ba..31ecfd83e4d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,8 +35,12 @@ tauri = { version = "1.5.4", features = [ "http-all", "window-start-dragging", "window-unmaximize", "window-unminimize", + "linux-protocol-headers", ] } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } +percent-encoding = "2.3.1" +reqwest = "0.11.18" +futures-util = "0.3.30" [features] # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index ed3ec32f37b..792c656cf51 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,9 +1,57 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use futures_util::{StreamExt}; +use reqwest::Client; +use tauri::{ Manager}; +use tauri::http::{ResponseBuilder}; + fn main() { tauri::Builder::default() .plugin(tauri_plugin_window_state::Builder::default().build()) + .register_uri_scheme_protocol("sse", |app_handle, request| { + let path = request.uri().strip_prefix("sse://localhost/").unwrap(); + let path = percent_encoding::percent_decode(path.as_bytes()) + .decode_utf8_lossy() + .to_string(); + // println!("path : {}", path); + let client = Client::new(); + let window = app_handle.get_window("main").unwrap(); + // send http request + let body = reqwest::Body::from(request.body().clone()); + let response_future = client.request(request.method().clone(), path) + .headers(request.headers().clone()) + .body(body).send(); + + // get response and emit to client + tauri::async_runtime::spawn(async move { + let res = response_future.await; + + match res { + Ok(res) => { + let mut stream = res.bytes_stream(); + + while let Some(chunk) = stream.next().await { + match chunk { + Ok(bytes) => { + window.emit("sse-response", bytes).unwrap(); + } + Err(err) => { + println!("Error: {:?}", err); + } + } + } + window.emit("sse-response", 0).unwrap(); + } + Err(err) => { + println!("Error: {:?}", err); + } + } + }); + ResponseBuilder::new() + .header("Access-Control-Allow-Origin", "*") + .status(200).body("OK".into()) + }) .run(tauri::generate_context!()) .expect("error while running tauri application"); } From 2d920f7ccc7bed1ed06cdb52e0ef50f96f8100ac Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Sat, 28 Sep 2024 15:05:41 +0800 Subject: [PATCH 04/65] using stream: schema to fetch in App --- app/global.d.ts | 1 + app/utils.ts | 41 +--------------- app/utils/stream.ts | 100 ++++++++++++++++++++++++++++++++++++++++ src-tauri/Cargo.lock | 36 +-------------- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 51 ++------------------ src-tauri/src/stream.rs | 96 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 204 insertions(+), 122 deletions(-) create mode 100644 app/utils/stream.ts create mode 100644 src-tauri/src/stream.rs diff --git a/app/global.d.ts b/app/global.d.ts index 8ee636bcd3c..a1453dc33b4 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -12,6 +12,7 @@ declare module "*.svg"; declare interface Window { __TAURI__?: { + convertFileSrc(url: string, protocol?: string): string; writeText(text: string): Promise; invoke(command: string, payload?: Record): Promise; dialog: { diff --git a/app/utils.ts b/app/utils.ts index 5be7bb2d9f7..fbe77c114c5 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -3,6 +3,7 @@ import { showToast } from "./components/ui-lib"; import Locale from "./locales"; import { RequestMessage } from "./client/api"; import { ServiceProvider } from "./constant"; +import { fetch } from "./utils/stream"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -286,46 +287,6 @@ export function showPlugins(provider: ServiceProvider, model: string) { return false; } -export function fetch( - url: string, - options?: Record, -): Promise { - if (window.__TAURI__) { - const tauriUri = window.__TAURI__.convertFileSrc(url, "sse"); - return window.fetch(tauriUri, options).then((r) => { - // 1. create response, - // TODO using event to get status and statusText and headers - const { status, statusText } = r; - const { readable, writable } = new TransformStream(); - const res = new Response(readable, { status, statusText }); - // 2. call fetch_read_body multi times, and write to Response.body - const writer = writable.getWriter(); - let unlisten; - window.__TAURI__.event - .listen("sse-response", (e) => { - const { id, payload } = e; - console.log("event", id, payload); - writer.ready.then(() => { - if (payload !== 0) { - writer.write(new Uint8Array(payload)); - } else { - writer.releaseLock(); - writable.close(); - unlisten && unlisten(); - } - }); - }) - .then((u) => (unlisten = u)); - return res; - }); - } - return window.fetch(url, options); -} - -if (undefined !== window) { - window.tauriFetch = fetch; -} - export function adapter(config: Record) { const { baseURL, url, params, ...rest } = config; const path = baseURL ? `${baseURL}${url}` : url; diff --git a/app/utils/stream.ts b/app/utils/stream.ts new file mode 100644 index 00000000000..8f9ccfbaa1d --- /dev/null +++ b/app/utils/stream.ts @@ -0,0 +1,100 @@ +// using tauri register_uri_scheme_protocol, register `stream:` protocol +// see src-tauri/src/stream.rs, and src-tauri/src/main.rs +// 1. window.fetch(`stream://localhost/${fetchUrl}`), get request_id +// 2. listen event: `stream-response` multi times to get response headers and body + +type ResponseEvent = { + id: number; + payload: { + request_id: number; + status?: number; + error?: string; + name?: string; + value?: string; + chunk?: number[]; + }; +}; + +export function fetch(url: string, options?: RequestInit): Promise { + if (window.__TAURI__) { + const tauriUri = window.__TAURI__.convertFileSrc(url, "stream"); + const { signal, ...rest } = options || {}; + return window + .fetch(tauriUri, rest) + .then((r) => r.text()) + .then((rid) => parseInt(rid)) + .then((request_id: number) => { + // 1. using event to get status and statusText and headers, and resolve it + let resolve: Function | undefined; + let reject: Function | undefined; + let status: number; + let writable: WritableStream | undefined; + let writer: WritableStreamDefaultWriter | undefined; + const headers = new Headers(); + let unlisten: Function | undefined; + + if (signal) { + signal.addEventListener("abort", () => { + // Reject the promise with the abort reason. + unlisten && unlisten(); + reject && reject(signal.reason); + }); + } + // @ts-ignore 2. listen response multi times, and write to Response.body + window.__TAURI__.event + .listen("stream-response", (e: ResponseEvent) => { + const { id, payload } = e; + const { + request_id: rid, + status: _status, + name, + value, + error, + chunk, + } = payload; + if (request_id != rid) { + return; + } + /** + * 1. get status code + * 2. get headers + * 3. start get body, then resolve response + * 4. get body chunk + */ + if (error) { + unlisten && unlisten(); + return reject && reject(error); + } else if (_status) { + status = _status; + } else if (name && value) { + headers.append(name, value); + } else if (chunk) { + if (resolve) { + const ts = new TransformStream(); + writable = ts.writable; + writer = writable.getWriter(); + resolve(new Response(ts.readable, { status, headers })); + resolve = undefined; + } + writer && + writer.ready.then(() => { + writer && writer.write(new Uint8Array(chunk)); + }); + } else if (_status === 0) { + // end of body + unlisten && unlisten(); + writer && + writer.ready.then(() => { + writer && writer.releaseLock(); + writable && writable.close(); + }); + } + }) + .then((u: Function) => (unlisten = u)); + return new Promise( + (_resolve, _reject) => ([resolve, reject] = [_resolve, _reject]), + ); + }); + } + return window.fetch(url, options); +} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fcc06d163cd..c9baffc0acc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1986,6 +1986,7 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" name = "nextchat" version = "0.1.0" dependencies = [ + "bytes", "futures-util", "percent-encoding", "reqwest", @@ -2216,17 +2217,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "os_info" -version = "3.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" -dependencies = [ - "log", - "serde", - "windows-sys 0.52.0", -] - [[package]] name = "overload" version = "0.1.1" @@ -3251,19 +3241,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sys-locale" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" -dependencies = [ - "js-sys", - "libc", - "wasm-bindgen", - "web-sys", - "windows-sys 0.45.0", -] - [[package]] name = "system-configuration" version = "0.5.1" @@ -3412,7 +3389,6 @@ dependencies = [ "objc", "once_cell", "open", - "os_info", "percent-encoding", "rand 0.8.5", "raw-window-handle", @@ -3425,7 +3401,6 @@ dependencies = [ "serde_repr", "serialize-to-javascript", "state", - "sys-locale", "tar", "tauri-macros", "tauri-runtime", @@ -4345,15 +4320,6 @@ dependencies = [ "windows-targets 0.48.0", ] -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - [[package]] name = "windows-targets" version = "0.42.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 31ecfd83e4d..c954deb72a8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -41,6 +41,7 @@ tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-works percent-encoding = "2.3.1" reqwest = "0.11.18" futures-util = "0.3.30" +bytes = "1.7.2" [features] # this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled. diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 792c656cf51..e382082572f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,57 +1,14 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use futures_util::{StreamExt}; -use reqwest::Client; -use tauri::{ Manager}; -use tauri::http::{ResponseBuilder}; +mod stream; fn main() { tauri::Builder::default() .plugin(tauri_plugin_window_state::Builder::default().build()) - .register_uri_scheme_protocol("sse", |app_handle, request| { - let path = request.uri().strip_prefix("sse://localhost/").unwrap(); - let path = percent_encoding::percent_decode(path.as_bytes()) - .decode_utf8_lossy() - .to_string(); - // println!("path : {}", path); - let client = Client::new(); - let window = app_handle.get_window("main").unwrap(); - // send http request - let body = reqwest::Body::from(request.body().clone()); - let response_future = client.request(request.method().clone(), path) - .headers(request.headers().clone()) - .body(body).send(); - - // get response and emit to client - tauri::async_runtime::spawn(async move { - let res = response_future.await; - - match res { - Ok(res) => { - let mut stream = res.bytes_stream(); - - while let Some(chunk) = stream.next().await { - match chunk { - Ok(bytes) => { - window.emit("sse-response", bytes).unwrap(); - } - Err(err) => { - println!("Error: {:?}", err); - } - } - } - window.emit("sse-response", 0).unwrap(); - } - Err(err) => { - println!("Error: {:?}", err); - } - } - }); - ResponseBuilder::new() - .header("Access-Control-Allow-Origin", "*") - .status(200).body("OK".into()) - }) + .register_uri_scheme_protocol("stream", move |app_handle, request| { + stream::stream(app_handle, request) + }) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs new file mode 100644 index 00000000000..5e84e0f00d1 --- /dev/null +++ b/src-tauri/src/stream.rs @@ -0,0 +1,96 @@ + +use std::error::Error; +use futures_util::{StreamExt}; +use reqwest::Client; +use tauri::{ Manager, AppHandle }; +use tauri::http::{Request, ResponseBuilder}; +use tauri::http::Response; + +static mut REQUEST_COUNTER: u32 = 0; + +#[derive(Clone, serde::Serialize)] +pub struct ErrorPayload { + request_id: u32, + error: String, +} + +#[derive(Clone, serde::Serialize)] +pub struct StatusPayload { + request_id: u32, + status: u16, +} + +#[derive(Clone, serde::Serialize)] +pub struct HeaderPayload { + request_id: u32, + name: String, + value: String, +} + +#[derive(Clone, serde::Serialize)] +pub struct ChunkPayload { + request_id: u32, + chunk: bytes::Bytes, +} + +pub fn stream(app_handle: &AppHandle, request: &Request) -> Result> { + let mut request_id = 0; + let event_name = "stream-response"; + unsafe { + REQUEST_COUNTER += 1; + request_id = REQUEST_COUNTER; + } + let path = request.uri().to_string().replace("stream://localhost/", "").replace("http://stream.localhost/", ""); + let path = percent_encoding::percent_decode(path.as_bytes()) + .decode_utf8_lossy() + .to_string(); + // println!("path : {}", path); + let client = Client::new(); + let handle = app_handle.app_handle(); + // send http request + let body = reqwest::Body::from(request.body().clone()); + let response_future = client.request(request.method().clone(), path) + .headers(request.headers().clone()) + .body(body).send(); + + // get response and emit to client + tauri::async_runtime::spawn(async move { + let res = response_future.await; + + match res { + Ok(res) => { + handle.emit_all(event_name, StatusPayload{ request_id, status: res.status().as_u16() }).unwrap(); + for (name, value) in res.headers() { + handle.emit_all(event_name, HeaderPayload { + request_id, + name: name.to_string(), + value: std::str::from_utf8(value.as_bytes()).unwrap().to_string() + }).unwrap(); + } + let mut stream = res.bytes_stream(); + + while let Some(chunk) = stream.next().await { + match chunk { + Ok(bytes) => { + handle.emit_all(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); + } + Err(err) => { + println!("Error: {:?}", err); + } + } + } + handle.emit_all(event_name, StatusPayload { request_id, status: 0 }).unwrap(); + } + Err(err) => { + println!("Error: {:?}", err.source().expect("REASON").to_string()); + handle.emit_all(event_name, ErrorPayload { + request_id, + error: err.source().expect("REASON").to_string() + }).unwrap(); + } + } + }); + return ResponseBuilder::new() + .header("Access-Control-Allow-Origin", "*") + .status(200).body(request_id.to_string().into()) +} From 3898c507c466c13537330fd6feb7b960e330c774 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Sun, 29 Sep 2024 19:44:09 +0800 Subject: [PATCH 05/65] using stream_fetch in App --- app/utils.ts | 8 ++- app/utils/chat.ts | 2 + app/utils/stream.ts | 152 +++++++++++++++++++--------------------- src-tauri/src/main.rs | 4 +- src-tauri/src/stream.rs | 127 +++++++++++++++++++-------------- 5 files changed, 156 insertions(+), 137 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index fbe77c114c5..baf45abe573 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -288,12 +288,16 @@ export function showPlugins(provider: ServiceProvider, model: string) { } export function adapter(config: Record) { - const { baseURL, url, params, ...rest } = config; + const { baseURL, url, params, method, data, ...rest } = config; const path = baseURL ? `${baseURL}${url}` : url; const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, rest) + return fetch(fetchUrl as string, { + ...rest, + method, + body: method.toUpperCase() == "GET" ? undefined : data, + }) .then((res) => res.text()) .then((data) => ({ data })); } diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 7f3bb23c58e..359b2c53ebc 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -10,6 +10,7 @@ import { fetchEventSource, } from "@fortaine/fetch-event-source"; import { prettyObject } from "./format"; +import { fetch as tauriFetch } from "./stream"; export function compressImage(file: Blob, maxSize: number): Promise { return new Promise((resolve, reject) => { @@ -287,6 +288,7 @@ export function stream( REQUEST_TIMEOUT_MS, ); fetchEventSource(chatPath, { + fetch: tauriFetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/utils/stream.ts b/app/utils/stream.ts index 8f9ccfbaa1d..09b898431e7 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -1,100 +1,94 @@ -// using tauri register_uri_scheme_protocol, register `stream:` protocol +// using tauri command to send request // see src-tauri/src/stream.rs, and src-tauri/src/main.rs -// 1. window.fetch(`stream://localhost/${fetchUrl}`), get request_id -// 2. listen event: `stream-response` multi times to get response headers and body +// 1. invoke('stream_fetch', {url, method, headers, body}), get response with headers. +// 2. listen event: `stream-response` multi times to get body type ResponseEvent = { id: number; payload: { request_id: number; status?: number; - error?: string; - name?: string; - value?: string; chunk?: number[]; }; }; export function fetch(url: string, options?: RequestInit): Promise { if (window.__TAURI__) { - const tauriUri = window.__TAURI__.convertFileSrc(url, "stream"); - const { signal, ...rest } = options || {}; - return window - .fetch(tauriUri, rest) - .then((r) => r.text()) - .then((rid) => parseInt(rid)) - .then((request_id: number) => { - // 1. using event to get status and statusText and headers, and resolve it - let resolve: Function | undefined; - let reject: Function | undefined; - let status: number; - let writable: WritableStream | undefined; - let writer: WritableStreamDefaultWriter | undefined; - const headers = new Headers(); - let unlisten: Function | undefined; + const { signal, method = "GET", headers = {}, body = [] } = options || {}; + return window.__TAURI__ + .invoke("stream_fetch", { + method, + url, + headers, + // TODO FormData + body: + typeof body === "string" + ? Array.from(new TextEncoder().encode(body)) + : [], + }) + .then( + (res: { + request_id: number; + status: number; + status_text: string; + headers: Record; + }) => { + const { request_id, status, status_text: statusText, headers } = res; + console.log("send request_id", request_id, status, statusText); + let unlisten: Function | undefined; + const ts = new TransformStream(); + const writer = ts.writable.getWriter(); - if (signal) { - signal.addEventListener("abort", () => { - // Reject the promise with the abort reason. + const close = () => { unlisten && unlisten(); - reject && reject(signal.reason); + writer.ready.then(() => { + try { + writer.releaseLock(); + } catch (e) { + console.error(e); + } + ts.writable.close(); + }); + }; + + const response = new Response(ts.readable, { + status, + statusText, + headers, }); - } - // @ts-ignore 2. listen response multi times, and write to Response.body - window.__TAURI__.event - .listen("stream-response", (e: ResponseEvent) => { - const { id, payload } = e; - const { - request_id: rid, - status: _status, - name, - value, - error, - chunk, - } = payload; - if (request_id != rid) { - return; - } - /** - * 1. get status code - * 2. get headers - * 3. start get body, then resolve response - * 4. get body chunk - */ - if (error) { - unlisten && unlisten(); - return reject && reject(error); - } else if (_status) { - status = _status; - } else if (name && value) { - headers.append(name, value); - } else if (chunk) { - if (resolve) { - const ts = new TransformStream(); - writable = ts.writable; - writer = writable.getWriter(); - resolve(new Response(ts.readable, { status, headers })); - resolve = undefined; + if (signal) { + signal.addEventListener("abort", () => close()); + } + // @ts-ignore 2. listen response multi times, and write to Response.body + window.__TAURI__.event + .listen("stream-response", (e: ResponseEvent) => { + const { id, payload } = e; + const { request_id: rid, chunk, status } = payload; + if (request_id != rid) { + return; + } + if (chunk) { + writer && + writer.ready.then(() => { + writer && writer.write(new Uint8Array(chunk)); + }); + } else if (status === 0) { + // end of body + close(); } - writer && - writer.ready.then(() => { - writer && writer.write(new Uint8Array(chunk)); - }); - } else if (_status === 0) { - // end of body - unlisten && unlisten(); - writer && - writer.ready.then(() => { - writer && writer.releaseLock(); - writable && writable.close(); - }); - } - }) - .then((u: Function) => (unlisten = u)); - return new Promise( - (_resolve, _reject) => ([resolve, reject] = [_resolve, _reject]), - ); + }) + .then((u: Function) => (unlisten = u)); + return response; + }, + ) + .catch((e) => { + console.error("stream error", e); + throw e; }); } return window.fetch(url, options); } + +if (undefined !== window) { + window.tauriFetch = fetch; +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e382082572f..d04969c043b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,10 +5,8 @@ mod stream; fn main() { tauri::Builder::default() + .invoke_handler(tauri::generate_handler![stream::stream_fetch]) .plugin(tauri_plugin_window_state::Builder::default().build()) - .register_uri_scheme_protocol("stream", move |app_handle, request| { - stream::stream(app_handle, request) - }) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 5e84e0f00d1..514e6229803 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -1,30 +1,25 @@ +// +// use std::error::Error; use futures_util::{StreamExt}; use reqwest::Client; -use tauri::{ Manager, AppHandle }; -use tauri::http::{Request, ResponseBuilder}; -use tauri::http::Response; +use reqwest::header::{HeaderName, HeaderMap}; static mut REQUEST_COUNTER: u32 = 0; #[derive(Clone, serde::Serialize)] -pub struct ErrorPayload { - request_id: u32, - error: String, -} - -#[derive(Clone, serde::Serialize)] -pub struct StatusPayload { +pub struct StreamResponse { request_id: u32, status: u16, + status_text: String, + headers: HashMap } #[derive(Clone, serde::Serialize)] -pub struct HeaderPayload { +pub struct EndPayload { request_id: u32, - name: String, - value: String, + status: u16, } #[derive(Clone, serde::Serialize)] @@ -33,64 +28,90 @@ pub struct ChunkPayload { chunk: bytes::Bytes, } -pub fn stream(app_handle: &AppHandle, request: &Request) -> Result> { +use std::collections::HashMap; + +#[derive(serde::Serialize)] +pub struct CustomResponse { + message: String, + other_val: usize, +} + +#[tauri::command] +pub async fn stream_fetch( + window: tauri::Window, + method: String, + url: String, + headers: HashMap, + body: Vec, +) -> Result { + let mut request_id = 0; let event_name = "stream-response"; unsafe { REQUEST_COUNTER += 1; request_id = REQUEST_COUNTER; } - let path = request.uri().to_string().replace("stream://localhost/", "").replace("http://stream.localhost/", ""); - let path = percent_encoding::percent_decode(path.as_bytes()) - .decode_utf8_lossy() - .to_string(); - // println!("path : {}", path); - let client = Client::new(); - let handle = app_handle.app_handle(); - // send http request - let body = reqwest::Body::from(request.body().clone()); - let response_future = client.request(request.method().clone(), path) - .headers(request.headers().clone()) - .body(body).send(); - - // get response and emit to client - tauri::async_runtime::spawn(async move { - let res = response_future.await; - - match res { - Ok(res) => { - handle.emit_all(event_name, StatusPayload{ request_id, status: res.status().as_u16() }).unwrap(); - for (name, value) in res.headers() { - handle.emit_all(event_name, HeaderPayload { - request_id, - name: name.to_string(), - value: std::str::from_utf8(value.as_bytes()).unwrap().to_string() - }).unwrap(); - } + + let mut _headers = HeaderMap::new(); + for (key, value) in headers { + _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); + } + let body = bytes::Bytes::from(body); + + let response_future = Client::new().request( + method.parse::().map_err(|err| format!("failed to parse method: {}", err))?, + url.parse::().map_err(|err| format!("failed to parse url: {}", err))? + ).headers(_headers).body(body).send(); + + let res = response_future.await; + let response = match res { + Ok(res) => { + println!("Error: {:?}", res); + // get response and emit to client + // .register_uri_scheme_protocol("stream", move |app_handle, request| { + let mut headers = HashMap::new(); + for (name, value) in res.headers() { + headers.insert( + name.as_str().to_string(), + std::str::from_utf8(value.as_bytes()).unwrap().to_string() + ); + } + let status = res.status().as_u16(); + + tauri::async_runtime::spawn(async move { let mut stream = res.bytes_stream(); while let Some(chunk) = stream.next().await { match chunk { Ok(bytes) => { - handle.emit_all(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); + println!("chunk: {:?}", bytes); + window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); } Err(err) => { println!("Error: {:?}", err); } } } - handle.emit_all(event_name, StatusPayload { request_id, status: 0 }).unwrap(); + window.emit(event_name, EndPayload { request_id, status: 0 }).unwrap(); + }); + + StreamResponse { + request_id, + status, + status_text: "OK".to_string(), + headers, } - Err(err) => { - println!("Error: {:?}", err.source().expect("REASON").to_string()); - handle.emit_all(event_name, ErrorPayload { - request_id, - error: err.source().expect("REASON").to_string() - }).unwrap(); + } + Err(err) => { + println!("Error: {:?}", err.source().expect("REASON").to_string()); + StreamResponse { + request_id, + status: 599, + status_text: err.source().expect("REASON").to_string(), + headers: HashMap::new(), } } - }); - return ResponseBuilder::new() - .header("Access-Control-Allow-Origin", "*") - .status(200).body(request_id.to_string().into()) + }; + Ok(response) } + From 9e6ee50fa6335fe9c405b69e09bb7b6046aff42c Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Sun, 29 Sep 2024 20:32:36 +0800 Subject: [PATCH 06/65] using stream_fetch in App --- app/utils/stream.ts | 110 +++++++++++++++++++--------------------- src-tauri/src/stream.rs | 4 +- 2 files changed, 52 insertions(+), 62 deletions(-) diff --git a/app/utils/stream.ts b/app/utils/stream.ts index 09b898431e7..f8c272e4296 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -12,9 +12,55 @@ type ResponseEvent = { }; }; +type StreamResponse = { + request_id: number; + status: number; + status_text: string; + headers: Record; +}; + export function fetch(url: string, options?: RequestInit): Promise { if (window.__TAURI__) { const { signal, method = "GET", headers = {}, body = [] } = options || {}; + let unlisten: Function | undefined; + let request_id = 0; + const ts = new TransformStream(); + const writer = ts.writable.getWriter(); + + const close = () => { + unlisten && unlisten(); + writer.ready.then(() => { + try { + writer.releaseLock(); + } catch (e) { + console.error(e); + } + ts.writable.close(); + }); + }; + + if (signal) { + signal.addEventListener("abort", () => close()); + } + // @ts-ignore 2. listen response multi times, and write to Response.body + window.__TAURI__.event + .listen("stream-response", (e: ResponseEvent) => { + const { request_id: rid, chunk, status } = e?.payload || {}; + if (request_id != rid) { + return; + } + if (chunk) { + writer && + writer.ready.then(() => { + writer && writer.write(new Uint8Array(chunk)); + }); + } else if (status === 0) { + // end of body + close(); + } + }) + .then((u: Function) => (unlisten = u)); + return window.__TAURI__ .invoke("stream_fetch", { method, @@ -26,61 +72,11 @@ export function fetch(url: string, options?: RequestInit): Promise { ? Array.from(new TextEncoder().encode(body)) : [], }) - .then( - (res: { - request_id: number; - status: number; - status_text: string; - headers: Record; - }) => { - const { request_id, status, status_text: statusText, headers } = res; - console.log("send request_id", request_id, status, statusText); - let unlisten: Function | undefined; - const ts = new TransformStream(); - const writer = ts.writable.getWriter(); - - const close = () => { - unlisten && unlisten(); - writer.ready.then(() => { - try { - writer.releaseLock(); - } catch (e) { - console.error(e); - } - ts.writable.close(); - }); - }; - - const response = new Response(ts.readable, { - status, - statusText, - headers, - }); - if (signal) { - signal.addEventListener("abort", () => close()); - } - // @ts-ignore 2. listen response multi times, and write to Response.body - window.__TAURI__.event - .listen("stream-response", (e: ResponseEvent) => { - const { id, payload } = e; - const { request_id: rid, chunk, status } = payload; - if (request_id != rid) { - return; - } - if (chunk) { - writer && - writer.ready.then(() => { - writer && writer.write(new Uint8Array(chunk)); - }); - } else if (status === 0) { - // end of body - close(); - } - }) - .then((u: Function) => (unlisten = u)); - return response; - }, - ) + .then((res: StreamResponse) => { + request_id = res.request_id; + const { status, status_text: statusText, headers } = res; + return new Response(ts.readable, { status, statusText, headers }); + }) .catch((e) => { console.error("stream error", e); throw e; @@ -88,7 +84,3 @@ export function fetch(url: string, options?: RequestInit): Promise { } return window.fetch(url, options); } - -if (undefined !== window) { - window.tauriFetch = fetch; -} diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 514e6229803..81710c73346 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -66,9 +66,7 @@ pub async fn stream_fetch( let res = response_future.await; let response = match res { Ok(res) => { - println!("Error: {:?}", res); // get response and emit to client - // .register_uri_scheme_protocol("stream", move |app_handle, request| { let mut headers = HashMap::new(); for (name, value) in res.headers() { headers.insert( @@ -84,7 +82,7 @@ pub async fn stream_fetch( while let Some(chunk) = stream.next().await { match chunk { Ok(bytes) => { - println!("chunk: {:?}", bytes); + // println!("chunk: {:?}", bytes); window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); } Err(err) => { From f9d410517030259434c26f7443bacdc32568682b Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Sun, 29 Sep 2024 21:47:38 +0800 Subject: [PATCH 07/65] stash code --- app/utils/stream.ts | 22 ++++++++++++++++++++-- src-tauri/src/stream.rs | 30 ++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/app/utils/stream.ts b/app/utils/stream.ts index f8c272e4296..dd665e71c75 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -21,7 +21,12 @@ type StreamResponse = { export function fetch(url: string, options?: RequestInit): Promise { if (window.__TAURI__) { - const { signal, method = "GET", headers = {}, body = [] } = options || {}; + const { + signal, + method = "GET", + headers: _headers = {}, + body = [], + } = options || {}; let unlisten: Function | undefined; let request_id = 0; const ts = new TransformStream(); @@ -32,10 +37,10 @@ export function fetch(url: string, options?: RequestInit): Promise { writer.ready.then(() => { try { writer.releaseLock(); + ts.writable.close(); } catch (e) { console.error(e); } - ts.writable.close(); }); }; @@ -61,6 +66,19 @@ export function fetch(url: string, options?: RequestInit): Promise { }) .then((u: Function) => (unlisten = u)); + const headers = { + Accept: "*", + Connection: "close", + Origin: "http://localhost:3000", + Referer: "http://localhost:3000/", + "Sec-Fetch-Dest": "empty", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Site": "cross-site", + "User-Agent": navigator.userAgent, + }; + for (const item of new Headers(_headers || {})) { + headers[item[0]] = item[1]; + } return window.__TAURI__ .invoke("stream_fetch", { method, diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 81710c73346..97989ba7e4f 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -53,15 +53,33 @@ pub async fn stream_fetch( } let mut _headers = HeaderMap::new(); - for (key, value) in headers { - _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); + for (key, value) in &headers { + _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); } - let body = bytes::Bytes::from(body); - let response_future = Client::new().request( - method.parse::().map_err(|err| format!("failed to parse method: {}", err))?, + println!("method: {:?}", method); + println!("url: {:?}", url); + println!("headers: {:?}", headers); + println!("headers: {:?}", _headers); + + let method = method.parse::().map_err(|err| format!("failed to parse method: {}", err))?; + let client = Client::builder() + .user_agent("Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15") + .default_headers(_headers) + .build() + .map_err(|err| format!("failed to generate client: {}", err))?; + + let mut request = client.request( + method.clone(), url.parse::().map_err(|err| format!("failed to parse url: {}", err))? - ).headers(_headers).body(body).send(); + ); + + if method == reqwest::Method::POST { + let body = bytes::Bytes::from(body); + println!("body: {:?}", body); + request = request.body(body); + } + let response_future = request.send(); let res = response_future.await; let response = match res { From b5f6e5a5989a36ecb1b5f2b37209f2d4bffc607b Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 00:38:30 +0800 Subject: [PATCH 08/65] update --- app/store/plugin.ts | 2 +- app/utils/stream.ts | 28 ++++++++++------------------ src-tauri/src/stream.rs | 8 +++++--- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/app/store/plugin.ts b/app/store/plugin.ts index 40abdc8d9f4..b3d9f6d8ce6 100644 --- a/app/store/plugin.ts +++ b/app/store/plugin.ts @@ -7,7 +7,7 @@ import yaml from "js-yaml"; import { adapter, getOperationId } from "../utils"; import { useAccessStore } from "./access"; -const isApp = getClientConfig()?.isApp; +const isApp = getClientConfig()?.isApp !== false; export type Plugin = { id: string; diff --git a/app/utils/stream.ts b/app/utils/stream.ts index dd665e71c75..625ecea1f22 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -32,15 +32,13 @@ export function fetch(url: string, options?: RequestInit): Promise { const ts = new TransformStream(); const writer = ts.writable.getWriter(); + let closed = false; const close = () => { + if (closed) return; + closed = true; unlisten && unlisten(); writer.ready.then(() => { - try { - writer.releaseLock(); - ts.writable.close(); - } catch (e) { - console.error(e); - } + writer.close().catch((e) => console.error(e)); }); }; @@ -55,10 +53,9 @@ export function fetch(url: string, options?: RequestInit): Promise { return; } if (chunk) { - writer && - writer.ready.then(() => { - writer && writer.write(new Uint8Array(chunk)); - }); + writer.ready.then(() => { + writer.write(new Uint8Array(chunk)); + }); } else if (status === 0) { // end of body close(); @@ -67,13 +64,8 @@ export function fetch(url: string, options?: RequestInit): Promise { .then((u: Function) => (unlisten = u)); const headers = { - Accept: "*", - Connection: "close", - Origin: "http://localhost:3000", - Referer: "http://localhost:3000/", - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "cross-site", + Accept: "application/json, text/plain, */*", + "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", "User-Agent": navigator.userAgent, }; for (const item of new Headers(_headers || {})) { @@ -81,7 +73,7 @@ export function fetch(url: string, options?: RequestInit): Promise { } return window.__TAURI__ .invoke("stream_fetch", { - method, + method: method.toUpperCase(), url, headers, // TODO FormData diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 97989ba7e4f..a35e2a00123 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -8,7 +8,7 @@ use reqwest::header::{HeaderName, HeaderMap}; static mut REQUEST_COUNTER: u32 = 0; -#[derive(Clone, serde::Serialize)] +#[derive(Debug, Clone, serde::Serialize)] pub struct StreamResponse { request_id: u32, status: u16, @@ -66,6 +66,7 @@ pub async fn stream_fetch( let client = Client::builder() .user_agent("Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15") .default_headers(_headers) + .redirect(reqwest::redirect::Policy::limited(3)) .build() .map_err(|err| format!("failed to generate client: {}", err))?; @@ -104,7 +105,7 @@ pub async fn stream_fetch( window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); } Err(err) => { - println!("Error: {:?}", err); + println!("Error chunk: {:?}", err); } } } @@ -119,7 +120,7 @@ pub async fn stream_fetch( } } Err(err) => { - println!("Error: {:?}", err.source().expect("REASON").to_string()); + println!("Error response: {:?}", err.source().expect("REASON").to_string()); StreamResponse { request_id, status: 599, @@ -128,6 +129,7 @@ pub async fn stream_fetch( } } }; + println!("Response: {:?}", response); Ok(response) } From 5141145e4df26bbb732e2536bdb6ac2739f2a6bd Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 00:58:50 +0800 Subject: [PATCH 09/65] revert plugin runtime using tarui/api/http, not using fetch_stream --- app/utils.ts | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 31569516389..6b2f65952c7 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -2,8 +2,8 @@ import { useEffect, useState } from "react"; import { showToast } from "./components/ui-lib"; import Locale from "./locales"; import { RequestMessage } from "./client/api"; -import { ServiceProvider } from "./constant"; -import { fetch } from "./utils/stream"; +import { ServiceProvider, REQUEST_TIMEOUT_MS } from "./constant"; +import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -287,19 +287,35 @@ export function showPlugins(provider: ServiceProvider, model: string) { return false; } +export function fetch( + url: string, + options?: Record, +): Promise { + if (window.__TAURI__) { + const payload = options?.body || options?.data; + return tauriFetch(url, { + ...options, + body: + payload && + ({ + type: "Text", + payload, + } as any), + timeout: ((options?.timeout as number) || REQUEST_TIMEOUT_MS) / 1000, + responseType: + options?.responseType == "text" ? ResponseType.Text : ResponseType.JSON, + } as any); + } + return window.fetch(url, options); +} + export function adapter(config: Record) { - const { baseURL, url, params, method, data, ...rest } = config; + const { baseURL, url, params, ...rest } = config; const path = baseURL ? `${baseURL}${url}` : url; const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, { - ...rest, - method, - body: method.toUpperCase() == "GET" ? undefined : data, - }) - .then((res) => res.text()) - .then((data) => ({ data })); + return fetch(fetchUrl as string, { ...rest, responseType: "text" }); } export function safeLocalStorage(): { From a50c282d01c24a66c603d57ce47c978f725f8c7d Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 01:19:20 +0800 Subject: [PATCH 10/65] remove DEFAULT_API_HOST --- app/client/platforms/alibaba.ts | 2 + app/client/platforms/anthropic.ts | 6 +-- app/client/platforms/baidu.ts | 2 + app/client/platforms/bytedance.ts | 2 + app/client/platforms/google.ts | 6 ++- app/client/platforms/iflytek.ts | 6 ++- app/client/platforms/moonshot.ts | 4 +- app/client/platforms/openai.ts | 4 +- app/client/platforms/tencent.ts | 8 ++-- app/constant.ts | 1 - app/store/access.ts | 72 +++++++++---------------------- app/store/sync.ts | 3 +- app/utils/cors.ts | 19 -------- 13 files changed, 45 insertions(+), 90 deletions(-) delete mode 100644 app/utils/cors.ts diff --git a/app/client/platforms/alibaba.ts b/app/client/platforms/alibaba.ts index 4ade9ebb98f..727e3aebf14 100644 --- a/app/client/platforms/alibaba.ts +++ b/app/client/platforms/alibaba.ts @@ -23,6 +23,7 @@ import { import { prettyObject } from "@/app/utils/format"; import { getClientConfig } from "@/app/config/client"; import { getMessageTextContent } from "@/app/utils"; +import { fetch } from "@/app/utils/stream"; export interface OpenAIListModelResponse { object: string; @@ -178,6 +179,7 @@ export class QwenApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/anthropic.ts b/app/client/platforms/anthropic.ts index 7826838a61e..1a83bd53aa1 100644 --- a/app/client/platforms/anthropic.ts +++ b/app/client/platforms/anthropic.ts @@ -8,7 +8,7 @@ import { ChatMessageTool, } from "@/app/store"; import { getClientConfig } from "@/app/config/client"; -import { DEFAULT_API_HOST } from "@/app/constant"; +import { ANTHROPIC_BASE_URL } from "@/app/constant"; import { getMessageTextContent, isVisionModel } from "@/app/utils"; import { preProcessImageContent, stream } from "@/app/utils/chat"; import { cloudflareAIGatewayUrl } from "@/app/utils/cloudflare"; @@ -388,9 +388,7 @@ export class ClaudeApi implements LLMApi { if (baseUrl.trim().length === 0) { const isApp = !!getClientConfig()?.isApp; - baseUrl = isApp - ? DEFAULT_API_HOST + "/api/proxy/anthropic" - : ApiPath.Anthropic; + baseUrl = isApp ? ANTHROPIC_BASE_URL : ApiPath.Anthropic; } if (!baseUrl.startsWith("http") && !baseUrl.startsWith("/api")) { diff --git a/app/client/platforms/baidu.ts b/app/client/platforms/baidu.ts index c360417c602..4f3294d5e02 100644 --- a/app/client/platforms/baidu.ts +++ b/app/client/platforms/baidu.ts @@ -24,6 +24,7 @@ import { import { prettyObject } from "@/app/utils/format"; import { getClientConfig } from "@/app/config/client"; import { getMessageTextContent } from "@/app/utils"; +import { fetch } from "@/app/utils/stream"; export interface OpenAIListModelResponse { object: string; @@ -197,6 +198,7 @@ export class ErnieApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/bytedance.ts b/app/client/platforms/bytedance.ts index a6e2d426ee3..279be815f3e 100644 --- a/app/client/platforms/bytedance.ts +++ b/app/client/platforms/bytedance.ts @@ -23,6 +23,7 @@ import { import { prettyObject } from "@/app/utils/format"; import { getClientConfig } from "@/app/config/client"; import { getMessageTextContent } from "@/app/utils"; +import { fetch } from "@/app/utils/stream"; export interface OpenAIListModelResponse { object: string; @@ -165,6 +166,7 @@ export class DoubaoApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/google.ts b/app/client/platforms/google.ts index 3c2607271bf..7a74dd4f3b6 100644 --- a/app/client/platforms/google.ts +++ b/app/client/platforms/google.ts @@ -9,7 +9,7 @@ import { } from "../api"; import { useAccessStore, useAppConfig, useChatStore } from "@/app/store"; import { getClientConfig } from "@/app/config/client"; -import { DEFAULT_API_HOST } from "@/app/constant"; +import { GEMINI_BASE_URL } from "@/app/constant"; import Locale from "../../locales"; import { EventStreamContentType, @@ -22,6 +22,7 @@ import { isVisionModel, } from "@/app/utils"; import { preProcessImageContent } from "@/app/utils/chat"; +import { fetch } from "@/app/utils/stream"; export class GeminiProApi implements LLMApi { path(path: string): string { @@ -34,7 +35,7 @@ export class GeminiProApi implements LLMApi { const isApp = !!getClientConfig()?.isApp; if (baseUrl.length === 0) { - baseUrl = isApp ? DEFAULT_API_HOST + `/api/proxy/google` : ApiPath.Google; + baseUrl = isApp ? GEMINI_BASE_URL : ApiPath.Google; } if (baseUrl.endsWith("/")) { baseUrl = baseUrl.slice(0, baseUrl.length - 1); @@ -213,6 +214,7 @@ export class GeminiProApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/iflytek.ts b/app/client/platforms/iflytek.ts index 3931672e661..07bfeda5807 100644 --- a/app/client/platforms/iflytek.ts +++ b/app/client/platforms/iflytek.ts @@ -1,7 +1,7 @@ "use client"; import { ApiPath, - DEFAULT_API_HOST, + IFLYTEK_BASE_URL, Iflytek, REQUEST_TIMEOUT_MS, } from "@/app/constant"; @@ -22,6 +22,7 @@ import { import { prettyObject } from "@/app/utils/format"; import { getClientConfig } from "@/app/config/client"; import { getMessageTextContent } from "@/app/utils"; +import { fetch } from "@/app/utils/stream"; import { RequestPayload } from "./openai"; @@ -40,7 +41,7 @@ export class SparkApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = ApiPath.Iflytek; - baseUrl = isApp ? DEFAULT_API_HOST + "/proxy" + apiPath : apiPath; + baseUrl = isApp ? IFLYTEK_BASE_URL + apiPath : apiPath; } if (baseUrl.endsWith("/")) { @@ -149,6 +150,7 @@ export class SparkApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/moonshot.ts b/app/client/platforms/moonshot.ts index 6b197974571..4570dca9722 100644 --- a/app/client/platforms/moonshot.ts +++ b/app/client/platforms/moonshot.ts @@ -2,7 +2,7 @@ // azure and openai, using same models. so using same LLMApi. import { ApiPath, - DEFAULT_API_HOST, + MOONSHOT_BASE_URL, Moonshot, REQUEST_TIMEOUT_MS, } from "@/app/constant"; @@ -40,7 +40,7 @@ export class MoonshotApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = ApiPath.Moonshot; - baseUrl = isApp ? DEFAULT_API_HOST + "/proxy" + apiPath : apiPath; + baseUrl = isApp ? MOONSHOT_BASE_URL + apiPath : apiPath; } if (baseUrl.endsWith("/")) { diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 0a8d6203ae5..0b2d91c995d 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -2,7 +2,7 @@ // azure and openai, using same models. so using same LLMApi. import { ApiPath, - DEFAULT_API_HOST, + OPENAI_BASE_URL, DEFAULT_MODELS, OpenaiPath, Azure, @@ -98,7 +98,7 @@ export class ChatGPTApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = isAzure ? ApiPath.Azure : ApiPath.OpenAI; - baseUrl = isApp ? DEFAULT_API_HOST + "/proxy" + apiPath : apiPath; + baseUrl = isApp ? OPENAI_BASE_URL + apiPath : apiPath; } if (baseUrl.endsWith("/")) { diff --git a/app/client/platforms/tencent.ts b/app/client/platforms/tencent.ts index 3e8f1a45957..28f5b56f243 100644 --- a/app/client/platforms/tencent.ts +++ b/app/client/platforms/tencent.ts @@ -1,5 +1,5 @@ "use client"; -import { ApiPath, DEFAULT_API_HOST, REQUEST_TIMEOUT_MS } from "@/app/constant"; +import { ApiPath, TENCENT_BASE_URL, REQUEST_TIMEOUT_MS } from "@/app/constant"; import { useAccessStore, useAppConfig, useChatStore } from "@/app/store"; import { @@ -22,6 +22,7 @@ import mapKeys from "lodash-es/mapKeys"; import mapValues from "lodash-es/mapValues"; import isArray from "lodash-es/isArray"; import isObject from "lodash-es/isObject"; +import { fetch } from "@/app/utils/stream"; export interface OpenAIListModelResponse { object: string; @@ -70,9 +71,7 @@ export class HunyuanApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; - baseUrl = isApp - ? DEFAULT_API_HOST + "/api/proxy/tencent" - : ApiPath.Tencent; + baseUrl = isApp ? TENCENT_BASE_URL : ApiPath.Tencent; } if (baseUrl.endsWith("/")) { @@ -179,6 +178,7 @@ export class HunyuanApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { + fetch, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/constant.ts b/app/constant.ts index a54a973daa6..a06b8f05062 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -11,7 +11,6 @@ export const RUNTIME_CONFIG_DOM = "danger-runtime-config"; export const STABILITY_BASE_URL = "https://api.stability.ai"; -export const DEFAULT_API_HOST = "https://api.nextchat.dev"; export const OPENAI_BASE_URL = "https://api.openai.com"; export const ANTHROPIC_BASE_URL = "https://api.anthropic.com"; diff --git a/app/store/access.ts b/app/store/access.ts index 9fcd227e7c0..74050733c79 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -1,9 +1,17 @@ import { - ApiPath, - DEFAULT_API_HOST, GoogleSafetySettingsThreshold, ServiceProvider, StoreKey, + OPENAI_BASE_URL, + ANTHROPIC_BASE_URL, + GEMINI_BASE_URL, + BAIDU_BASE_URL, + BYTEDANCE_BASE_URL, + ALIBABA_BASE_URL, + TENCENT_BASE_URL, + MOONSHOT_BASE_URL, + STABILITY_BASE_URL, + IFLYTEK_BASE_URL, } from "../constant"; import { getHeaders } from "../client/api"; import { getClientConfig } from "../config/client"; @@ -15,46 +23,6 @@ let fetchState = 0; // 0 not fetch, 1 fetching, 2 done const isApp = getClientConfig()?.buildMode === "export"; -const DEFAULT_OPENAI_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/openai" - : ApiPath.OpenAI; - -const DEFAULT_GOOGLE_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/google" - : ApiPath.Google; - -const DEFAULT_ANTHROPIC_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/anthropic" - : ApiPath.Anthropic; - -const DEFAULT_BAIDU_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/baidu" - : ApiPath.Baidu; - -const DEFAULT_BYTEDANCE_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/bytedance" - : ApiPath.ByteDance; - -const DEFAULT_ALIBABA_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/alibaba" - : ApiPath.Alibaba; - -const DEFAULT_TENCENT_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/tencent" - : ApiPath.Tencent; - -const DEFAULT_MOONSHOT_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/moonshot" - : ApiPath.Moonshot; - -const DEFAULT_STABILITY_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/stability" - : ApiPath.Stability; - -const DEFAULT_IFLYTEK_URL = isApp - ? DEFAULT_API_HOST + "/api/proxy/iflytek" - : ApiPath.Iflytek; - const DEFAULT_ACCESS_STATE = { accessCode: "", useCustomConfig: false, @@ -62,7 +30,7 @@ const DEFAULT_ACCESS_STATE = { provider: ServiceProvider.OpenAI, // openai - openaiUrl: DEFAULT_OPENAI_URL, + openaiUrl: OPENAI_BASE_URL, openaiApiKey: "", // azure @@ -71,44 +39,44 @@ const DEFAULT_ACCESS_STATE = { azureApiVersion: "2023-08-01-preview", // google ai studio - googleUrl: DEFAULT_GOOGLE_URL, + googleUrl: GEMINI_BASE_URL, googleApiKey: "", googleApiVersion: "v1", googleSafetySettings: GoogleSafetySettingsThreshold.BLOCK_ONLY_HIGH, // anthropic - anthropicUrl: DEFAULT_ANTHROPIC_URL, + anthropicUrl: ANTHROPIC_BASE_URL, anthropicApiKey: "", anthropicApiVersion: "2023-06-01", // baidu - baiduUrl: DEFAULT_BAIDU_URL, + baiduUrl: BAIDU_BASE_URL, baiduApiKey: "", baiduSecretKey: "", // bytedance - bytedanceUrl: DEFAULT_BYTEDANCE_URL, + bytedanceUrl: BYTEDANCE_BASE_URL, bytedanceApiKey: "", // alibaba - alibabaUrl: DEFAULT_ALIBABA_URL, + alibabaUrl: ALIBABA_BASE_URL, alibabaApiKey: "", // moonshot - moonshotUrl: DEFAULT_MOONSHOT_URL, + moonshotUrl: MOONSHOT_BASE_URL, moonshotApiKey: "", //stability - stabilityUrl: DEFAULT_STABILITY_URL, + stabilityUrl: STABILITY_BASE_URL, stabilityApiKey: "", // tencent - tencentUrl: DEFAULT_TENCENT_URL, + tencentUrl: TENCENT_BASE_URL, tencentSecretKey: "", tencentSecretId: "", // iflytek - iflytekUrl: DEFAULT_IFLYTEK_URL, + iflytekUrl: IFLYTEK_BASE_URL, iflytekApiKey: "", iflytekApiSecret: "", diff --git a/app/store/sync.ts b/app/store/sync.ts index 9db60d5f410..c53a7a82a3d 100644 --- a/app/store/sync.ts +++ b/app/store/sync.ts @@ -12,7 +12,6 @@ import { downloadAs, readFromFile } from "../utils"; import { showToast } from "../components/ui-lib"; import Locale from "../locales"; import { createSyncClient, ProviderType } from "../utils/cloud"; -import { corsPath } from "../utils/cors"; export interface WebDavConfig { server: string; @@ -26,7 +25,7 @@ export type SyncStore = GetStoreState; const DEFAULT_SYNC_STATE = { provider: ProviderType.WebDAV, useProxy: true, - proxyUrl: corsPath(ApiPath.Cors), + proxyUrl: ApiPath.Cors, webdav: { endpoint: "", diff --git a/app/utils/cors.ts b/app/utils/cors.ts deleted file mode 100644 index f5e5ce6f0a2..00000000000 --- a/app/utils/cors.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { getClientConfig } from "../config/client"; -import { DEFAULT_API_HOST } from "../constant"; - -export function corsPath(path: string) { - const baseUrl = getClientConfig()?.isApp ? `${DEFAULT_API_HOST}` : ""; - - if (baseUrl === "" && path === "") { - return ""; - } - if (!path.startsWith("/")) { - path = "/" + path; - } - - if (!path.endsWith("/")) { - path += "/"; - } - - return `${baseUrl}${path}`; -} From 9be58f3eb4217b00073a954262ac4e5b970806f3 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 01:30:20 +0800 Subject: [PATCH 11/65] fix ts error --- app/client/platforms/alibaba.ts | 2 +- app/client/platforms/baidu.ts | 2 +- app/client/platforms/bytedance.ts | 2 +- app/client/platforms/google.ts | 2 +- app/client/platforms/iflytek.ts | 2 +- app/client/platforms/tencent.ts | 2 +- app/store/sync.ts | 2 +- app/utils/chat.ts | 2 +- app/utils/stream.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/client/platforms/alibaba.ts b/app/client/platforms/alibaba.ts index 727e3aebf14..86229a14705 100644 --- a/app/client/platforms/alibaba.ts +++ b/app/client/platforms/alibaba.ts @@ -179,7 +179,7 @@ export class QwenApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/baidu.ts b/app/client/platforms/baidu.ts index 4f3294d5e02..2511a696b9b 100644 --- a/app/client/platforms/baidu.ts +++ b/app/client/platforms/baidu.ts @@ -198,7 +198,7 @@ export class ErnieApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/bytedance.ts b/app/client/platforms/bytedance.ts index 279be815f3e..000a9e278db 100644 --- a/app/client/platforms/bytedance.ts +++ b/app/client/platforms/bytedance.ts @@ -166,7 +166,7 @@ export class DoubaoApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/google.ts b/app/client/platforms/google.ts index 7a74dd4f3b6..dcf300a0f1b 100644 --- a/app/client/platforms/google.ts +++ b/app/client/platforms/google.ts @@ -214,7 +214,7 @@ export class GeminiProApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/iflytek.ts b/app/client/platforms/iflytek.ts index 07bfeda5807..de638829ee5 100644 --- a/app/client/platforms/iflytek.ts +++ b/app/client/platforms/iflytek.ts @@ -150,7 +150,7 @@ export class SparkApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/client/platforms/tencent.ts b/app/client/platforms/tencent.ts index 28f5b56f243..3610fac0a48 100644 --- a/app/client/platforms/tencent.ts +++ b/app/client/platforms/tencent.ts @@ -178,7 +178,7 @@ export class HunyuanApi implements LLMApi { controller.signal.onabort = finish; fetchEventSource(chatPath, { - fetch, + fetch: fetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/store/sync.ts b/app/store/sync.ts index c53a7a82a3d..8477c1e4ba7 100644 --- a/app/store/sync.ts +++ b/app/store/sync.ts @@ -25,7 +25,7 @@ export type SyncStore = GetStoreState; const DEFAULT_SYNC_STATE = { provider: ProviderType.WebDAV, useProxy: true, - proxyUrl: ApiPath.Cors, + proxyUrl: ApiPath.Cors as string, webdav: { endpoint: "", diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 359b2c53ebc..254cef401b1 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -288,7 +288,7 @@ export function stream( REQUEST_TIMEOUT_MS, ); fetchEventSource(chatPath, { - fetch: tauriFetch, + fetch: tauriFetch as any, ...chatPayload, async onopen(res) { clearTimeout(requestTimeoutId); diff --git a/app/utils/stream.ts b/app/utils/stream.ts index 625ecea1f22..e8850fcba8d 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -63,7 +63,7 @@ export function fetch(url: string, options?: RequestInit): Promise { }) .then((u: Function) => (unlisten = u)); - const headers = { + const headers: Record = { Accept: "application/json, text/plain, */*", "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", "User-Agent": navigator.userAgent, From 3c01738c29c64c215f0d118a2db0e65c3f51f4de Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 01:37:16 +0800 Subject: [PATCH 12/65] update --- src-tauri/src/stream.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index a35e2a00123..9aae3d164ea 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -57,14 +57,13 @@ pub async fn stream_fetch( _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); } - println!("method: {:?}", method); - println!("url: {:?}", url); - println!("headers: {:?}", headers); - println!("headers: {:?}", _headers); + // println!("method: {:?}", method); + // println!("url: {:?}", url); + // println!("headers: {:?}", headers); + // println!("headers: {:?}", _headers); let method = method.parse::().map_err(|err| format!("failed to parse method: {}", err))?; let client = Client::builder() - .user_agent("Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15") .default_headers(_headers) .redirect(reqwest::redirect::Policy::limited(3)) .build() @@ -77,7 +76,7 @@ pub async fn stream_fetch( if method == reqwest::Method::POST { let body = bytes::Bytes::from(body); - println!("body: {:?}", body); + // println!("body: {:?}", body); request = request.body(body); } let response_future = request.send(); @@ -129,7 +128,7 @@ pub async fn stream_fetch( } } }; - println!("Response: {:?}", response); + // println!("Response: {:?}", response); Ok(response) } From b174a40634d7c2ab809a2ed89ff6fa2fbbe1beb1 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 01:44:27 +0800 Subject: [PATCH 13/65] update --- app/client/platforms/iflytek.ts | 2 +- app/client/platforms/moonshot.ts | 2 +- app/client/platforms/openai.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/client/platforms/iflytek.ts b/app/client/platforms/iflytek.ts index de638829ee5..55a39d0ccca 100644 --- a/app/client/platforms/iflytek.ts +++ b/app/client/platforms/iflytek.ts @@ -41,7 +41,7 @@ export class SparkApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = ApiPath.Iflytek; - baseUrl = isApp ? IFLYTEK_BASE_URL + apiPath : apiPath; + baseUrl = isApp ? IFLYTEK_BASE_URL : apiPath; } if (baseUrl.endsWith("/")) { diff --git a/app/client/platforms/moonshot.ts b/app/client/platforms/moonshot.ts index 4570dca9722..e0ef3494fe7 100644 --- a/app/client/platforms/moonshot.ts +++ b/app/client/platforms/moonshot.ts @@ -40,7 +40,7 @@ export class MoonshotApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = ApiPath.Moonshot; - baseUrl = isApp ? MOONSHOT_BASE_URL + apiPath : apiPath; + baseUrl = isApp ? MOONSHOT_BASE_URL : apiPath; } if (baseUrl.endsWith("/")) { diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 0b2d91c995d..a2263361143 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -98,7 +98,7 @@ export class ChatGPTApi implements LLMApi { if (baseUrl.length === 0) { const isApp = !!getClientConfig()?.isApp; const apiPath = isAzure ? ApiPath.Azure : ApiPath.OpenAI; - baseUrl = isApp ? OPENAI_BASE_URL + apiPath : apiPath; + baseUrl = isApp ? OPENAI_BASE_URL : apiPath; } if (baseUrl.endsWith("/")) { From af49ed4fdcd81b05c6bc0f11a35af346180134f8 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 01:51:14 +0800 Subject: [PATCH 14/65] update --- app/global.d.ts | 1 - src-tauri/src/stream.rs | 9 +-------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/global.d.ts b/app/global.d.ts index a1453dc33b4..8ee636bcd3c 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -12,7 +12,6 @@ declare module "*.svg"; declare interface Window { __TAURI__?: { - convertFileSrc(url: string, protocol?: string): string; writeText(text: string): Promise; invoke(command: string, payload?: Record): Promise; dialog: { diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 9aae3d164ea..f7d5a7693d7 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -2,6 +2,7 @@ // use std::error::Error; +use std::collections::HashMap; use futures_util::{StreamExt}; use reqwest::Client; use reqwest::header::{HeaderName, HeaderMap}; @@ -28,14 +29,6 @@ pub struct ChunkPayload { chunk: bytes::Bytes, } -use std::collections::HashMap; - -#[derive(serde::Serialize)] -pub struct CustomResponse { - message: String, - other_val: usize, -} - #[tauri::command] pub async fn stream_fetch( window: tauri::Window, From f42488d4cb1aba73b4632b49b6606efd0b5a378d Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 02:28:19 +0800 Subject: [PATCH 15/65] using stream fetch replace old tauri http fetch --- app/utils.ts | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 6b2f65952c7..4887a1021ad 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -2,8 +2,9 @@ import { useEffect, useState } from "react"; import { showToast } from "./components/ui-lib"; import Locale from "./locales"; import { RequestMessage } from "./client/api"; -import { ServiceProvider, REQUEST_TIMEOUT_MS } from "./constant"; -import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; +import { ServiceProvider } from "./constant"; +// import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; +import { fetch as tauriStreamFetch } from "./utils/stream"; export function trimTopic(topic: string) { // Fix an issue where double quotes still show in the Indonesian language @@ -292,19 +293,22 @@ export function fetch( options?: Record, ): Promise { if (window.__TAURI__) { - const payload = options?.body || options?.data; - return tauriFetch(url, { - ...options, - body: - payload && - ({ - type: "Text", - payload, - } as any), - timeout: ((options?.timeout as number) || REQUEST_TIMEOUT_MS) / 1000, - responseType: - options?.responseType == "text" ? ResponseType.Text : ResponseType.JSON, - } as any); + return tauriStreamFetch(url, options) + .then((res) => res.text()) + .then((data) => ({ data })); + // const payload = options?.body || options?.data; + // return tauriFetch(url, { + // ...options, + // body: + // payload && + // ({ + // type: "Text", + // payload, + // } as any), + // timeout: ((options?.timeout as number) || REQUEST_TIMEOUT_MS) / 1000, + // responseType: + // options?.responseType == "text" ? ResponseType.Text : ResponseType.JSON, + // } as any); } return window.fetch(url, options); } From 8030e71a5aefe551d23b19867fd8738791c0d712 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 02:33:02 +0800 Subject: [PATCH 16/65] update --- src-tauri/src/stream.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index f7d5a7693d7..51d844305e6 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -2,12 +2,13 @@ // use std::error::Error; +use std::sync::atomic::{AtomicU32, Ordering}; use std::collections::HashMap; use futures_util::{StreamExt}; use reqwest::Client; use reqwest::header::{HeaderName, HeaderMap}; -static mut REQUEST_COUNTER: u32 = 0; +static REQUEST_COUNTER: AtomicU32 = AtomicU32::new(0); #[derive(Debug, Clone, serde::Serialize)] pub struct StreamResponse { @@ -38,12 +39,8 @@ pub async fn stream_fetch( body: Vec, ) -> Result { - let mut request_id = 0; let event_name = "stream-response"; - unsafe { - REQUEST_COUNTER += 1; - request_id = REQUEST_COUNTER; - } + let request_id = REQUEST_COUNTER.fetch_add(1, Ordering::SeqCst); let mut _headers = HeaderMap::new(); for (key, value) in &headers { @@ -72,6 +69,10 @@ pub async fn stream_fetch( // println!("body: {:?}", body); request = request.body(body); } + + // println!("client: {:?}", client); + // println!("request: {:?}", request); + let response_future = request.send(); let res = response_future.await; From ef4665cd8b590531af31c56562afdbeb7fa7d0bd Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 02:57:51 +0800 Subject: [PATCH 17/65] update --- app/utils.ts | 8 ++++---- app/utils/stream.ts | 10 +++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 4887a1021ad..9f5dd315090 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -293,9 +293,7 @@ export function fetch( options?: Record, ): Promise { if (window.__TAURI__) { - return tauriStreamFetch(url, options) - .then((res) => res.text()) - .then((data) => ({ data })); + return tauriStreamFetch(url, options); // const payload = options?.body || options?.data; // return tauriFetch(url, { // ...options, @@ -319,7 +317,9 @@ export function adapter(config: Record) { const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, { ...rest, responseType: "text" }); + return fetch(fetchUrl as string, { ...rest, responseType: "text" }) + .then((res) => res.text()) + .then((data) => ({ data })); } export function safeLocalStorage(): { diff --git a/app/utils/stream.ts b/app/utils/stream.ts index e8850fcba8d..2a8c13777e5 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -85,7 +85,15 @@ export function fetch(url: string, options?: RequestInit): Promise { .then((res: StreamResponse) => { request_id = res.request_id; const { status, status_text: statusText, headers } = res; - return new Response(ts.readable, { status, statusText, headers }); + const response = new Response(ts.readable, { + status, + statusText, + headers, + }); + if (status >= 300) { + setTimeout(close, 50); + } + return response; }) .catch((e) => { console.error("stream error", e); From 6293b95a3b7f6722d5e8971a4937331119cb174f Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 10:13:11 +0800 Subject: [PATCH 18/65] update default api base url --- app/store/access.ts | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/app/store/access.ts b/app/store/access.ts index 74050733c79..dec3a725886 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -2,6 +2,7 @@ import { GoogleSafetySettingsThreshold, ServiceProvider, StoreKey, + ApiPath, OPENAI_BASE_URL, ANTHROPIC_BASE_URL, GEMINI_BASE_URL, @@ -23,6 +24,26 @@ let fetchState = 0; // 0 not fetch, 1 fetching, 2 done const isApp = getClientConfig()?.buildMode === "export"; +const DEFAULT_OPENAI_URL = isApp ? OPENAI_BASE_URL : ApiPath.OpenAI; + +const DEFAULT_GOOGLE_URL = isApp ? GEMINI_BASE_URL : ApiPath.Google; + +const DEFAULT_ANTHROPIC_URL = isApp ? ANTHROPIC_BASE_URL : ApiPath.Anthropic; + +const DEFAULT_BAIDU_URL = isApp ? BAIDU_BASE_URL : ApiPath.Baidu; + +const DEFAULT_BYTEDANCE_URL = isApp ? BYTEDANCE_BASE_URL : ApiPath.ByteDance; + +const DEFAULT_ALIBABA_URL = isApp ? ALIBABA_BASE_URL : ApiPath.Alibaba; + +const DEFAULT_TENCENT_URL = isApp ? TENCENT_BASE_URL : ApiPath.Tencent; + +const DEFAULT_MOONSHOT_URL = isApp ? MOONSHOT_BASE_URL : ApiPath.Moonshot; + +const DEFAULT_STABILITY_URL = isApp ? STABILITY_BASE_URL : ApiPath.Stability; + +const DEFAULT_IFLYTEK_URL = isApp ? IFLYTEK_BASE_URL : ApiPath.Iflytek; + const DEFAULT_ACCESS_STATE = { accessCode: "", useCustomConfig: false, @@ -30,7 +51,7 @@ const DEFAULT_ACCESS_STATE = { provider: ServiceProvider.OpenAI, // openai - openaiUrl: OPENAI_BASE_URL, + openaiUrl: DEFAULT_OPENAI_URL, openaiApiKey: "", // azure @@ -39,44 +60,44 @@ const DEFAULT_ACCESS_STATE = { azureApiVersion: "2023-08-01-preview", // google ai studio - googleUrl: GEMINI_BASE_URL, + googleUrl: DEFAULT_GOOGLE_URL, googleApiKey: "", googleApiVersion: "v1", googleSafetySettings: GoogleSafetySettingsThreshold.BLOCK_ONLY_HIGH, // anthropic - anthropicUrl: ANTHROPIC_BASE_URL, + anthropicUrl: DEFAULT_ANTHROPIC_URL, anthropicApiKey: "", anthropicApiVersion: "2023-06-01", // baidu - baiduUrl: BAIDU_BASE_URL, + baiduUrl: DEFAULT_BAIDU_URL, baiduApiKey: "", baiduSecretKey: "", // bytedance - bytedanceUrl: BYTEDANCE_BASE_URL, + bytedanceUrl: DEFAULT_BYTEDANCE_URL, bytedanceApiKey: "", // alibaba - alibabaUrl: ALIBABA_BASE_URL, + alibabaUrl: DEFAULT_ALIBABA_URL, alibabaApiKey: "", // moonshot - moonshotUrl: MOONSHOT_BASE_URL, + moonshotUrl: DEFAULT_MOONSHOT_URL, moonshotApiKey: "", //stability - stabilityUrl: STABILITY_BASE_URL, + stabilityUrl: DEFAULT_STABILITY_URL, stabilityApiKey: "", // tencent - tencentUrl: TENCENT_BASE_URL, + tencentUrl: DEFAULT_TENCENT_URL, tencentSecretKey: "", tencentSecretId: "", // iflytek - iflytekUrl: IFLYTEK_BASE_URL, + iflytekUrl: DEFAULT_IFLYTEK_URL, iflytekApiKey: "", iflytekApiSecret: "", From b6d9ba93fa101deeb9920f29bee5f675591dacd5 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 10:18:30 +0800 Subject: [PATCH 19/65] update --- src-tauri/src/stream.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 51d844305e6..938c663e1f9 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -95,14 +95,18 @@ pub async fn stream_fetch( match chunk { Ok(bytes) => { // println!("chunk: {:?}", bytes); - window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }).unwrap(); + if let Err(e) = window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }) { + println!("Failed to emit chunk payload: {:?}", e); + } } Err(err) => { println!("Error chunk: {:?}", err); } } } - window.emit(event_name, EndPayload { request_id, status: 0 }).unwrap(); + if let Err(e) = window.emit(event_name, EndPayload{ request_id, status: 0 }) { + println!("Failed to emit end payload: {:?}", e); + } }); StreamResponse { From edfa6d14eefb339781c839750fb68bbfeb632011 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 10:23:24 +0800 Subject: [PATCH 20/65] update --- src-tauri/src/stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 938c663e1f9..3d21623e6f3 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -64,7 +64,7 @@ pub async fn stream_fetch( url.parse::().map_err(|err| format!("failed to parse url: {}", err))? ); - if method == reqwest::Method::POST { + if method == reqwest::Method::POST || method == reqwest::Method::PUT || method == reqwest::Method::PATCH { let body = bytes::Bytes::from(body); // println!("body: {:?}", body); request = request.body(body); From 7173cf21846475455502cf2d6363fff30e3c4600 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 13:07:06 +0800 Subject: [PATCH 21/65] update --- README.md | 2 ++ src-tauri/tauri.conf.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index be5e91d65c7..5887369ff40 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ For enterprise inquiries, please contact: **business@nextchat.dev** ## What's New +- 🚀 v2.15.4 The Application supports using Tauri fetch LLM API, MORE SECURITY! [#5379](https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/issues/5379) - 🚀 v2.15.0 Now supports Plugins! Read this: [NextChat-Awesome-Plugins](https://github.com/ChatGPTNextWeb/NextChat-Awesome-Plugins) - 🚀 v2.14.0 Now supports Artifacts & SD - 🚀 v2.10.1 support Google Gemini Pro model. @@ -137,6 +138,7 @@ For enterprise inquiries, please contact: **business@nextchat.dev** ## 最新动态 +- 🚀 v2.15.4 客户端支持Tauri本地直接调用大模型API,更安全![#5379](https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/issues/5379) - 🚀 v2.15.0 现在支持插件功能了!了解更多:[NextChat-Awesome-Plugins](https://github.com/ChatGPTNextWeb/NextChat-Awesome-Plugins) - 🚀 v2.14.0 现在支持 Artifacts & SD 了。 - 🚀 v2.10.1 现在支持 Gemini Pro 模型。 diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index eb0d411cba6..cc137ee8afd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "NextChat", - "version": "2.15.3" + "version": "2.15.4" }, "tauri": { "allowlist": { From 35e03e1bcaf228d685e6b2a1ec9168f7892dab98 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 13:44:01 +0800 Subject: [PATCH 22/65] remove code --- src-tauri/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c954deb72a8..8a11c3b6f98 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,7 +35,6 @@ tauri = { version = "1.5.4", features = [ "http-all", "window-start-dragging", "window-unmaximize", "window-unminimize", - "linux-protocol-headers", ] } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } percent-encoding = "2.3.1" From 3029dcb2f6edbf2fcc805188ac3883a09715fd3f Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 15:32:47 +0800 Subject: [PATCH 23/65] hotfix for run plugin call post api --- app/utils.ts | 5 ++++- src-tauri/src/stream.rs | 18 +++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 9f5dd315090..e542e256d57 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -293,7 +293,10 @@ export function fetch( options?: Record, ): Promise { if (window.__TAURI__) { - return tauriStreamFetch(url, options); + return tauriStreamFetch(url, { + ...options, + body: options?.body || options?.data, + }); // const payload = options?.body || options?.data; // return tauriFetch(url, { // ...options, diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 3d21623e6f3..0fcc02dfc33 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -47,10 +47,10 @@ pub async fn stream_fetch( _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); } - // println!("method: {:?}", method); - // println!("url: {:?}", url); - // println!("headers: {:?}", headers); - // println!("headers: {:?}", _headers); + println!("method: {:?}", method); + println!("url: {:?}", url); + println!("headers: {:?}", headers); + println!("headers: {:?}", _headers); let method = method.parse::().map_err(|err| format!("failed to parse method: {}", err))?; let client = Client::builder() @@ -66,12 +66,12 @@ pub async fn stream_fetch( if method == reqwest::Method::POST || method == reqwest::Method::PUT || method == reqwest::Method::PATCH { let body = bytes::Bytes::from(body); - // println!("body: {:?}", body); + println!("body: {:?}", body); request = request.body(body); } - // println!("client: {:?}", client); - // println!("request: {:?}", request); + println!("client: {:?}", client); + println!("request: {:?}", request); let response_future = request.send(); @@ -94,7 +94,7 @@ pub async fn stream_fetch( while let Some(chunk) = stream.next().await { match chunk { Ok(bytes) => { - // println!("chunk: {:?}", bytes); + println!("chunk: {:?}", bytes); if let Err(e) = window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }) { println!("Failed to emit chunk payload: {:?}", e); } @@ -126,7 +126,7 @@ pub async fn stream_fetch( } } }; - // println!("Response: {:?}", response); + println!("Response: {:?}", response); Ok(response) } From fd3568c459d2339817838b824b6ee5f8d4b59d24 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 15:33:40 +0800 Subject: [PATCH 24/65] hotfix for run plugin call post api --- src-tauri/src/stream.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 0fcc02dfc33..3d21623e6f3 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -47,10 +47,10 @@ pub async fn stream_fetch( _headers.insert(key.parse::().unwrap(), value.parse().unwrap()); } - println!("method: {:?}", method); - println!("url: {:?}", url); - println!("headers: {:?}", headers); - println!("headers: {:?}", _headers); + // println!("method: {:?}", method); + // println!("url: {:?}", url); + // println!("headers: {:?}", headers); + // println!("headers: {:?}", _headers); let method = method.parse::().map_err(|err| format!("failed to parse method: {}", err))?; let client = Client::builder() @@ -66,12 +66,12 @@ pub async fn stream_fetch( if method == reqwest::Method::POST || method == reqwest::Method::PUT || method == reqwest::Method::PATCH { let body = bytes::Bytes::from(body); - println!("body: {:?}", body); + // println!("body: {:?}", body); request = request.body(body); } - println!("client: {:?}", client); - println!("request: {:?}", request); + // println!("client: {:?}", client); + // println!("request: {:?}", request); let response_future = request.send(); @@ -94,7 +94,7 @@ pub async fn stream_fetch( while let Some(chunk) = stream.next().await { match chunk { Ok(bytes) => { - println!("chunk: {:?}", bytes); + // println!("chunk: {:?}", bytes); if let Err(e) = window.emit(event_name, ChunkPayload{ request_id, chunk: bytes }) { println!("Failed to emit chunk payload: {:?}", e); } @@ -126,7 +126,7 @@ pub async fn stream_fetch( } } }; - println!("Response: {:?}", response); + // println!("Response: {:?}", response); Ok(response) } From d830c23daba6e80452286aadfec8eeb9cc8652bb Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 30 Sep 2024 15:38:13 +0800 Subject: [PATCH 25/65] hotfix for run plugin call post api --- app/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utils.ts b/app/utils.ts index e542e256d57..c1476152a53 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -295,7 +295,7 @@ export function fetch( if (window.__TAURI__) { return tauriStreamFetch(url, { ...options, - body: options?.body || options?.data, + body: (options?.body || options?.data) as any, }); // const payload = options?.body || options?.data; // return tauriFetch(url, { From 953114041bb8381314c7f880d83c5157d0b6b3ad Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Tue, 1 Oct 2024 12:02:29 +0800 Subject: [PATCH 26/65] add connect timeout --- src-tauri/src/stream.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-tauri/src/stream.rs b/src-tauri/src/stream.rs index 3d21623e6f3..d2c0726b0b4 100644 --- a/src-tauri/src/stream.rs +++ b/src-tauri/src/stream.rs @@ -1,6 +1,7 @@ // // +use std::time::Duration; use std::error::Error; use std::sync::atomic::{AtomicU32, Ordering}; use std::collections::HashMap; @@ -56,6 +57,7 @@ pub async fn stream_fetch( let client = Client::builder() .default_headers(_headers) .redirect(reqwest::redirect::Policy::limited(3)) + .connect_timeout(Duration::new(3, 0)) .build() .map_err(|err| format!("failed to generate client: {}", err))?; From 9c577ad9d57d47ad5831ca15f15988ba0381ee2c Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Tue, 1 Oct 2024 12:55:57 +0800 Subject: [PATCH 27/65] hotfix for plugin runtime --- app/utils.ts | 9 ++++++--- app/utils/chat.ts | 5 ++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index c1476152a53..95880115a3d 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -320,9 +320,12 @@ export function adapter(config: Record) { const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, { ...rest, responseType: "text" }) - .then((res) => res.text()) - .then((data) => ({ data })); + return fetch(fetchUrl as string, { ...rest, responseType: "text" }).then( + (res) => { + const { status, headers } = res; + return res.text().then((data) => ({ status, headers, data })); + }, + ); } export function safeLocalStorage(): { diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 254cef401b1..3d796048000 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -222,7 +222,10 @@ export function stream( ), ) .then((res) => { - const content = JSON.stringify(res.data); + let content = res.data; + try { + content = JSON.stringify(res.data); + } catch (e) {} if (res.status >= 300) { return Promise.reject(content); } From 919ee51dca25ba03f2d627eaabbe17b578dec45d Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Tue, 1 Oct 2024 13:58:50 +0800 Subject: [PATCH 28/65] hover show errorMsg when plugin run error --- app/components/chat.tsx | 1 + app/store/chat.ts | 1 + app/utils.ts | 6 ++++-- app/utils/chat.ts | 11 ++++++----- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 3d519dee722..b45d36f9587 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1815,6 +1815,7 @@ function _Chat() { {message?.tools?.map((tool) => (
{tool.isError === false ? ( diff --git a/app/store/chat.ts b/app/store/chat.ts index 968d8cb6422..931cad76883 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -37,6 +37,7 @@ export type ChatMessageTool = { }; content?: string; isError?: boolean; + errorMsg?: string; }; export type ChatMessage = RequestMessage & { diff --git a/app/utils.ts b/app/utils.ts index 95880115a3d..83bcea5c0ec 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -322,8 +322,10 @@ export function adapter(config: Record) { : path; return fetch(fetchUrl as string, { ...rest, responseType: "text" }).then( (res) => { - const { status, headers } = res; - return res.text().then((data) => ({ status, headers, data })); + const { status, headers, statusText } = res; + return res + .text() + .then((data: string) => ({ status, statusText, headers, data })); }, ); } diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 3d796048000..46f23263895 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -222,10 +222,7 @@ export function stream( ), ) .then((res) => { - let content = res.data; - try { - content = JSON.stringify(res.data); - } catch (e) {} + let content = res.data || res?.statusText; if (res.status >= 300) { return Promise.reject(content); } @@ -240,7 +237,11 @@ export function stream( return content; }) .catch((e) => { - options?.onAfterTool?.({ ...tool, isError: true }); + options?.onAfterTool?.({ + ...tool, + isError: true, + errorMsg: e.toString(), + }); return e.toString(); }) .then((content) => ({ From d51d31a55959c00279f9d84b302d3ac4de77f559 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Tue, 1 Oct 2024 14:40:23 +0800 Subject: [PATCH 29/65] update --- app/utils.ts | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/app/utils.ts b/app/utils.ts index 83bcea5c0ec..b3d27cbce2c 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -293,41 +293,23 @@ export function fetch( options?: Record, ): Promise { if (window.__TAURI__) { - return tauriStreamFetch(url, { - ...options, - body: (options?.body || options?.data) as any, - }); - // const payload = options?.body || options?.data; - // return tauriFetch(url, { - // ...options, - // body: - // payload && - // ({ - // type: "Text", - // payload, - // } as any), - // timeout: ((options?.timeout as number) || REQUEST_TIMEOUT_MS) / 1000, - // responseType: - // options?.responseType == "text" ? ResponseType.Text : ResponseType.JSON, - // } as any); + return tauriStreamFetch(url, options); } return window.fetch(url, options); } export function adapter(config: Record) { - const { baseURL, url, params, ...rest } = config; + const { baseURL, url, params, data: body, ...rest } = config; const path = baseURL ? `${baseURL}${url}` : url; const fetchUrl = params ? `${path}?${new URLSearchParams(params as any).toString()}` : path; - return fetch(fetchUrl as string, { ...rest, responseType: "text" }).then( - (res) => { - const { status, headers, statusText } = res; - return res - .text() - .then((data: string) => ({ status, statusText, headers, data })); - }, - ); + return fetch(fetchUrl as string, { ...rest, body }).then((res) => { + const { status, headers, statusText } = res; + return res + .text() + .then((data: string) => ({ status, statusText, headers, data })); + }); } export function safeLocalStorage(): { From 450766a44bf6868a716de7c012c7e42347c62898 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 3 Oct 2024 20:28:15 +0800 Subject: [PATCH 30/65] google gemini support function call --- app/client/platforms/google.ts | 193 ++++++++++++++------------------- app/utils.ts | 3 + app/utils/chat.ts | 1 + 3 files changed, 86 insertions(+), 111 deletions(-) diff --git a/app/client/platforms/google.ts b/app/client/platforms/google.ts index 3c2607271bf..3b82a569bc6 100644 --- a/app/client/platforms/google.ts +++ b/app/client/platforms/google.ts @@ -7,21 +7,25 @@ import { LLMUsage, SpeechOptions, } from "../api"; -import { useAccessStore, useAppConfig, useChatStore } from "@/app/store"; +import { + useAccessStore, + useAppConfig, + useChatStore, + usePluginStore, + ChatMessageTool, +} from "@/app/store"; +import { stream } from "@/app/utils/chat"; import { getClientConfig } from "@/app/config/client"; import { DEFAULT_API_HOST } from "@/app/constant"; -import Locale from "../../locales"; -import { - EventStreamContentType, - fetchEventSource, -} from "@fortaine/fetch-event-source"; -import { prettyObject } from "@/app/utils/format"; + import { getMessageTextContent, getMessageImages, isVisionModel, } from "@/app/utils"; import { preProcessImageContent } from "@/app/utils/chat"; +import { nanoid } from "nanoid"; +import { RequestPayload } from "./openai"; export class GeminiProApi implements LLMApi { path(path: string): string { @@ -177,114 +181,81 @@ export class GeminiProApi implements LLMApi { ); if (shouldStream) { - let responseText = ""; - let remainText = ""; - let finished = false; - - const finish = () => { - if (!finished) { - finished = true; - options.onFinish(responseText + remainText); - } - }; - - // animate response to make it looks smooth - function animateResponseText() { - if (finished || controller.signal.aborted) { - responseText += remainText; - finish(); - return; - } - - if (remainText.length > 0) { - const fetchCount = Math.max(1, Math.round(remainText.length / 60)); - const fetchText = remainText.slice(0, fetchCount); - responseText += fetchText; - remainText = remainText.slice(fetchCount); - options.onUpdate?.(responseText, fetchText); - } - - requestAnimationFrame(animateResponseText); - } - - // start animaion - animateResponseText(); - - controller.signal.onabort = finish; - - fetchEventSource(chatPath, { - ...chatPayload, - async onopen(res) { - clearTimeout(requestTimeoutId); - const contentType = res.headers.get("content-type"); - console.log( - "[Gemini] request response content type: ", - contentType, - ); - - if (contentType?.startsWith("text/plain")) { - responseText = await res.clone().text(); - return finish(); - } - - if ( - !res.ok || - !res.headers - .get("content-type") - ?.startsWith(EventStreamContentType) || - res.status !== 200 - ) { - const responseTexts = [responseText]; - let extraInfo = await res.clone().text(); - try { - const resJson = await res.clone().json(); - extraInfo = prettyObject(resJson); - } catch {} - - if (res.status === 401) { - responseTexts.push(Locale.Error.Unauthorized); - } - - if (extraInfo) { - responseTexts.push(extraInfo); - } - - responseText = responseTexts.join("\n\n"); - - return finish(); - } - }, - onmessage(msg) { - if (msg.data === "[DONE]" || finished) { - return finish(); - } - const text = msg.data; - try { - const json = JSON.parse(text); - const delta = apiClient.extractMessage(json); - - if (delta) { - remainText += delta; - } + const [tools, funcs] = usePluginStore + .getState() + .getAsTools( + useChatStore.getState().currentSession().mask?.plugin || [], + ); + return stream( + chatPath, + requestPayload, + getHeaders(), + // @ts-ignore + [{ functionDeclarations: tools.map((tool) => tool.function) }], + funcs, + controller, + // parseSSE + (text: string, runTools: ChatMessageTool[]) => { + // console.log("parseSSE", text, runTools); + const chunkJson = JSON.parse(text); - const blockReason = json?.promptFeedback?.blockReason; - if (blockReason) { - // being blocked - console.log(`[Google] [Safety Ratings] result:`, blockReason); - } - } catch (e) { - console.error("[Request] parse error", text, msg); + const functionCall = chunkJson?.candidates + ?.at(0) + ?.content.parts.at(0)?.functionCall; + if (functionCall) { + const { name, args } = functionCall; + runTools.push({ + id: nanoid(), + type: "function", + function: { + name, + arguments: JSON.stringify(args), // utils.chat call function, using JSON.parse + }, + }); } + return chunkJson?.candidates?.at(0)?.content.parts.at(0)?.text; }, - onclose() { - finish(); - }, - onerror(e) { - options.onError?.(e); - throw e; + // processToolMessage, include tool_calls message and tool call results + ( + requestPayload: RequestPayload, + toolCallMessage: any, + toolCallResult: any[], + ) => { + // @ts-ignore + requestPayload?.contents?.splice( + // @ts-ignore + requestPayload?.contents?.length, + 0, + { + role: "model", + parts: toolCallMessage.tool_calls.map( + (tool: ChatMessageTool) => ({ + functionCall: { + name: tool?.function?.name, + args: JSON.parse(tool?.function?.arguments as string), + }, + }), + ), + }, + // @ts-ignore + ...toolCallResult.map((result) => ({ + role: "function", + parts: [ + { + functionResponse: { + name: result.name, + response: { + name: result.name, + content: result.content, // TODO just text content... + }, + }, + }, + ], + })), + ); }, - openWhenHidden: true, - }); + options, + ); } else { const res = await fetch(chatPath, chatPayload); clearTimeout(requestTimeoutId); diff --git a/app/utils.ts b/app/utils.ts index 6b2f65952c7..a7c817767e0 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -284,6 +284,9 @@ export function showPlugins(provider: ServiceProvider, model: string) { if (provider == ServiceProvider.Anthropic && !model.includes("claude-2")) { return true; } + if (provider == ServiceProvider.Google && !model.includes("vision")) { + return true; + } return false; } diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 7f3bb23c58e..c93334bb1af 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -240,6 +240,7 @@ export function stream( return e.toString(); }) .then((content) => ({ + name: tool.function.name, role: "tool", content, tool_call_id: tool.id, From 461154bb039793b3086a4697d031f9a85a1c3b26 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Tue, 8 Oct 2024 10:29:42 +0800 Subject: [PATCH 31/65] fix: format package --- package.json | 166 +++++++++++++++++++++++++-------------------------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/package.json b/package.json index 3945a203f54..eb7683992aa 100644 --- a/package.json +++ b/package.json @@ -1,84 +1,84 @@ { - "name": "nextchat", - "private": false, - "license": "mit", - "scripts": { - "mask": "npx tsx app/masks/build.ts", - "mask:watch": "npx watch \"yarn mask\" app/masks", - "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", - "build": "yarn test:ci && yarn mask && cross-env BUILD_MODE=standalone next build", - "start": "next start", - "lint": "next lint", - "export": "yarn test:ci && yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", - "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", - "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", - "app:build": "yarn test:ci && yarn mask && yarn tauri build", - "prompts": "node ./scripts/fetch-prompts.mjs", - "prepare": "husky install", - "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev", - "test": "jest --watch", - "test:ci": "jest --ci" - }, - "dependencies": { - "@fortaine/fetch-event-source": "^3.0.6", - "@hello-pangea/dnd": "^16.5.0", - "@next/third-parties": "^14.1.0", - "@svgr/webpack": "^6.5.1", - "@vercel/analytics": "^0.1.11", - "@vercel/speed-insights": "^1.0.2", - "emoji-picker-react": "^4.9.2", - "fuse.js": "^7.0.0", - "heic2any": "^0.0.4", - "html-to-image": "^1.11.11", - "lodash-es": "^4.17.21", - "mermaid": "^10.6.1", - "nanoid": "^5.0.3", - "next": "^14.1.1", - "node-fetch": "^3.3.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-markdown": "^8.0.7", - "react-router-dom": "^6.15.0", - "rehype-highlight": "^6.0.0", - "rehype-katex": "^6.0.3", - "remark-breaks": "^3.0.2", - "remark-gfm": "^3.0.1", - "remark-math": "^5.1.1", - "sass": "^1.59.2", - "spark-md5": "^3.0.2", - "use-debounce": "^9.0.4", - "zustand": "^4.3.8" - }, - "devDependencies": { - "@tauri-apps/cli": "1.5.11", - "@testing-library/jest-dom": "^6.4.8", - "@testing-library/react": "^16.0.0", - "@types/jest": "^29.5.12", - "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.30", - "@types/react": "^18.2.70", - "@types/react-dom": "^18.2.7", - "@types/react-katex": "^3.0.0", - "@types/spark-md5": "^3.0.4", - "concurrently": "^8.2.2", - "cross-env": "^7.0.3", - "eslint": "^8.49.0", - "eslint-config-next": "13.4.19", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-prettier": "^5.1.3", - "husky": "^8.0.0", - "jest": "^29.7.0", - "jest-environment-jsdom": "^29.7.0", - "lint-staged": "^13.2.2", - "prettier": "^3.0.2", - "ts-node": "^10.9.2", - "tsx": "^4.16.0", - "typescript": "5.2.2", - "watch": "^1.0.2", - "webpack": "^5.88.1" - }, - "resolutions": { - "lint-staged/yaml": "^2.2.2" - }, - "packageManager": "yarn@1.22.19" -} \ No newline at end of file + "name": "nextchat", + "private": false, + "license": "mit", + "scripts": { + "mask": "npx tsx app/masks/build.ts", + "mask:watch": "npx watch \"yarn mask\" app/masks", + "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", + "build": "yarn test:ci && yarn mask && cross-env BUILD_MODE=standalone next build", + "start": "next start", + "lint": "next lint", + "export": "yarn test:ci && yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", + "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", + "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", + "app:build": "yarn test:ci && yarn mask && yarn tauri build", + "prompts": "node ./scripts/fetch-prompts.mjs", + "prepare": "husky install", + "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev", + "test": "jest --watch", + "test:ci": "jest --ci" + }, + "dependencies": { + "@fortaine/fetch-event-source": "^3.0.6", + "@hello-pangea/dnd": "^16.5.0", + "@next/third-parties": "^14.1.0", + "@svgr/webpack": "^6.5.1", + "@vercel/analytics": "^0.1.11", + "@vercel/speed-insights": "^1.0.2", + "emoji-picker-react": "^4.9.2", + "fuse.js": "^7.0.0", + "heic2any": "^0.0.4", + "html-to-image": "^1.11.11", + "lodash-es": "^4.17.21", + "mermaid": "^10.6.1", + "nanoid": "^5.0.3", + "next": "^14.1.1", + "node-fetch": "^3.3.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-markdown": "^8.0.7", + "react-router-dom": "^6.15.0", + "rehype-highlight": "^6.0.0", + "rehype-katex": "^6.0.3", + "remark-breaks": "^3.0.2", + "remark-gfm": "^3.0.1", + "remark-math": "^5.1.1", + "sass": "^1.59.2", + "spark-md5": "^3.0.2", + "use-debounce": "^9.0.4", + "zustand": "^4.3.8" + }, + "devDependencies": { + "@tauri-apps/cli": "1.5.11", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/jest": "^29.5.12", + "@types/lodash-es": "^4.17.12", + "@types/node": "^20.11.30", + "@types/react": "^18.2.70", + "@types/react-dom": "^18.2.7", + "@types/react-katex": "^3.0.0", + "@types/spark-md5": "^3.0.4", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "eslint": "^8.49.0", + "eslint-config-next": "13.4.19", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-prettier": "^5.1.3", + "husky": "^8.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": "^13.2.2", + "prettier": "^3.0.2", + "ts-node": "^10.9.2", + "tsx": "^4.16.0", + "typescript": "5.2.2", + "watch": "^1.0.2", + "webpack": "^5.88.1" + }, + "resolutions": { + "lint-staged/yaml": "^2.2.2" + }, + "packageManager": "yarn@1.22.19" +} From 7d55a6d0e441bddaf9870c9adfa88f1f72c600a5 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Tue, 8 Oct 2024 21:31:01 +0800 Subject: [PATCH 32/65] feat: allow send image only --- app/components/chat.tsx | 7 +++++-- app/store/chat.ts | 22 ++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 3d519dee722..77b48abee43 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -115,11 +115,14 @@ import { getClientConfig } from "../config/client"; import { useAllModels } from "../utils/hooks"; import { MultimodalContent } from "../client/api"; -const localStorage = safeLocalStorage(); import { ClientApi } from "../client/api"; import { createTTSPlayer } from "../utils/audio"; import { MsEdgeTTS, OUTPUT_FORMAT } from "../utils/ms_edge_tts"; +import { isEmpty } from "lodash-es"; + +const localStorage = safeLocalStorage(); + const ttsPlayer = createTTSPlayer(); const Markdown = dynamic(async () => (await import("./markdown")).Markdown, { @@ -1015,7 +1018,7 @@ function _Chat() { }; const doSubmit = (userInput: string) => { - if (userInput.trim() === "") return; + if (userInput.trim() === "" && isEmpty(attachImages)) return; const matchCommand = chatCommands.match(userInput); if (matchCommand.matched) { setUserInput(""); diff --git a/app/store/chat.ts b/app/store/chat.ts index 968d8cb6422..fc1fb23ba71 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -337,22 +337,16 @@ export const useChatStore = createPersistStore( if (attachImages && attachImages.length > 0) { mContent = [ - { - type: "text", - text: userContent, - }, + ...(userContent + ? [{ type: "text" as const, text: userContent }] + : []), + ...attachImages.map((url) => ({ + type: "image_url" as const, + image_url: { url }, + })), ]; - mContent = mContent.concat( - attachImages.map((url) => { - return { - type: "image_url", - image_url: { - url: url, - }, - }; - }), - ); } + let userMessage: ChatMessage = createMessage({ role: "user", content: mContent, From 77a58bc4b058ced13a99ddc593f544ec8f1603bb Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Wed, 9 Oct 2024 01:46:52 +0800 Subject: [PATCH 33/65] i18n: improve tw Traditional Chinese locale --- app/locales/tw.ts | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/app/locales/tw.ts b/app/locales/tw.ts index 7cb84670894..c800ad15d26 100644 --- a/app/locales/tw.ts +++ b/app/locales/tw.ts @@ -8,12 +8,12 @@ const tw = { Error: { Unauthorized: isApp ? `😆 對話遇到了一些問題,不用慌: - \\ 1️⃣ 想要零配置開箱即用,[點擊這裡立刻開啟對話 🚀](${SAAS_CHAT_UTM_URL}) - \\ 2️⃣ 如果你想消耗自己的 OpenAI 資源,點擊[這裡](/#/settings)修改設定 ⚙️` + \\ 1️⃣ 想要無須設定開箱即用,[點選這裡立刻開啟對話 🚀](${SAAS_CHAT_UTM_URL}) + \\ 2️⃣ 如果你想消耗自己的 OpenAI 資源,點選[這裡](/#/settings)修改設定 ⚙️` : `😆 對話遇到了一些問題,不用慌: - \ 1️⃣ 想要零配置開箱即用,[點擊這裡立刻開啟對話 🚀](${SAAS_CHAT_UTM_URL}) - \ 2️⃣ 如果你正在使用私有部署版本,點擊[這裡](/#/auth)輸入訪問秘鑰 🔑 - \ 3️⃣ 如果你想消耗自己的 OpenAI 資源,點擊[這裡](/#/settings)修改設定 ⚙️ + \ 1️⃣ 想要無須設定開箱即用,[點選這裡立刻開啟對話 🚀](${SAAS_CHAT_UTM_URL}) + \ 2️⃣ 如果你正在使用私有部署版本,點選[這裡](/#/auth)輸入存取金鑰 🔑 + \ 3️⃣ 如果你想消耗自己的 OpenAI 資源,點選[這裡](/#/settings)修改設定 ⚙️ `, }, @@ -25,9 +25,9 @@ const tw = { Confirm: "確認", Later: "稍候再說", Return: "返回", - SaasTips: "配置太麻煩,想要立即使用", + SaasTips: "設定太麻煩,想要立即使用", TopTips: - "🥳 NextChat AI 首發優惠,立刻解鎖 OpenAI o1, GPT-4o, Claude-3.5 等最新大模型", + "🥳 NextChat AI 首發優惠,立刻解鎖 OpenAI o1, GPT-4o, Claude-3.5 等最新的大型語言模型", }, ChatItem: { ChatItemCount: (count: number) => `${count} 則對話`, @@ -53,8 +53,8 @@ const tw = { PinToastAction: "檢視", Delete: "刪除", Edit: "編輯", - RefreshTitle: "刷新標題", - RefreshToast: "已發送刷新標題請求", + RefreshTitle: "重新整理標題", + RefreshToast: "已傳送重新整理標題請求", }, Commands: { new: "新建聊天", @@ -95,10 +95,10 @@ const tw = { IsContext: "預設提示詞", ShortcutKey: { Title: "鍵盤快捷方式", - newChat: "打開新聊天", + newChat: "開啟新聊天", focusInput: "聚焦輸入框", copyLastMessage: "複製最後一個回覆", - copyLastCode: "複製最後一個代碼塊", + copyLastCode: "複製最後一個程式碼區塊", showShortcutKey: "顯示快捷方式", }, }, @@ -174,9 +174,9 @@ const tw = { SubTitle: "聊天內容的字型大小", }, FontFamily: { - Title: "聊天字體", - SubTitle: "聊天內容的字體,若置空則應用全局默認字體", - Placeholder: "字體名稱", + Title: "聊天字型", + SubTitle: "聊天內容的字型,若留空則套用全域預設字型", + Placeholder: "字型名稱", }, InjectSystemPrompts: { Title: "匯入系統提示", @@ -301,8 +301,8 @@ const tw = { Title: "使用 NextChat AI", Label: "(性價比最高的方案)", SubTitle: - "由 NextChat 官方維護,零配置開箱即用,支持 OpenAI o1、GPT-4o、Claude-3.5 等最新大模型", - ChatNow: "立刻對話", + "由 NextChat 官方維護,無須設定開箱即用,支援 OpenAI o1、GPT-4o、Claude-3.5 等最新的大型語言模型", + ChatNow: "立刻開始對話", }, AccessCode: { @@ -485,18 +485,18 @@ const tw = { }, }, SearchChat: { - Name: "搜索", + Name: "搜尋", Page: { - Title: "搜索聊天記錄", - Search: "輸入搜索關鍵詞", + Title: "搜尋聊天記錄", + Search: "輸入搜尋關鍵詞", NoResult: "沒有找到結果", - NoData: "沒有數據", - Loading: "加載中", + NoData: "沒有資料", + Loading: "載入中", SubTitle: (count: number) => `找到 ${count} 條結果`, }, Item: { - View: "查看", + View: "檢視", }, }, NewChat: { From 6c1cbe120cb5f018bfc618c7c4382a696a1aa339 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 9 Oct 2024 11:46:49 +0800 Subject: [PATCH 34/65] update --- app/utils/stream.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utils/stream.ts b/app/utils/stream.ts index 2a8c13777e5..313ec4dd5b8 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -91,7 +91,7 @@ export function fetch(url: string, options?: RequestInit): Promise { headers, }); if (status >= 300) { - setTimeout(close, 50); + setTimeout(close, 100); } return response; }) From a925b424a8b02399d22ed05b3dc28631dbc03bc5 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 9 Oct 2024 13:42:25 +0800 Subject: [PATCH 35/65] fix compressModel, related #5426, fix #5606 #5603 #5575 --- app/store/chat.ts | 50 +++++++++++++++++++++++++++++++++++++++++---- app/store/config.ts | 8 ++++---- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/app/store/chat.ts b/app/store/chat.ts index 931cad76883..98163981cd3 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -16,6 +16,8 @@ import { DEFAULT_SYSTEM_TEMPLATE, KnowledgeCutOffDate, StoreKey, + SUMMARIZE_MODEL, + GEMINI_SUMMARIZE_MODEL, } from "../constant"; import Locale, { getLang } from "../locales"; import { isDalle3, safeLocalStorage } from "../utils"; @@ -23,6 +25,8 @@ import { prettyObject } from "../utils/format"; import { createPersistStore } from "../utils/store"; import { estimateTokenLength } from "../utils/token"; import { ModelConfig, ModelType, useAppConfig } from "./config"; +import { useAccessStore } from "./access"; +import { collectModelsWithDefaultModel } from "../utils/model"; import { createEmptyMask, Mask } from "./mask"; const localStorage = safeLocalStorage(); @@ -103,6 +107,29 @@ function createEmptySession(): ChatSession { }; } +function getSummarizeModel(currentModel: string, providerName: string) { + // if it is using gpt-* models, force to use 4o-mini to summarize + if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) { + const configStore = useAppConfig.getState(); + const accessStore = useAccessStore.getState(); + const allModel = collectModelsWithDefaultModel( + configStore.models, + [configStore.customModels, accessStore.customModels].join(","), + accessStore.defaultModel, + ); + const summarizeModel = allModel.find( + (m) => m.name === SUMMARIZE_MODEL && m.available, + ); + if (summarizeModel) { + return [summarizeModel.name, summarizeModel.providerName]; + } + } + if (currentModel.startsWith("gemini")) { + return [GEMINI_SUMMARIZE_MODEL, ServiceProvider.Google]; + } + return [currentModel, providerName]; +} + function countMessages(msgs: ChatMessage[]) { return msgs.reduce( (pre, cur) => pre + estimateTokenLength(getMessageTextContent(cur)), @@ -579,7 +606,13 @@ export const useChatStore = createPersistStore( return; } - const providerName = modelConfig.compressProviderName; + // if not config compressModel, then using getSummarizeModel + const [model, providerName] = modelConfig.compressModel + ? [modelConfig.compressModel, modelConfig.compressProviderName] + : getSummarizeModel( + session.mask.modelConfig.model, + session.mask.modelConfig.providerName, + ); const api: ClientApi = getClientApi(providerName); // remove error messages if any @@ -611,7 +644,7 @@ export const useChatStore = createPersistStore( api.llm.chat({ messages: topicMessages, config: { - model: modelConfig.compressModel, + model, stream: false, providerName, }, @@ -675,7 +708,8 @@ export const useChatStore = createPersistStore( config: { ...modelcfg, stream: true, - model: modelConfig.compressModel, + model, + providerName, }, onUpdate(message) { session.memoryPrompt = message; @@ -728,7 +762,7 @@ export const useChatStore = createPersistStore( }, { name: StoreKey.Chat, - version: 3.2, + version: 3.3, migrate(persistedState, version) { const state = persistedState as any; const newState = JSON.parse( @@ -784,6 +818,14 @@ export const useChatStore = createPersistStore( config.modelConfig.compressProviderName; }); } + // revert default summarize model for every session + if (version < 3.3) { + newState.sessions.forEach((s) => { + const config = useAppConfig.getState(); + s.mask.modelConfig.compressModel = undefined; + s.mask.modelConfig.compressProviderName = undefined; + }); + } return newState as any; }, diff --git a/app/store/config.ts b/app/store/config.ts index 3dcd4d86b80..c52ee3915b9 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -71,8 +71,8 @@ export const DEFAULT_CONFIG = { sendMemory: true, historyMessageCount: 4, compressMessageLengthThreshold: 1000, - compressModel: "gpt-4o-mini" as ModelType, - compressProviderName: "OpenAI" as ServiceProvider, + compressModel: undefined, + compressProviderName: undefined, enableInjectSystemPrompts: true, template: config?.template ?? DEFAULT_INPUT_TEMPLATE, size: "1024x1024" as DalleSize, @@ -178,7 +178,7 @@ export const useAppConfig = createPersistStore( }), { name: StoreKey.Config, - version: 4, + version: 4.1, merge(persistedState, currentState) { const state = persistedState as ChatConfig | undefined; @@ -231,7 +231,7 @@ export const useAppConfig = createPersistStore( : config?.template ?? DEFAULT_INPUT_TEMPLATE; } - if (version < 4) { + if (version < 4.1) { state.modelConfig.compressModel = DEFAULT_CONFIG.modelConfig.compressModel; state.modelConfig.compressProviderName = From 93ca303b6c981fd910a7320d8a3d78b335cea1d4 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 9 Oct 2024 13:49:33 +0800 Subject: [PATCH 36/65] fix ts error --- app/store/chat.ts | 17 ++++++++++++----- app/store/config.ts | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/store/chat.ts b/app/store/chat.ts index 98163981cd3..02adb26b3b9 100644 --- a/app/store/chat.ts +++ b/app/store/chat.ts @@ -18,6 +18,7 @@ import { StoreKey, SUMMARIZE_MODEL, GEMINI_SUMMARIZE_MODEL, + ServiceProvider, } from "../constant"; import Locale, { getLang } from "../locales"; import { isDalle3, safeLocalStorage } from "../utils"; @@ -107,7 +108,10 @@ function createEmptySession(): ChatSession { }; } -function getSummarizeModel(currentModel: string, providerName: string) { +function getSummarizeModel( + currentModel: string, + providerName: string, +): string[] { // if it is using gpt-* models, force to use 4o-mini to summarize if (currentModel.startsWith("gpt") || currentModel.startsWith("chatgpt")) { const configStore = useAppConfig.getState(); @@ -121,7 +125,10 @@ function getSummarizeModel(currentModel: string, providerName: string) { (m) => m.name === SUMMARIZE_MODEL && m.available, ); if (summarizeModel) { - return [summarizeModel.name, summarizeModel.providerName]; + return [ + summarizeModel.name, + summarizeModel.provider?.providerName as string, + ]; } } if (currentModel.startsWith("gemini")) { @@ -613,7 +620,7 @@ export const useChatStore = createPersistStore( session.mask.modelConfig.model, session.mask.modelConfig.providerName, ); - const api: ClientApi = getClientApi(providerName); + const api: ClientApi = getClientApi(providerName as ServiceProvider); // remove error messages if any const messages = session.messages; @@ -822,8 +829,8 @@ export const useChatStore = createPersistStore( if (version < 3.3) { newState.sessions.forEach((s) => { const config = useAppConfig.getState(); - s.mask.modelConfig.compressModel = undefined; - s.mask.modelConfig.compressProviderName = undefined; + s.mask.modelConfig.compressModel = ""; + s.mask.modelConfig.compressProviderName = ""; }); } diff --git a/app/store/config.ts b/app/store/config.ts index c52ee3915b9..f9ddce4a80c 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -71,8 +71,8 @@ export const DEFAULT_CONFIG = { sendMemory: true, historyMessageCount: 4, compressMessageLengthThreshold: 1000, - compressModel: undefined, - compressProviderName: undefined, + compressModel: "", + compressProviderName: "", enableInjectSystemPrompts: true, template: config?.template ?? DEFAULT_INPUT_TEMPLATE, size: "1024x1024" as DalleSize, From c0c8cdbbf37fdde5df0fba4adf6fce477dded75b Mon Sep 17 00:00:00 2001 From: DDMeaqua Date: Wed, 9 Oct 2024 14:36:58 +0800 Subject: [PATCH 37/65] =?UTF-8?q?fix:=20[#5574]=20=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- README_CN.md | 6 +++--- README_JA.md | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c72c791b264..4d19bb3252d 100644 --- a/README.md +++ b/README.md @@ -332,9 +332,9 @@ To control custom models, use `+` to add a custom model, use `-` to hide a model User `-all` to disable all default models, `+all` to enable all default models. -For Azure: use `modelName@azure=deploymentName` to customize model name and deployment name. -> Example: `+gpt-3.5-turbo@azure=gpt35` will show option `gpt35(Azure)` in model list. -> If you only can use Azure model, `-all,+gpt-3.5-turbo@azure=gpt35` will `gpt35(Azure)` the only option in model list. +For Azure: use `modelName@Azure=deploymentName` to customize model name and deployment name. +> Example: `+gpt-3.5-turbo@Azure=gpt35` will show option `gpt35(Azure)` in model list. +> If you only can use Azure model, `-all,+gpt-3.5-turbo@Azure=gpt35` will `gpt35(Azure)` the only option in model list. For ByteDance: use `modelName@bytedance=deploymentName` to customize model name and deployment name. > Example: `+Doubao-lite-4k@bytedance=ep-xxxxx-xxx` will show option `Doubao-lite-4k(ByteDance)` in model list. diff --git a/README_CN.md b/README_CN.md index c5d02477c2c..fa92f5f0776 100644 --- a/README_CN.md +++ b/README_CN.md @@ -216,9 +216,9 @@ ByteDance Api Url. 用来控制模型列表,使用 `+` 增加一个模型,使用 `-` 来隐藏一个模型,使用 `模型名=展示名` 来自定义模型的展示名,用英文逗号隔开。 -在Azure的模式下,支持使用`modelName@azure=deploymentName`的方式配置模型名称和部署名称(deploy-name) -> 示例:`+gpt-3.5-turbo@azure=gpt35`这个配置会在模型列表显示一个`gpt35(Azure)`的选项。 -> 如果你只能使用Azure模式,那么设置 `-all,+gpt-3.5-turbo@azure=gpt35` 则可以让对话的默认使用 `gpt35(Azure)` +在Azure的模式下,支持使用`modelName@Azure=deploymentName`的方式配置模型名称和部署名称(deploy-name) +> 示例:`+gpt-3.5-turbo@Azure=gpt35`这个配置会在模型列表显示一个`gpt35(Azure)`的选项。 +> 如果你只能使用Azure模式,那么设置 `-all,+gpt-3.5-turbo@Azure=gpt35` 则可以让对话的默认使用 `gpt35(Azure)` 在ByteDance的模式下,支持使用`modelName@bytedance=deploymentName`的方式配置模型名称和部署名称(deploy-name) > 示例: `+Doubao-lite-4k@bytedance=ep-xxxxx-xxx`这个配置会在模型列表显示一个`Doubao-lite-4k(ByteDance)`的选项 diff --git a/README_JA.md b/README_JA.md index 2b0a3ab782c..24a28686f34 100644 --- a/README_JA.md +++ b/README_JA.md @@ -207,8 +207,8 @@ ByteDance API の URL。 モデルリストを管理します。`+` でモデルを追加し、`-` でモデルを非表示にし、`モデル名=表示名` でモデルの表示名をカスタマイズし、カンマで区切ります。 -Azure モードでは、`modelName@azure=deploymentName` 形式でモデル名とデプロイ名(deploy-name)を設定できます。 -> 例:`+gpt-3.5-turbo@azure=gpt35` この設定でモデルリストに `gpt35(Azure)` のオプションが表示されます。 +Azure モードでは、`modelName@Azure=deploymentName` 形式でモデル名とデプロイ名(deploy-name)を設定できます。 +> 例:`+gpt-3.5-turbo@Azure=gpt35` この設定でモデルリストに `gpt35(Azure)` のオプションが表示されます。 ByteDance モードでは、`modelName@bytedance=deploymentName` 形式でモデル名とデプロイ名(deploy-name)を設定できます。 > 例: `+Doubao-lite-4k@bytedance=ep-xxxxx-xxx` この設定でモデルリストに `Doubao-lite-4k(ByteDance)` のオプションが表示されます。 From 4e9bb51d2fe648b429861a20c4c1048fb59ee283 Mon Sep 17 00:00:00 2001 From: ElricLiu <20209191+ElricLiu@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:43:49 +0800 Subject: [PATCH 38/65] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c284e987bf..b3472291d39 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ For enterprise inquiries, please contact: **business@nextchat.dev** 企业版咨询: **business@nextchat.dev** - + ## Features From 1dac02e4d63206213913f4abfe934f9c28727fb6 Mon Sep 17 00:00:00 2001 From: Lloyd Zhou Date: Wed, 9 Oct 2024 14:48:43 +0800 Subject: [PATCH 39/65] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3472291d39..aba21a5108b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ For enterprise inquiries, please contact: **business@nextchat.dev** 企业版咨询: **business@nextchat.dev** - + ## Features From 3e63d405c1b85b62ad7762af64318f92b05ebeb7 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 9 Oct 2024 16:12:01 +0800 Subject: [PATCH 40/65] update --- app/utils/stream.ts | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/app/utils/stream.ts b/app/utils/stream.ts index 313ec4dd5b8..2eda768f36f 100644 --- a/app/utils/stream.ts +++ b/app/utils/stream.ts @@ -28,7 +28,8 @@ export function fetch(url: string, options?: RequestInit): Promise { body = [], } = options || {}; let unlisten: Function | undefined; - let request_id = 0; + let setRequestId: Function | undefined; + const requestIdPromise = new Promise((resolve) => (setRequestId = resolve)); const ts = new TransformStream(); const writer = ts.writable.getWriter(); @@ -47,20 +48,22 @@ export function fetch(url: string, options?: RequestInit): Promise { } // @ts-ignore 2. listen response multi times, and write to Response.body window.__TAURI__.event - .listen("stream-response", (e: ResponseEvent) => { - const { request_id: rid, chunk, status } = e?.payload || {}; - if (request_id != rid) { - return; - } - if (chunk) { - writer.ready.then(() => { - writer.write(new Uint8Array(chunk)); - }); - } else if (status === 0) { - // end of body - close(); - } - }) + .listen("stream-response", (e: ResponseEvent) => + requestIdPromise.then((request_id) => { + const { request_id: rid, chunk, status } = e?.payload || {}; + if (request_id != rid) { + return; + } + if (chunk) { + writer.ready.then(() => { + writer.write(new Uint8Array(chunk)); + }); + } else if (status === 0) { + // end of body + close(); + } + }), + ) .then((u: Function) => (unlisten = u)); const headers: Record = { @@ -83,8 +86,8 @@ export function fetch(url: string, options?: RequestInit): Promise { : [], }) .then((res: StreamResponse) => { - request_id = res.request_id; - const { status, status_text: statusText, headers } = res; + const { request_id, status, status_text: statusText, headers } = res; + setRequestId?.(request_id); const response = new Response(ts.readable, { status, statusText, From 268cf3b6066d35f3f6d0acfbb066e07f2139c306 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Thu, 10 Oct 2024 12:47:25 +0800 Subject: [PATCH 41/65] hotfix plugin result is not string #5614 --- app/utils/chat.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/utils/chat.ts b/app/utils/chat.ts index 46f23263895..cf9b7af41d3 100644 --- a/app/utils/chat.ts +++ b/app/utils/chat.ts @@ -223,6 +223,11 @@ export function stream( ) .then((res) => { let content = res.data || res?.statusText; + // hotfix #5614 + content = + typeof content === "string" + ? content + : JSON.stringify(content); if (res.status >= 300) { return Promise.reject(content); } From 2eebfcf6fe873595a69ac0de805811fa7ed94f12 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Fri, 11 Oct 2024 11:29:22 +0800 Subject: [PATCH 42/65] client app tauri updater #2966 --- app/components/settings.tsx | 16 ++++++++++++---- app/global.d.ts | 7 +++++++ app/locales/cn.ts | 2 ++ app/locales/en.ts | 2 ++ app/store/update.ts | 2 ++ app/utils.ts | 23 +++++++++++++++++++++++ 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 9f338718e28..9ee919b8d7f 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -49,7 +49,7 @@ import Locale, { changeLang, getLang, } from "../locales"; -import { copyToClipboard } from "../utils"; +import { copyToClipboard, clientUpdate } from "../utils"; import Link from "next/link"; import { Anthropic, @@ -1357,9 +1357,17 @@ export function Settings() { {checkingUpdate ? ( ) : hasNewVersion ? ( - - {Locale.Settings.Update.GoToUpdate} - + clientConfig?.isApp ? ( + } + text={Locale.Settings.Update.GoToUpdate} + onClick={() => clientUpdate()} + /> + ) : ( + + {Locale.Settings.Update.GoToUpdate} + + ) ) : ( } diff --git a/app/global.d.ts b/app/global.d.ts index 8ee636bcd3c..897871fec37 100644 --- a/app/global.d.ts +++ b/app/global.d.ts @@ -26,6 +26,13 @@ declare interface Window { isPermissionGranted(): Promise; sendNotification(options: string | Options): void; }; + updater: { + checkUpdate(): Promise; + installUpdate(): Promise; + onUpdaterEvent( + handler: (status: UpdateStatusResult) => void, + ): Promise; + }; http: { fetch( url: string, diff --git a/app/locales/cn.ts b/app/locales/cn.ts index e5bcca0edbb..3086cc63e3e 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -205,6 +205,8 @@ const cn = { IsChecking: "正在检查更新...", FoundUpdate: (x: string) => `发现新版本:${x}`, GoToUpdate: "前往更新", + Success: "Update Succesfull.", + Failed: "Update Failed.", }, SendKey: "发送键", Theme: "主题", diff --git a/app/locales/en.ts b/app/locales/en.ts index 1204575224a..a025a522ff5 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -207,6 +207,8 @@ const en: LocaleType = { IsChecking: "Checking update...", FoundUpdate: (x: string) => `Found new version: ${x}`, GoToUpdate: "Update", + Success: "Update Succesfull.", + Failed: "Update Failed.", }, SendKey: "Send Key", Theme: "Theme", diff --git a/app/store/update.ts b/app/store/update.ts index e68fde369d5..327dc5e88f9 100644 --- a/app/store/update.ts +++ b/app/store/update.ts @@ -6,6 +6,7 @@ import { } from "../constant"; import { getClientConfig } from "../config/client"; import { createPersistStore } from "../utils/store"; +import { clientUpdate } from "../utils"; import ChatGptIcon from "../icons/chatgpt.png"; import Locale from "../locales"; import { ClientApi } from "../client/api"; @@ -119,6 +120,7 @@ export const useUpdateStore = createPersistStore( icon: `${ChatGptIcon.src}`, sound: "Default", }); + clientUpdate(); } } }); diff --git a/app/utils.ts b/app/utils.ts index 5d45017107c..9e75ffc7fc7 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -386,3 +386,26 @@ export function getOperationId(operation: { `${operation.method.toUpperCase()}${operation.path.replaceAll("/", "_")}` ); } + +export function clientUpdate() { + // this a wild for updating client app + return window.__TAURI__?.updater + .checkUpdate() + .then((updateResult) => { + if (updateResult.shouldUpdate) { + window.__TAURI__?.updater + .installUpdate() + .then((result) => { + showToast(Locale.Settings.Update.Success); + }) + .catch((e) => { + console.error("[Install Update Error]", e); + showToast(Locale.Settings.Update.Failed); + }); + } + }) + .catch((e) => { + console.error("[Check Update Error]", e); + showToast(Locale.Settings.Update.Failed); + }); +} From bd9de4dc4db95a6d9aca4567d6147cb5b55b38ab Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Fri, 11 Oct 2024 11:42:36 +0800 Subject: [PATCH 43/65] fix version compare --- app/components/settings.tsx | 4 ++-- app/utils.ts | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 9ee919b8d7f..c5653543cae 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -49,7 +49,7 @@ import Locale, { changeLang, getLang, } from "../locales"; -import { copyToClipboard, clientUpdate } from "../utils"; +import { copyToClipboard, clientUpdate, semverCompare } from "../utils"; import Link from "next/link"; import { Anthropic, @@ -585,7 +585,7 @@ export function Settings() { const [checkingUpdate, setCheckingUpdate] = useState(false); const currentVersion = updateStore.formatVersion(updateStore.version); const remoteId = updateStore.formatVersion(updateStore.remoteVersion); - const hasNewVersion = currentVersion !== remoteId; + const hasNewVersion = semverCompare(currentVersion, remoteId) === -1; const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL; function checkUpdate(force = false) { diff --git a/app/utils.ts b/app/utils.ts index 9e75ffc7fc7..9e9e90f66af 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -409,3 +409,14 @@ export function clientUpdate() { showToast(Locale.Settings.Update.Failed); }); } + +// https://gist.github.com/iwill/a83038623ba4fef6abb9efca87ae9ccb +export function semverCompare(a, b) { + if (a.startsWith(b + "-")) return -1; + if (b.startsWith(a + "-")) return 1; + return a.localeCompare(b, undefined, { + numeric: true, + sensitivity: "case", + caseFirst: "upper", + }); +} From a0d4a04192e2221f0ca969cab3236d4090a85955 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Fri, 11 Oct 2024 11:52:24 +0800 Subject: [PATCH 44/65] update --- app/locales/en.ts | 2 +- app/utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/locales/en.ts b/app/locales/en.ts index a025a522ff5..40471536ff9 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -207,7 +207,7 @@ const en: LocaleType = { IsChecking: "Checking update...", FoundUpdate: (x: string) => `Found new version: ${x}`, GoToUpdate: "Update", - Success: "Update Succesfull.", + Success: "Update Successful.", Failed: "Update Failed.", }, SendKey: "Send Key", diff --git a/app/utils.ts b/app/utils.ts index 9e9e90f66af..d8fc46330d1 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -411,7 +411,7 @@ export function clientUpdate() { } // https://gist.github.com/iwill/a83038623ba4fef6abb9efca87ae9ccb -export function semverCompare(a, b) { +export function semverCompare(a: string, b: string) { if (a.startsWith(b + "-")) return -1; if (b.startsWith(a + "-")) return 1; return a.localeCompare(b, undefined, { From be98aa20785c852ec8338090ed12798d34a50fba Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Fri, 11 Oct 2024 15:17:38 +0800 Subject: [PATCH 45/65] chore: improve test --- .github/workflows/test.yml | 23 +++++++++++++++++++++++ package.json | 8 ++++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000000..b2f37cfb436 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,23 @@ +name: Run Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + cache: "yarn" + + - name: Install dependencies + run: yarn install + + - name: Run Jest tests + run: yarn test:ci diff --git a/package.json b/package.json index 6db49241fbd..e433445342e 100644 --- a/package.json +++ b/package.json @@ -6,13 +6,13 @@ "mask": "npx tsx app/masks/build.ts", "mask:watch": "npx watch \"yarn mask\" app/masks", "dev": "concurrently -r \"yarn run mask:watch\" \"next dev\"", - "build": "yarn test:ci && yarn mask && cross-env BUILD_MODE=standalone next build", + "build": "yarn mask && cross-env BUILD_MODE=standalone next build", "start": "next start", "lint": "next lint", - "export": "yarn test:ci && yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", + "export": "yarn mask && cross-env BUILD_MODE=export BUILD_APP=1 next build", "export:dev": "concurrently -r \"yarn mask:watch\" \"cross-env BUILD_MODE=export BUILD_APP=1 next dev\"", "app:dev": "concurrently -r \"yarn mask:watch\" \"yarn tauri dev\"", - "app:build": "yarn test:ci && yarn mask && yarn tauri build", + "app:build": "yarn mask && yarn tauri build", "prompts": "node ./scripts/fetch-prompts.mjs", "prepare": "husky install", "proxy-dev": "sh ./scripts/init-proxy.sh && proxychains -f ./scripts/proxychains.conf yarn dev", @@ -88,4 +88,4 @@ "lint-staged/yaml": "^2.2.2" }, "packageManager": "yarn@1.22.19" -} \ No newline at end of file +} From bd43af3a8d57d06fd74ca6556641a7397e383684 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Fri, 11 Oct 2024 15:41:46 +0800 Subject: [PATCH 46/65] chore: cache node_modules --- .github/workflows/test.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2f37cfb436..fc885b29354 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,12 @@ name: Run Tests -on: [push, pull_request] +on: + push: + branches: + - main + tags: + - "!*" + pull_request: jobs: test: @@ -16,6 +22,14 @@ jobs: node-version: 18 cache: "yarn" + - name: Cache node_modules + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-node_modules- + - name: Install dependencies run: yarn install From c98dc31cdfd8bb92d11cc19cb577cb4d99356a72 Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 09:03:20 +0000 Subject: [PATCH 47/65] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E7=A0=81=E8=BE=93=E5=85=A5=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/auth.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/components/auth.tsx b/app/components/auth.tsx index e19512d8741..6c5e75d798d 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -11,6 +11,7 @@ import Logo from "../icons/logo.svg"; import { useMobileScreen } from "@/app/utils"; import BotIcon from "../icons/bot.svg"; import { getClientConfig } from "../config/client"; +import { PasswordInput } from "./ui-lib"; import LeftIcon from "@/app/icons/left.svg"; import { safeLocalStorage } from "@/app/utils"; import { @@ -60,17 +61,20 @@ export function AuthPage() {
{Locale.Auth.Title}
{Locale.Auth.Tips}
- { accessStore.update( (access) => (access.accessCode = e.currentTarget.value), ); }} /> + {!accessStore.hideUserApiKey ? ( <>
{Locale.Auth.SubTips}
From 4a7fd3a3803b229f6ecaeea03a0589017130470c Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:36:11 +0000 Subject: [PATCH 48/65] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A6=96=E9=A1=B5=20ap?= =?UTF-8?q?i=20=E8=BE=93=E5=85=A5=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/auth.tsx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/components/auth.tsx b/app/components/auth.tsx index 6c5e75d798d..539a52eecc9 100644 --- a/app/components/auth.tsx +++ b/app/components/auth.tsx @@ -78,22 +78,26 @@ export function AuthPage() { {!accessStore.hideUserApiKey ? ( <>
{Locale.Auth.SubTips}
- { accessStore.update( (access) => (access.openaiApiKey = e.currentTarget.value), ); }} /> - { accessStore.update( (access) => (access.googleApiKey = e.currentTarget.value), From 6792d6e475756b188f90c1f56d19188eabb7b55f Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:19:36 +0000 Subject: [PATCH 49/65] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E4=BD=BF=E8=83=BD/=E7=A6=81=E7=94=A8=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8A=98=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/markdown.tsx | 10 ++++++++-- app/components/mask.tsx | 17 +++++++++++++++++ app/components/settings.tsx | 15 +++++++++++++++ app/locales/cn.ts | 4 ++++ app/locales/en.ts | 5 +++++ app/store/config.ts | 2 ++ app/store/mask.ts | 1 + 7 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index a25b8537bc1..22664df8acc 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -169,6 +169,12 @@ export function PreCode(props: { children: any }) { } function CustomCode(props: { children: any; className?: string }) { + const chatStore = useChatStore(); + const session = chatStore.currentSession(); + const config = useAppConfig(); + const enableCodeFold = + session.mask?.enableCodeFold != false && config.enableCodeFold; + const ref = useRef(null); const [collapsed, setCollapsed] = useState(true); const [showToggle, setShowToggle] = useState(false); @@ -190,13 +196,13 @@ function CustomCode(props: { children: any; className?: string }) { className={props?.className} ref={ref} style={{ - maxHeight: collapsed ? "400px" : "none", + maxHeight: enableCodeFold && collapsed ? "400px" : "none", overflowY: "hidden", }} > {props.children} - {showToggle && collapsed && ( + {showToggle && enableCodeFold && collapsed && (
diff --git a/app/components/mask.tsx b/app/components/mask.tsx index c60e7a528fe..12b19e33514 100644 --- a/app/components/mask.tsx +++ b/app/components/mask.tsx @@ -183,6 +183,23 @@ export function MaskConfig(props: { > )} + {globalConfig.enableCodeFold && ( + + { + props.updateMask((mask) => { + mask.enableCodeFold = e.currentTarget.checked; + }); + }} + > + + )} {!props.shouldSyncFromGlobal ? ( + + + updateConfig( + (config) => (config.enableCodeFold = e.currentTarget.checked), + ) + } + > + diff --git a/app/locales/cn.ts b/app/locales/cn.ts index e5bcca0edbb..3ba8dd80b3e 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -665,6 +665,10 @@ const cn = { Title: "启用Artifacts", SubTitle: "启用之后可以直接渲染HTML页面", }, + CodeFold: { + Title: "启用CodeFold", + SubTitle: "启用之后可以折叠/展开过长的代码块", + }, Share: { Title: "分享此面具", SubTitle: "生成此面具的直达链接", diff --git a/app/locales/en.ts b/app/locales/en.ts index 1204575224a..40782be7ad0 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -675,6 +675,11 @@ const en: LocaleType = { Title: "Enable Artifacts", SubTitle: "Can render HTML page when enable artifacts.", }, + CodeFold: { + Title: "Enable CodeFold", + SubTitle: + "Automatically collapse/expand overly long code block when enable CodeFold", + }, Share: { Title: "Share This Mask", SubTitle: "Generate a link to this mask", diff --git a/app/store/config.ts b/app/store/config.ts index f9ddce4a80c..f14793c287a 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -52,6 +52,8 @@ export const DEFAULT_CONFIG = { enableArtifacts: true, // show artifacts config + enableCodeFold: true, // code fold config + disablePromptHint: false, dontShowMaskSplashScreen: false, // dont show splash screen when create chat diff --git a/app/store/mask.ts b/app/store/mask.ts index 0c74a892e56..850abeef6f4 100644 --- a/app/store/mask.ts +++ b/app/store/mask.ts @@ -19,6 +19,7 @@ export type Mask = { builtin: boolean; plugin?: string[]; enableArtifacts?: boolean; + enableCodeFold?: boolean; }; export const DEFAULT_MASK_STATE = { From 8fd843d228e75068c1233738d4ce6507e2bddc4c Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:38:52 +0000 Subject: [PATCH 50/65] =?UTF-8?q?=E5=8F=82=E8=80=83coderabbitai=E5=BB=BA?= =?UTF-8?q?=E8=AE=AE=E8=A7=84=E8=8C=83=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/markdown.tsx | 19 ++++++++++++------- app/components/settings.tsx | 1 + app/locales/cn.ts | 4 ++-- app/locales/en.ts | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 22664df8acc..8e744b441d0 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -190,6 +190,16 @@ function CustomCode(props: { children: any; className?: string }) { const toggleCollapsed = () => { setCollapsed((collapsed) => !collapsed); }; + const renderShowMoreButton = () => { + if (showToggle && enableCodeFold && collapsed) { + return ( +
+ +
+ ); + } + return null; + }; return ( <> {props.children} - {showToggle && enableCodeFold && collapsed && ( -
- -
- )} + + {renderShowMoreButton()} ); } diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 5f478374edf..e2464481341 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -1517,6 +1517,7 @@ export function Settings() { aria-label={Locale.Mask.Config.CodeFold.Title} type="checkbox" checked={config.enableCodeFold} + data-testid="enable-code-fold-checkbox" onChange={(e) => updateConfig( (config) => (config.enableCodeFold = e.currentTarget.checked), diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 3ba8dd80b3e..09eafe492c7 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -666,8 +666,8 @@ const cn = { SubTitle: "启用之后可以直接渲染HTML页面", }, CodeFold: { - Title: "启用CodeFold", - SubTitle: "启用之后可以折叠/展开过长的代码块", + Title: "启用代码折叠", + SubTitle: "启用之后可以自动折叠/展开过长的代码块", }, Share: { Title: "分享此面具", diff --git a/app/locales/en.ts b/app/locales/en.ts index 40782be7ad0..8dfe8ed9348 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -678,7 +678,7 @@ const en: LocaleType = { CodeFold: { Title: "Enable CodeFold", SubTitle: - "Automatically collapse/expand overly long code block when enable CodeFold", + "Automatically collapse/expand overly long code blocks when CodeFold is enabled", }, Share: { Title: "Share This Mask", From 4a1319f2c0db25e5609553e2938761a4455ff6b8 Mon Sep 17 00:00:00 2001 From: code-october <148516338+code-october@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:57:23 +0000 Subject: [PATCH 51/65] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/markdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/markdown.tsx b/app/components/markdown.tsx index 8e744b441d0..9841a196d27 100644 --- a/app/components/markdown.tsx +++ b/app/components/markdown.tsx @@ -173,7 +173,7 @@ function CustomCode(props: { children: any; className?: string }) { const session = chatStore.currentSession(); const config = useAppConfig(); const enableCodeFold = - session.mask?.enableCodeFold != false && config.enableCodeFold; + session.mask?.enableCodeFold !== false && config.enableCodeFold; const ref = useRef(null); const [collapsed, setCollapsed] = useState(true); @@ -212,7 +212,7 @@ function CustomCode(props: { children: any; className?: string }) { > {props.children} - + {renderShowMoreButton()} ); From 819238acaf5114329168f2c95da74d747795daa1 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Fri, 11 Oct 2024 20:49:43 +0800 Subject: [PATCH 52/65] fix: i18n --- app/locales/cn.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 3086cc63e3e..1e0116ec915 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -205,8 +205,8 @@ const cn = { IsChecking: "正在检查更新...", FoundUpdate: (x: string) => `发现新版本:${x}`, GoToUpdate: "前往更新", - Success: "Update Succesfull.", - Failed: "Update Failed.", + Success: "更新成功!", + Failed: "更新失败", }, SendKey: "发送键", Theme: "主题", From 9961b513cc0bfa1db8e1865af4099fdd9b78c15d Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Sat, 12 Oct 2024 14:54:22 +0800 Subject: [PATCH 53/65] fix: sidebar style --- app/components/home.module.scss | 3 +++ app/components/sidebar.tsx | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/components/home.module.scss b/app/components/home.module.scss index b31334568dd..381b6a9b951 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -140,6 +140,9 @@ display: flex; justify-content: space-between; align-items: center; + &-narrow { + justify-content: center; + } } .sidebar-logo { diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index 493b1103beb..2a5c308b78c 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -165,11 +165,17 @@ export function SideBarHeader(props: { subTitle?: string | React.ReactNode; logo?: React.ReactNode; children?: React.ReactNode; + shouldNarrow?: boolean; }) { - const { title, subTitle, logo, children } = props; + const { title, subTitle, logo, children, shouldNarrow } = props; return ( -
+
{title} @@ -227,6 +233,7 @@ export function SideBar(props: { className?: string }) { title="NextChat" subTitle="Build your own AI assistant." logo={} + shouldNarrow={shouldNarrow} >
Date: Sat, 12 Oct 2024 16:49:24 +0000 Subject: [PATCH 54/65] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E2=80=9C=E5=8E=8B?= =?UTF-8?q?=E7=BC=A9=E6=A8=A1=E5=9E=8B=E2=80=9D=E5=90=8D=E7=A7=B0=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E2=80=9C=E7=94=9F=E6=88=90=E5=AF=B9=E8=AF=9D?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E2=80=9D=E7=9A=84=E5=8A=9F=E8=83=BD=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/locales/cn.ts | 4 ++-- app/locales/en.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/locales/cn.ts b/app/locales/cn.ts index 09eafe492c7..b7debe80514 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -495,8 +495,8 @@ const cn = { Model: "模型 (model)", CompressModel: { - Title: "压缩模型", - SubTitle: "用于压缩历史记录的模型", + Title: "对话摘要模型", + SubTitle: "用于压缩历史记录、生成对话标题的模型", }, Temperature: { Title: "随机性 (temperature)", diff --git a/app/locales/en.ts b/app/locales/en.ts index 8dfe8ed9348..5cc296f1efd 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -500,8 +500,8 @@ const en: LocaleType = { Model: "Model", CompressModel: { - Title: "Compression Model", - SubTitle: "Model used to compress history", + Title: "Summary Model", + SubTitle: "Model used to compress history and generate title", }, Temperature: { Title: "Temperature", From 12e7caa20977d8fbee2d16ec3d33ae3d94472603 Mon Sep 17 00:00:00 2001 From: ccq18 <348578429@qq.com> Date: Mon, 14 Oct 2024 16:03:01 +0800 Subject: [PATCH 55/65] =?UTF-8?q?fix=20=E9=BB=98=E8=AE=A4=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E6=97=B6=E9=97=B4=E6=94=B9=E4=B8=BA3=E5=88=86?= =?UTF-8?q?=E9=92=9F=EF=BC=8C=E6=94=AF=E6=8C=81o1-mini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/constant.ts b/app/constant.ts index a06b8f05062..85637051165 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -95,7 +95,7 @@ export const UNFINISHED_INPUT = (id: string) => "unfinished-input-" + id; export const STORAGE_KEY = "chatgpt-next-web"; -export const REQUEST_TIMEOUT_MS = 60000; +export const REQUEST_TIMEOUT_MS = 180000; export const EXPORT_MESSAGE_CLASS_NAME = "export-markdown"; From 592f62005b474b78042a373cbfd7361f3de9b323 Mon Sep 17 00:00:00 2001 From: ccq18 <348578429@qq.com> Date: Mon, 14 Oct 2024 16:31:17 +0800 Subject: [PATCH 56/65] =?UTF-8?q?=E4=BB=85=E4=BF=AE=E6=94=B9o1=E7=9A=84?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E6=97=B6=E9=97=B4=E4=B8=BA4=E5=88=86?= =?UTF-8?q?=E9=92=9F=EF=BC=8C=E5=87=8F=E5=B0=91o1=E7=B3=BB=E5=88=97?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=AF=B7=E6=B1=82=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/client/platforms/openai.ts | 2 +- app/constant.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index a2263361143..76bac59e876 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -352,7 +352,7 @@ export class ChatGPTApi implements LLMApi { // make a fetch request const requestTimeoutId = setTimeout( () => controller.abort(), - isDalle3 || isO1 ? REQUEST_TIMEOUT_MS * 2 : REQUEST_TIMEOUT_MS, // dalle3 using b64_json is slow. + isDalle3 || isO1 ? REQUEST_TIMEOUT_MS * 4 : REQUEST_TIMEOUT_MS, // dalle3 using b64_json is slow. ); const res = await fetch(chatPath, chatPayload); diff --git a/app/constant.ts b/app/constant.ts index 85637051165..a06b8f05062 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -95,7 +95,7 @@ export const UNFINISHED_INPUT = (id: string) => "unfinished-input-" + id; export const STORAGE_KEY = "chatgpt-next-web"; -export const REQUEST_TIMEOUT_MS = 180000; +export const REQUEST_TIMEOUT_MS = 60000; export const EXPORT_MESSAGE_CLASS_NAME = "export-markdown"; From 8c39a687b5d8bb44dfcc103ac69910d97220bea7 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 14 Oct 2024 16:53:46 +0800 Subject: [PATCH 57/65] update deploy_preview run target --- .github/workflows/deploy_preview.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy_preview.yml b/.github/workflows/deploy_preview.yml index 30d9b85b44c..b988452433b 100644 --- a/.github/workflows/deploy_preview.yml +++ b/.github/workflows/deploy_preview.yml @@ -3,9 +3,7 @@ name: VercelPreviewDeployment on: pull_request_target: types: - - opened - - synchronize - - reopened + - review_requested env: VERCEL_TEAM: ${{ secrets.VERCEL_TEAM }} From 103106bb9371748b3f1ab3f304846546297657cc Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 14 Oct 2024 17:09:56 +0800 Subject: [PATCH 58/65] update test run target --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc885b29354..faf7205d9cb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,8 @@ on: tags: - "!*" pull_request: + types: + - review_requested jobs: test: From 7f454cbcec0d5c735726808ccbe75ba897142a31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:49:46 +0000 Subject: [PATCH 59/65] Bump @types/jest from 29.5.12 to 29.5.13 Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.5.12 to 29.5.13. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest) --- updated-dependencies: - dependency-name: "@types/jest" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e433445342e..803c0d1a4cb 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@tauri-apps/cli": "1.5.11", "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", - "@types/jest": "^29.5.12", + "@types/jest": "^29.5.13", "@types/js-yaml": "4.0.9", "@types/lodash-es": "^4.17.12", "@types/node": "^20.11.30", diff --git a/yarn.lock b/yarn.lock index 0f6a29d6d78..ef296924e09 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2263,10 +2263,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.12": - version "29.5.12" - resolved "https://registry.npmmirror.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== +"@types/jest@^29.5.13": + version "29.5.13" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.13.tgz#8bc571659f401e6a719a7bf0dbcb8b78c71a8adc" + integrity sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg== dependencies: expect "^29.0.0" pretty-format "^29.0.0" From 87d85c10c3b3dcd7a62e174dabb6338f005ce9b7 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Mon, 14 Oct 2024 21:48:36 +0800 Subject: [PATCH 60/65] update --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index cc137ee8afd..56a5b46a9e6 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -99,7 +99,7 @@ "endpoints": [ "https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web/releases/latest/download/latest.json" ], - "dialog": false, + "dialog": true, "windows": { "installMode": "passive" }, From 463fa743e987624ab357c4335de0b133ccfa8fd0 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Tue, 15 Oct 2024 16:10:44 +0800 Subject: [PATCH 61/65] update version --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 56a5b46a9e6..b2c3e04b07b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "NextChat", - "version": "2.15.4" + "version": "2.15.5" }, "tauri": { "allowlist": { From deb1e76c41ec156450db10872f88f84d2865d450 Mon Sep 17 00:00:00 2001 From: Dogtiti <499960698@qq.com> Date: Wed, 16 Oct 2024 21:57:07 +0800 Subject: [PATCH 62/65] fix: use tauri fetch --- app/client/platforms/anthropic.ts | 1 + app/client/platforms/moonshot.ts | 1 + app/client/platforms/openai.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/app/client/platforms/anthropic.ts b/app/client/platforms/anthropic.ts index 1a83bd53aa1..3645cbe6eac 100644 --- a/app/client/platforms/anthropic.ts +++ b/app/client/platforms/anthropic.ts @@ -13,6 +13,7 @@ import { getMessageTextContent, isVisionModel } from "@/app/utils"; import { preProcessImageContent, stream } from "@/app/utils/chat"; import { cloudflareAIGatewayUrl } from "@/app/utils/cloudflare"; import { RequestPayload } from "./openai"; +import { fetch } from "@/app/utils/stream"; export type MultiBlockContent = { type: "image" | "text"; diff --git a/app/client/platforms/moonshot.ts b/app/client/platforms/moonshot.ts index e0ef3494fe7..22a34b2e22f 100644 --- a/app/client/platforms/moonshot.ts +++ b/app/client/platforms/moonshot.ts @@ -24,6 +24,7 @@ import { import { getClientConfig } from "@/app/config/client"; import { getMessageTextContent } from "@/app/utils"; import { RequestPayload } from "./openai"; +import { fetch } from "@/app/utils/stream"; export class MoonshotApi implements LLMApi { private disableListModels = true; diff --git a/app/client/platforms/openai.ts b/app/client/platforms/openai.ts index 76bac59e876..30f7415c141 100644 --- a/app/client/platforms/openai.ts +++ b/app/client/platforms/openai.ts @@ -42,6 +42,7 @@ import { isVisionModel, isDalle3 as _isDalle3, } from "@/app/utils"; +import { fetch } from "@/app/utils/stream"; export interface OpenAIListModelResponse { object: string; From 8455fefc8aeada7e4204099f1548908320c4c1b7 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 23 Oct 2024 11:40:06 +0800 Subject: [PATCH 63/65] add xai --- app/api/[provider]/[...path]/route.ts | 3 + app/api/auth.ts | 5 +- app/api/xai.ts | 128 +++++++++++++++++ app/client/api.ts | 10 ++ app/client/platforms/xai.ts | 195 ++++++++++++++++++++++++++ app/components/settings.tsx | 41 ++++++ app/config/server.ts | 9 ++ app/constant.ts | 23 +++ app/locales/cn.ts | 11 ++ app/locales/en.ts | 11 ++ app/store/access.ts | 12 ++ 11 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 app/api/xai.ts create mode 100644 app/client/platforms/xai.ts diff --git a/app/api/[provider]/[...path]/route.ts b/app/api/[provider]/[...path]/route.ts index dffb3e9daa4..5ac248d0c87 100644 --- a/app/api/[provider]/[...path]/route.ts +++ b/app/api/[provider]/[...path]/route.ts @@ -10,6 +10,7 @@ import { handle as alibabaHandler } from "../../alibaba"; import { handle as moonshotHandler } from "../../moonshot"; import { handle as stabilityHandler } from "../../stability"; import { handle as iflytekHandler } from "../../iflytek"; +import { handle as xaiHandler } from "../../xai"; import { handle as proxyHandler } from "../../proxy"; async function handle( @@ -38,6 +39,8 @@ async function handle( return stabilityHandler(req, { params }); case ApiPath.Iflytek: return iflytekHandler(req, { params }); + case ApiPath.XAI: + return xaiHandler(req, { params }); case ApiPath.OpenAI: return openaiHandler(req, { params }); default: diff --git a/app/api/auth.ts b/app/api/auth.ts index 95965ceec2d..fb147cf51f5 100644 --- a/app/api/auth.ts +++ b/app/api/auth.ts @@ -92,6 +92,9 @@ export function auth(req: NextRequest, modelProvider: ModelProvider) { systemApiKey = serverConfig.iflytekApiKey + ":" + serverConfig.iflytekApiSecret; break; + case ModelProvider.XAI: + systemApiKey = serverConfig.xaiApiKey; + break; case ModelProvider.GPT: default: if (req.nextUrl.pathname.includes("azure/deployments")) { @@ -102,7 +105,7 @@ export function auth(req: NextRequest, modelProvider: ModelProvider) { } if (systemApiKey) { - console.log("[Auth] use system api key"); + console.log("[Auth] use system api key", systemApiKey); req.headers.set("Authorization", `Bearer ${systemApiKey}`); } else { console.log("[Auth] admin did not provide an api key"); diff --git a/app/api/xai.ts b/app/api/xai.ts new file mode 100644 index 00000000000..a4ee8b39731 --- /dev/null +++ b/app/api/xai.ts @@ -0,0 +1,128 @@ +import { getServerSideConfig } from "@/app/config/server"; +import { + XAI_BASE_URL, + ApiPath, + ModelProvider, + ServiceProvider, +} from "@/app/constant"; +import { prettyObject } from "@/app/utils/format"; +import { NextRequest, NextResponse } from "next/server"; +import { auth } from "@/app/api/auth"; +import { isModelAvailableInServer } from "@/app/utils/model"; + +const serverConfig = getServerSideConfig(); + +export async function handle( + req: NextRequest, + { params }: { params: { path: string[] } }, +) { + console.log("[XAI Route] params ", params); + + if (req.method === "OPTIONS") { + return NextResponse.json({ body: "OK" }, { status: 200 }); + } + + const authResult = auth(req, ModelProvider.XAI); + if (authResult.error) { + return NextResponse.json(authResult, { + status: 401, + }); + } + + try { + const response = await request(req); + return response; + } catch (e) { + console.error("[XAI] ", e); + return NextResponse.json(prettyObject(e)); + } +} + +async function request(req: NextRequest) { + const controller = new AbortController(); + + // alibaba use base url or just remove the path + let path = `${req.nextUrl.pathname}`.replaceAll(ApiPath.XAI, ""); + + let baseUrl = serverConfig.xaiUrl || XAI_BASE_URL; + + if (!baseUrl.startsWith("http")) { + baseUrl = `https://${baseUrl}`; + } + + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.slice(0, -1); + } + + console.log("[Proxy] ", path); + console.log("[Base Url]", baseUrl); + + const timeoutId = setTimeout( + () => { + controller.abort(); + }, + 10 * 60 * 1000, + ); + + const fetchUrl = `${baseUrl}${path}`; + const fetchOptions: RequestInit = { + headers: { + "Content-Type": "application/json", + Authorization: req.headers.get("Authorization") ?? "", + }, + method: req.method, + body: req.body, + redirect: "manual", + // @ts-ignore + duplex: "half", + signal: controller.signal, + }; + + // #1815 try to refuse some request to some models + if (serverConfig.customModels && req.body) { + try { + const clonedBody = await req.text(); + fetchOptions.body = clonedBody; + + const jsonBody = JSON.parse(clonedBody) as { model?: string }; + + // not undefined and is false + if ( + isModelAvailableInServer( + serverConfig.customModels, + jsonBody?.model as string, + ServiceProvider.XAI as string, + ) + ) { + return NextResponse.json( + { + error: true, + message: `you are not allowed to use ${jsonBody?.model} model`, + }, + { + status: 403, + }, + ); + } + } catch (e) { + console.error(`[XAI] filter`, e); + } + } + try { + const res = await fetch(fetchUrl, fetchOptions); + + // to prevent browser prompt for credentials + const newHeaders = new Headers(res.headers); + newHeaders.delete("www-authenticate"); + // to disable nginx buffering + newHeaders.set("X-Accel-Buffering", "no"); + + return new Response(res.body, { + status: res.status, + statusText: res.statusText, + headers: newHeaders, + }); + } finally { + clearTimeout(timeoutId); + } +} diff --git a/app/client/api.ts b/app/client/api.ts index 7a242ea99dd..4238c2a264b 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -20,6 +20,7 @@ import { QwenApi } from "./platforms/alibaba"; import { HunyuanApi } from "./platforms/tencent"; import { MoonshotApi } from "./platforms/moonshot"; import { SparkApi } from "./platforms/iflytek"; +import { XAIApi } from "./platforms/xai"; export const ROLES = ["system", "user", "assistant"] as const; export type MessageRole = (typeof ROLES)[number]; @@ -152,6 +153,9 @@ export class ClientApi { case ModelProvider.Iflytek: this.llm = new SparkApi(); break; + case ModelProvider.XAI: + this.llm = new XAIApi(); + break; default: this.llm = new ChatGPTApi(); } @@ -239,6 +243,7 @@ export function getHeaders(ignoreHeaders: boolean = false) { const isAlibaba = modelConfig.providerName === ServiceProvider.Alibaba; const isMoonshot = modelConfig.providerName === ServiceProvider.Moonshot; const isIflytek = modelConfig.providerName === ServiceProvider.Iflytek; + const isXAI = modelConfig.providerName === ServiceProvider.XAI; const isEnabledAccessControl = accessStore.enabledAccessControl(); const apiKey = isGoogle ? accessStore.googleApiKey @@ -252,6 +257,8 @@ export function getHeaders(ignoreHeaders: boolean = false) { ? accessStore.alibabaApiKey : isMoonshot ? accessStore.moonshotApiKey + : isXAI + ? accessStore.xaiApiKey : isIflytek ? accessStore.iflytekApiKey && accessStore.iflytekApiSecret ? accessStore.iflytekApiKey + ":" + accessStore.iflytekApiSecret @@ -266,6 +273,7 @@ export function getHeaders(ignoreHeaders: boolean = false) { isAlibaba, isMoonshot, isIflytek, + isXAI, apiKey, isEnabledAccessControl, }; @@ -328,6 +336,8 @@ export function getClientApi(provider: ServiceProvider): ClientApi { return new ClientApi(ModelProvider.Moonshot); case ServiceProvider.Iflytek: return new ClientApi(ModelProvider.Iflytek); + case ServiceProvider.XAI: + return new ClientApi(ModelProvider.XAI); default: return new ClientApi(ModelProvider.GPT); } diff --git a/app/client/platforms/xai.ts b/app/client/platforms/xai.ts new file mode 100644 index 00000000000..69f80e9fc26 --- /dev/null +++ b/app/client/platforms/xai.ts @@ -0,0 +1,195 @@ +"use client"; +// azure and openai, using same models. so using same LLMApi. +import { ApiPath, XAI_BASE_URL, XAI, REQUEST_TIMEOUT_MS } from "@/app/constant"; +import { + useAccessStore, + useAppConfig, + useChatStore, + ChatMessageTool, + usePluginStore, +} from "@/app/store"; +import { stream } from "@/app/utils/chat"; +import { + ChatOptions, + getHeaders, + LLMApi, + LLMModel, + SpeechOptions, +} from "../api"; +import { getClientConfig } from "@/app/config/client"; +import { getMessageTextContent } from "@/app/utils"; +import { RequestPayload } from "./openai"; +import { fetch } from "@/app/utils/stream"; + +export class XAIApi implements LLMApi { + private disableListModels = true; + + path(path: string): string { + const accessStore = useAccessStore.getState(); + + let baseUrl = ""; + + if (accessStore.useCustomConfig) { + baseUrl = accessStore.xaiUrl; + } + + if (baseUrl.length === 0) { + const isApp = !!getClientConfig()?.isApp; + const apiPath = ApiPath.XAI; + baseUrl = isApp ? XAI_BASE_URL : apiPath; + } + + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.slice(0, baseUrl.length - 1); + } + if (!baseUrl.startsWith("http") && !baseUrl.startsWith(ApiPath.XAI)) { + baseUrl = "https://" + baseUrl; + } + + console.log("[Proxy Endpoint] ", baseUrl, path); + + return [baseUrl, path].join("/"); + } + + extractMessage(res: any) { + return res.choices?.at(0)?.message?.content ?? ""; + } + + speech(options: SpeechOptions): Promise { + throw new Error("Method not implemented."); + } + + async chat(options: ChatOptions) { + const messages: ChatOptions["messages"] = []; + for (const v of options.messages) { + const content = getMessageTextContent(v); + messages.push({ role: v.role, content }); + } + + const modelConfig = { + ...useAppConfig.getState().modelConfig, + ...useChatStore.getState().currentSession().mask.modelConfig, + ...{ + model: options.config.model, + providerName: options.config.providerName, + }, + }; + + const requestPayload: RequestPayload = { + messages, + stream: options.config.stream, + model: modelConfig.model, + temperature: modelConfig.temperature, + presence_penalty: modelConfig.presence_penalty, + frequency_penalty: modelConfig.frequency_penalty, + top_p: modelConfig.top_p, + // max_tokens: Math.max(modelConfig.max_tokens, 1024), + // Please do not ask me why not send max_tokens, no reason, this param is just shit, I dont want to explain anymore. + }; + + console.log("[Request] openai payload: ", requestPayload); + + const shouldStream = !!options.config.stream; + const controller = new AbortController(); + options.onController?.(controller); + + try { + const chatPath = this.path(XAI.ChatPath); + const chatPayload = { + method: "POST", + body: JSON.stringify(requestPayload), + signal: controller.signal, + headers: getHeaders(), + }; + + // make a fetch request + const requestTimeoutId = setTimeout( + () => controller.abort(), + REQUEST_TIMEOUT_MS, + ); + + if (shouldStream) { + const [tools, funcs] = usePluginStore + .getState() + .getAsTools( + useChatStore.getState().currentSession().mask?.plugin || [], + ); + return stream( + chatPath, + requestPayload, + getHeaders(), + tools as any, + funcs, + controller, + // parseSSE + (text: string, runTools: ChatMessageTool[]) => { + // console.log("parseSSE", text, runTools); + const json = JSON.parse(text); + const choices = json.choices as Array<{ + delta: { + content: string; + tool_calls: ChatMessageTool[]; + }; + }>; + const tool_calls = choices[0]?.delta?.tool_calls; + if (tool_calls?.length > 0) { + const index = tool_calls[0]?.index; + const id = tool_calls[0]?.id; + const args = tool_calls[0]?.function?.arguments; + if (id) { + runTools.push({ + id, + type: tool_calls[0]?.type, + function: { + name: tool_calls[0]?.function?.name as string, + arguments: args, + }, + }); + } else { + // @ts-ignore + runTools[index]["function"]["arguments"] += args; + } + } + return choices[0]?.delta?.content; + }, + // processToolMessage, include tool_calls message and tool call results + ( + requestPayload: RequestPayload, + toolCallMessage: any, + toolCallResult: any[], + ) => { + // @ts-ignore + requestPayload?.messages?.splice( + // @ts-ignore + requestPayload?.messages?.length, + 0, + toolCallMessage, + ...toolCallResult, + ); + }, + options, + ); + } else { + const res = await fetch(chatPath, chatPayload); + clearTimeout(requestTimeoutId); + + const resJson = await res.json(); + const message = this.extractMessage(resJson); + options.onFinish(message); + } + } catch (e) { + console.log("[Request] failed to make a chat request", e); + options.onError?.(e as Error); + } + } + async usage() { + return { + used: 0, + total: 0, + }; + } + + async models(): Promise { + return []; + } +} diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 82ce70e5a18..6ce71b5ef34 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -59,6 +59,7 @@ import { ByteDance, Alibaba, Moonshot, + XAI, Google, GoogleSafetySettingsThreshold, OPENAI_BASE_URL, @@ -1194,6 +1195,45 @@ export function Settings() { ); + const XAIConfigComponent = accessStore.provider === ServiceProvider.XAI && ( + <> + + + accessStore.update( + (access) => (access.moonshotUrl = e.currentTarget.value), + ) + } + > + + + { + accessStore.update( + (access) => (access.moonshotApiKey = e.currentTarget.value), + ); + }} + /> + + + ); + const stabilityConfigComponent = accessStore.provider === ServiceProvider.Stability && ( <> @@ -1652,6 +1692,7 @@ export function Settings() { {moonshotConfigComponent} {stabilityConfigComponent} {lflytekConfigComponent} + {XAIConfigComponent} )} diff --git a/app/config/server.ts b/app/config/server.ts index 6544fe5641d..eac4ba0cf33 100644 --- a/app/config/server.ts +++ b/app/config/server.ts @@ -71,6 +71,10 @@ declare global { IFLYTEK_API_KEY?: string; IFLYTEK_API_SECRET?: string; + // xai only + XAI_URL?: string; + XAI_API_KEY?: string; + // custom template for preprocessing user input DEFAULT_INPUT_TEMPLATE?: string; } @@ -146,6 +150,7 @@ export const getServerSideConfig = () => { const isAlibaba = !!process.env.ALIBABA_API_KEY; const isMoonshot = !!process.env.MOONSHOT_API_KEY; const isIflytek = !!process.env.IFLYTEK_API_KEY; + const isXAI = !!process.env.XAI_API_KEY; // const apiKeyEnvVar = process.env.OPENAI_API_KEY ?? ""; // const apiKeys = apiKeyEnvVar.split(",").map((v) => v.trim()); // const randomIndex = Math.floor(Math.random() * apiKeys.length); @@ -208,6 +213,10 @@ export const getServerSideConfig = () => { iflytekApiKey: process.env.IFLYTEK_API_KEY, iflytekApiSecret: process.env.IFLYTEK_API_SECRET, + isXAI, + xaiUrl: process.env.XAI_URL, + xaiApiKey: getApiKey(process.env.XAI_API_KEY), + cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID, cloudflareKVNamespaceId: process.env.CLOUDFLARE_KV_NAMESPACE_ID, cloudflareKVApiKey: getApiKey(process.env.CLOUDFLARE_KV_API_KEY), diff --git a/app/constant.ts b/app/constant.ts index a06b8f05062..9774bb594dd 100644 --- a/app/constant.ts +++ b/app/constant.ts @@ -28,6 +28,8 @@ export const TENCENT_BASE_URL = "https://hunyuan.tencentcloudapi.com"; export const MOONSHOT_BASE_URL = "https://api.moonshot.cn"; export const IFLYTEK_BASE_URL = "https://spark-api-open.xf-yun.com"; +export const XAI_BASE_URL = "https://api.x.ai"; + export const CACHE_URL_PREFIX = "/api/cache"; export const UPLOAD_URL = `${CACHE_URL_PREFIX}/upload`; @@ -59,6 +61,7 @@ export enum ApiPath { Iflytek = "/api/iflytek", Stability = "/api/stability", Artifacts = "/api/artifacts", + XAI = "/api/xai", } export enum SlotID { @@ -111,6 +114,7 @@ export enum ServiceProvider { Moonshot = "Moonshot", Stability = "Stability", Iflytek = "Iflytek", + XAI = "XAI", } // Google API safety settings, see https://ai.google.dev/gemini-api/docs/safety-settings @@ -133,6 +137,7 @@ export enum ModelProvider { Hunyuan = "Hunyuan", Moonshot = "Moonshot", Iflytek = "Iflytek", + XAI = "XAI", } export const Stability = { @@ -215,6 +220,11 @@ export const Iflytek = { ChatPath: "v1/chat/completions", }; +export const XAI = { + ExampleEndpoint: XAI_BASE_URL, + ChatPath: "v1/chat/completions", +}; + export const DEFAULT_INPUT_TEMPLATE = `{{input}}`; // input / time / model / lang // export const DEFAULT_SYSTEM_TEMPLATE = ` // You are ChatGPT, a large language model trained by {{ServiceProvider}}. @@ -364,6 +374,8 @@ const iflytekModels = [ "4.0Ultra", ]; +const xAIModes = ["grok-beta"]; + let seq = 1000; // 内置的模型序号生成器从1000开始 export const DEFAULT_MODELS = [ ...openaiModels.map((name) => ({ @@ -476,6 +488,17 @@ export const DEFAULT_MODELS = [ sorted: 10, }, })), + ...xAIModes.map((name) => ({ + name, + available: true, + sorted: seq++, + provider: { + id: "xai", + providerName: "XAI", + providerType: "xai", + sorted: 11, + }, + })), ] as const; export const CHAT_PAGE_SIZE = 15; diff --git a/app/locales/cn.ts b/app/locales/cn.ts index e514eb4fe65..006fc81620d 100644 --- a/app/locales/cn.ts +++ b/app/locales/cn.ts @@ -462,6 +462,17 @@ const cn = { SubTitle: "样例:", }, }, + XAI: { + ApiKey: { + Title: "接口密钥", + SubTitle: "使用自定义XAI API Key", + Placeholder: "XAI API Key", + }, + Endpoint: { + Title: "接口地址", + SubTitle: "样例:", + }, + }, Stability: { ApiKey: { Title: "接口密钥", diff --git a/app/locales/en.ts b/app/locales/en.ts index c86cc08f039..7204bd94696 100644 --- a/app/locales/en.ts +++ b/app/locales/en.ts @@ -446,6 +446,17 @@ const en: LocaleType = { SubTitle: "Example: ", }, }, + XAI: { + ApiKey: { + Title: "XAI API Key", + SubTitle: "Use a custom XAI API Key", + Placeholder: "XAI API Key", + }, + Endpoint: { + Title: "Endpoint Address", + SubTitle: "Example: ", + }, + }, Stability: { ApiKey: { Title: "Stability API Key", diff --git a/app/store/access.ts b/app/store/access.ts index dec3a725886..1a27deb1c2c 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -13,6 +13,7 @@ import { MOONSHOT_BASE_URL, STABILITY_BASE_URL, IFLYTEK_BASE_URL, + XAI_BASE_URL, } from "../constant"; import { getHeaders } from "../client/api"; import { getClientConfig } from "../config/client"; @@ -44,6 +45,8 @@ const DEFAULT_STABILITY_URL = isApp ? STABILITY_BASE_URL : ApiPath.Stability; const DEFAULT_IFLYTEK_URL = isApp ? IFLYTEK_BASE_URL : ApiPath.Iflytek; +const DEFAULT_XAI_URL = isApp ? XAI_BASE_URL : ApiPath.XAI; + const DEFAULT_ACCESS_STATE = { accessCode: "", useCustomConfig: false, @@ -101,6 +104,10 @@ const DEFAULT_ACCESS_STATE = { iflytekApiKey: "", iflytekApiSecret: "", + // moonshot + xaiUrl: DEFAULT_XAI_URL, + xaiApiKey: "", + // server config needCode: true, hideUserApiKey: false, @@ -169,6 +176,10 @@ export const useAccessStore = createPersistStore( return ensure(get(), ["iflytekApiKey"]); }, + isValidXAI() { + return ensure(get(), ["xaiApiKey"]); + }, + isAuthorized() { this.fetch(); @@ -184,6 +195,7 @@ export const useAccessStore = createPersistStore( this.isValidTencent() || this.isValidMoonshot() || this.isValidIflytek() || + this.isValidXAI() || !this.enabledAccessControl() || (this.enabledAccessControl() && ensure(get(), ["accessCode"])) ); From e791cd441d544a18126ddb825651d0e6274020e9 Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 23 Oct 2024 11:55:25 +0800 Subject: [PATCH 64/65] add xai --- app/api/auth.ts | 2 +- app/client/platforms/xai.ts | 4 +--- app/store/access.ts | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/api/auth.ts b/app/api/auth.ts index fb147cf51f5..d4ac66a113b 100644 --- a/app/api/auth.ts +++ b/app/api/auth.ts @@ -105,7 +105,7 @@ export function auth(req: NextRequest, modelProvider: ModelProvider) { } if (systemApiKey) { - console.log("[Auth] use system api key", systemApiKey); + console.log("[Auth] use system api key"); req.headers.set("Authorization", `Bearer ${systemApiKey}`); } else { console.log("[Auth] admin did not provide an api key"); diff --git a/app/client/platforms/xai.ts b/app/client/platforms/xai.ts index 69f80e9fc26..deb74e66c03 100644 --- a/app/client/platforms/xai.ts +++ b/app/client/platforms/xai.ts @@ -83,11 +83,9 @@ export class XAIApi implements LLMApi { presence_penalty: modelConfig.presence_penalty, frequency_penalty: modelConfig.frequency_penalty, top_p: modelConfig.top_p, - // max_tokens: Math.max(modelConfig.max_tokens, 1024), - // Please do not ask me why not send max_tokens, no reason, this param is just shit, I dont want to explain anymore. }; - console.log("[Request] openai payload: ", requestPayload); + console.log("[Request] xai payload: ", requestPayload); const shouldStream = !!options.config.stream; const controller = new AbortController(); diff --git a/app/store/access.ts b/app/store/access.ts index 1a27deb1c2c..b3d412a2daf 100644 --- a/app/store/access.ts +++ b/app/store/access.ts @@ -104,7 +104,7 @@ const DEFAULT_ACCESS_STATE = { iflytekApiKey: "", iflytekApiSecret: "", - // moonshot + // xai xaiUrl: DEFAULT_XAI_URL, xaiApiKey: "", From 65bb962fc0b6eaa0cb1e15451d954df216b1956f Mon Sep 17 00:00:00 2001 From: lloydzhou Date: Wed, 23 Oct 2024 12:00:59 +0800 Subject: [PATCH 65/65] hotfix --- app/components/settings.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/settings.tsx b/app/components/settings.tsx index 6ce71b5ef34..666caece838 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -1206,11 +1206,11 @@ export function Settings() { accessStore.update( - (access) => (access.moonshotUrl = e.currentTarget.value), + (access) => (access.xaiUrl = e.currentTarget.value), ) } > @@ -1221,12 +1221,12 @@ export function Settings() { > { accessStore.update( - (access) => (access.moonshotApiKey = e.currentTarget.value), + (access) => (access.xaiApiKey = e.currentTarget.value), ); }} />