mirror of
https://github.com/Chanzhaoyu/chatgpt-web.git
synced 2025-07-29 09:53:44 +00:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
797cc7461b | ||
![]() |
58547d1b58 | ||
![]() |
c933a851f4 | ||
![]() |
86fcbbff0b | ||
![]() |
5d1f8519c2 | ||
![]() |
3c21068150 | ||
![]() |
cd03a71ef1 | ||
![]() |
1d74717beb | ||
![]() |
e35abb1c98 | ||
![]() |
b4b0f65158 | ||
![]() |
910c19b02e | ||
![]() |
32049fbf18 | ||
![]() |
817a4842ac | ||
![]() |
0cd120ec5b | ||
![]() |
007763f7d7 | ||
![]() |
3debaec4b2 | ||
![]() |
35f353c1f7 | ||
![]() |
3ac6746930 | ||
![]() |
9b556e4833 | ||
![]() |
071283c007 | ||
![]() |
854261ef86 | ||
![]() |
633e9ad8e2 | ||
![]() |
47dd6c9801 | ||
![]() |
0eb9df6d31 | ||
![]() |
8bfbe6f7df | ||
![]() |
43e8635e7f | ||
![]() |
b7542c70cb | ||
![]() |
b594ec5de1 | ||
![]() |
9a9b154040 | ||
![]() |
12681b1a05 |
47
.github/workflows/ci.yml
vendored
Normal file
47
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Setup
|
||||
run: npm i -g @antfu/ni
|
||||
|
||||
- name: Install
|
||||
run: nci
|
||||
|
||||
- name: Lint
|
||||
run: nr lint:fix
|
||||
|
||||
typecheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Setup
|
||||
run: npm i -g @antfu/ni
|
||||
|
||||
- name: Install
|
||||
run: nci
|
||||
|
||||
- name: Typecheck
|
||||
run: nr type-check
|
2
.husky/commit-msg
Normal file → Executable file
2
.husky/commit-msg
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
pnpm exec commitlint --config .commitlintrc.json --edit "${1}"
|
||||
npx --no -- commitlint --edit
|
||||
|
2
.husky/pre-commit
Normal file → Executable file
2
.husky/pre-commit
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
pnpm exec lint-staged
|
||||
npx lint-staged
|
||||
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -33,6 +33,8 @@
|
||||
"rushstack",
|
||||
"Sider",
|
||||
"tailwindcss",
|
||||
"tsup",
|
||||
"Typecheck",
|
||||
"unplugin",
|
||||
"VITE",
|
||||
"vueuse"
|
||||
|
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,3 +1,14 @@
|
||||
## v2.1.0
|
||||
|
||||
`2023-02-14`
|
||||
### Enhancement
|
||||
- 更新依赖至最新
|
||||
- 联想功能移动至前端提交,后端只做转发
|
||||
|
||||
### BugFix
|
||||
- 修复部份项目检测有关 `Bug`
|
||||
- 修复清除上下文按钮失效
|
||||
|
||||
## v2.0.0
|
||||
|
||||
`2023-02-13`
|
||||
|
26
CONTRIBUTING.md
Normal file
26
CONTRIBUTING.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# 指南
|
||||
|
||||
## Commit 指南
|
||||
|
||||
Commit messages 请遵循[conventional-changelog 标准](https://www.conventionalcommits.org/en/v1.0.0/):
|
||||
|
||||
```bash
|
||||
<类型>[可选 范围]: <描述>
|
||||
|
||||
[可选 正文]
|
||||
|
||||
[可选 脚注]
|
||||
```
|
||||
|
||||
### Commit 类型
|
||||
|
||||
以下是 commit 类型列表:
|
||||
|
||||
- feat: 新特性或功能
|
||||
- fix: 缺陷修复
|
||||
- docs: 文档更新
|
||||
- style: 代码风格或者组件样式更新
|
||||
- refactor: 代码重构,不引入新功能和缺陷修复
|
||||
- perf: 性能优化
|
||||
- test: 单元测试
|
||||
- chore: 其他不修改 src 或测试文件的提交
|
40
README.md
40
README.md
@@ -1,19 +1,21 @@
|
||||
# ChatGPT Web Bot
|
||||
|
||||
中文 | [English](./README.en.md)
|
||||
# ChatGPT Web
|
||||
|
||||
使用 express 和 vue3 搭建的 ChartGPT 演示网页
|
||||
|
||||

|
||||
|
||||
## Route Map
|
||||
[x] 多会话
|
||||
> 提示:目前 `OpenAI` 开放的模型最高只有 `GPT-3`,和现在网页所使用的 `GPT-3.5` 或 `GPT-4` 有很大差距,需要等官方开放最新的模型接口。
|
||||
|
||||
[x] 多语言
|
||||
## 待实现路线
|
||||
[x] 多会话储存和上下文逻辑
|
||||
|
||||
[x] 主题
|
||||
[x] 对代码等消息类型的格式化美化处理
|
||||
|
||||
[x] 用户模块
|
||||
[x] 用户模块(注册、登录、个人中心)
|
||||
|
||||
[x] 界面多语言
|
||||
|
||||
[x] 界面主题
|
||||
|
||||
[x] More...
|
||||
|
||||
@@ -33,7 +35,7 @@ node -v
|
||||
npm install pnpm -g
|
||||
```
|
||||
|
||||
### OpenAI API KEy
|
||||
### OpenAI API Key
|
||||
获取 [OpenAI API key](https://platform.openai.com/overview) 并填写到本地环境变量
|
||||
```
|
||||
# service/.env 文件
|
||||
@@ -76,12 +78,24 @@ pnpm dev
|
||||
```
|
||||
|
||||
## 打包
|
||||
|
||||
### 后端服务
|
||||
> 如果你不需要本项目的 `node` 接口,可以省略如下操作
|
||||
|
||||
复制 `service` 文件夹到你有 `node` 服务环境的服务器上。(搜索关键字:`express部署)`
|
||||
复制 `service` 文件夹到你有 `node` 服务环境的服务器上。(搜索关键字:`express部署`)
|
||||
|
||||
操作上述 `安装` 和 `运行` 服务。
|
||||
```shell
|
||||
# 安装
|
||||
pnpm install
|
||||
|
||||
# 打包
|
||||
pnpm build
|
||||
|
||||
# 运行
|
||||
pnpm prod
|
||||
```
|
||||
|
||||
PS: 不进行打包,直接在服务器上运行 `pnpm start` 也可
|
||||
|
||||
### 网页
|
||||
根目录下运行以下命令,然后将 `dist` 文件夹复制到你的托管服务器上
|
||||
@@ -91,6 +105,10 @@ pnpm build
|
||||
```
|
||||
|
||||
### 常见问题
|
||||
Q: 为什么 `Git` 提交总是报错?
|
||||
|
||||
A: 因为有提交信息验证,请遵循 [Commit 指南](./CONTRIBUTING.md)
|
||||
|
||||
Q: 如果只使用前端页面,在哪里改请求接口?
|
||||
|
||||
A: 根目录下 `.env` 文件中的 `VITE_GLOB_API_URL` 字段。
|
||||
|
17
package.json
17
package.json
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "chatgpt-web",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"private": false,
|
||||
"description": "ChatGPT Web Bot",
|
||||
"author": "ChenZhaoYu <chenzhaoyu1994@gami.com>",
|
||||
"description": "ChatGPT Web",
|
||||
"author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>",
|
||||
"keywords": [
|
||||
"chatgpt-web",
|
||||
"chatgpt",
|
||||
"chatbot",
|
||||
"web",
|
||||
"vue"
|
||||
],
|
||||
"scripts": {
|
||||
@@ -28,8 +28,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^0.35.2",
|
||||
"@commitlint/cli": "^17.4.2",
|
||||
"@commitlint/config-conventional": "^17.4.2",
|
||||
"@commitlint/cli": "^17.4.3",
|
||||
"@commitlint/config-conventional": "^17.4.3",
|
||||
"@iconify/vue": "^4.1.0",
|
||||
"@types/node": "^18.13.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
@@ -47,9 +47,8 @@
|
||||
"vue-tsc": "^1.0.24"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,jsx,tsx,vue}": [
|
||||
"pnpm run lint:fix",
|
||||
"pnpm run type-check"
|
||||
"*.{ts,tsx,vue}": [
|
||||
"pnpm lint:fix"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@@ -2,8 +2,8 @@ lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@antfu/eslint-config': ^0.35.2
|
||||
'@commitlint/cli': ^17.4.2
|
||||
'@commitlint/config-conventional': ^17.4.2
|
||||
'@commitlint/cli': ^17.4.3
|
||||
'@commitlint/config-conventional': ^17.4.3
|
||||
'@iconify/vue': ^4.1.0
|
||||
'@types/node': ^18.13.0
|
||||
'@vitejs/plugin-vue': ^4.0.0
|
||||
@@ -30,8 +30,8 @@ dependencies:
|
||||
|
||||
devDependencies:
|
||||
'@antfu/eslint-config': 0.35.2_7kw3g6rralp5ps6mg3uyzz6azm
|
||||
'@commitlint/cli': 17.4.2
|
||||
'@commitlint/config-conventional': 17.4.2
|
||||
'@commitlint/cli': 17.4.3
|
||||
'@commitlint/config-conventional': 17.4.3
|
||||
'@iconify/vue': 4.1.0_vue@3.2.47
|
||||
'@types/node': 18.13.0
|
||||
'@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.47
|
||||
@@ -185,13 +185,13 @@ packages:
|
||||
'@babel/helper-validator-identifier': 7.19.1
|
||||
to-fast-properties: 2.0.0
|
||||
|
||||
/@commitlint/cli/17.4.2:
|
||||
resolution: {integrity: sha512-0rPGJ2O1owhpxMIXL9YJ2CgPkdrFLKZElIZHXDN8L8+qWK1DGH7Q7IelBT1pchXTYTuDlqkOTdh//aTvT3bSUA==}
|
||||
/@commitlint/cli/17.4.3:
|
||||
resolution: {integrity: sha512-IPTS7AZuBHgD0gl24El8HwuDM9zJN9JLa5KmZUQoFD1BQeGGdzAYJOnAr85CeJWpTDok0BGHDL0+4odnH0iTyA==}
|
||||
engines: {node: '>=v14'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@commitlint/format': 17.4.0
|
||||
'@commitlint/lint': 17.4.2
|
||||
'@commitlint/lint': 17.4.3
|
||||
'@commitlint/load': 17.4.2
|
||||
'@commitlint/read': 17.4.2
|
||||
'@commitlint/types': 17.4.0
|
||||
@@ -205,8 +205,8 @@ packages:
|
||||
- '@swc/wasm'
|
||||
dev: true
|
||||
|
||||
/@commitlint/config-conventional/17.4.2:
|
||||
resolution: {integrity: sha512-JVo1moSj5eDMoql159q8zKCU8lkOhQ+b23Vl3LVVrS6PXDLQIELnJ34ChQmFVbBdSSRNAbbXnRDhosFU+wnuHw==}
|
||||
/@commitlint/config-conventional/17.4.3:
|
||||
resolution: {integrity: sha512-8EsY2iDw74hCk3hIQSg7/E0R8/KtPjnFPZVwmmHxcjhZjkSykmxysefICPDnbI3xgxfov0zwL1WKDHM8zglJdw==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
conventional-changelog-conventionalcommits: 5.0.0
|
||||
@@ -253,13 +253,13 @@ packages:
|
||||
semver: 7.3.8
|
||||
dev: true
|
||||
|
||||
/@commitlint/lint/17.4.2:
|
||||
resolution: {integrity: sha512-HcymabrdBhsDMNzIv146+ZPNBPBK5gMNsVH+el2lCagnYgCi/4ixrHooeVyS64Fgce2K26+MC7OQ4vVH8wQWVw==}
|
||||
/@commitlint/lint/17.4.3:
|
||||
resolution: {integrity: sha512-GnPsqEYmXIB/MaBhRMzkiDJWyjuLrKad4xoxKO4N6Kc19iqjR4DPc/bl2dxeW9kUmtrAtefOzIEzJAevpA5y2w==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/is-ignored': 17.4.2
|
||||
'@commitlint/parse': 17.4.2
|
||||
'@commitlint/rules': 17.4.2
|
||||
'@commitlint/rules': 17.4.3
|
||||
'@commitlint/types': 17.4.0
|
||||
dev: true
|
||||
|
||||
@@ -323,8 +323,8 @@ packages:
|
||||
resolve-global: 1.0.0
|
||||
dev: true
|
||||
|
||||
/@commitlint/rules/17.4.2:
|
||||
resolution: {integrity: sha512-OGrPsMb9Fx3/bZ64/EzJehY9YDSGWzp81Pj+zJiY+r/NSgJI3nUYdlS37jykNIugzazdEXfMtQ10kmA+Kx2pZQ==}
|
||||
/@commitlint/rules/17.4.3:
|
||||
resolution: {integrity: sha512-xHReDfE3Z+O9p1sXeEhPRSk4FifBsC4EbXzvQ4aa0ykQe+n/iZDd4CrFC/Oiv2K9BU4ZnFHak30IbMLa4ks1Rw==}
|
||||
engines: {node: '>=v14'}
|
||||
dependencies:
|
||||
'@commitlint/ensure': 17.4.0
|
||||
|
@@ -1,2 +1,3 @@
|
||||
# OpenAI API Key
|
||||
OPENAI_API_KEY=
|
||||
# OpenAI API Key - https://platform.openai.com/overview
|
||||
# e.g: This key is invalid
|
||||
OPENAI_API_KEY='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'
|
||||
|
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": ["build"],
|
||||
"extends": ["@antfu"]
|
||||
}
|
||||
|
2
service/.gitignore
vendored
2
service/.gitignore
vendored
@@ -27,3 +27,5 @@ coverage
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
build
|
||||
|
1
service/.npmrc
Normal file
1
service/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
enable-pre-post-scripts=true
|
@@ -2,23 +2,27 @@
|
||||
"name": "chatgpt-web-service",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"description": "ChatGPT Web Bot node service",
|
||||
"description": "ChatGPT Web Service",
|
||||
"author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>",
|
||||
"keywords": [
|
||||
"chatgpt-web",
|
||||
"chatgpt",
|
||||
"chatbot",
|
||||
"web",
|
||||
"vue"
|
||||
"express"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "esno ./src/index.ts",
|
||||
"prod": "esno ./build/index.js",
|
||||
"build": "pnpm clean && tsup",
|
||||
"clean": "rimraf build",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"chatgpt": "^4.2.0",
|
||||
"chatgpt": "^4.3.2",
|
||||
"express": "^4.18.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -28,6 +32,8 @@
|
||||
"dotenv": "^16.0.3",
|
||||
"eslint": "^8.34.0",
|
||||
"esno": "^0.16.3",
|
||||
"rimraf": "^4.1.2",
|
||||
"tsup": "^6.6.2",
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
|
329
service/pnpm-lock.yaml
generated
329
service/pnpm-lock.yaml
generated
@@ -4,15 +4,17 @@ specifiers:
|
||||
'@antfu/eslint-config': ^0.35.2
|
||||
'@types/express': ^4.17.17
|
||||
'@types/node': ^18.13.0
|
||||
chatgpt: ^4.2.0
|
||||
chatgpt: ^4.3.2
|
||||
dotenv: ^16.0.3
|
||||
eslint: ^8.34.0
|
||||
esno: ^0.16.3
|
||||
express: ^4.18.2
|
||||
rimraf: ^4.1.2
|
||||
tsup: ^6.6.2
|
||||
typescript: ^4.9.5
|
||||
|
||||
dependencies:
|
||||
chatgpt: 4.2.0
|
||||
chatgpt: 4.3.2
|
||||
express: 4.18.2
|
||||
|
||||
devDependencies:
|
||||
@@ -22,6 +24,8 @@ devDependencies:
|
||||
dotenv: 16.0.3
|
||||
eslint: 8.34.0
|
||||
esno: 0.16.3
|
||||
rimraf: 4.1.2
|
||||
tsup: 6.6.2_typescript@4.9.5
|
||||
typescript: 4.9.5
|
||||
|
||||
packages:
|
||||
@@ -689,6 +693,18 @@ packages:
|
||||
color-convert: 2.0.1
|
||||
dev: true
|
||||
|
||||
/any-promise/1.3.0:
|
||||
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
||||
dev: true
|
||||
|
||||
/anymatch/3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/argparse/2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
dev: true
|
||||
@@ -742,6 +758,11 @@ packages:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
||||
/binary-extensions/2.2.0:
|
||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/body-parser/1.20.1:
|
||||
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
|
||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||
@@ -795,11 +816,26 @@ packages:
|
||||
semver: 7.3.8
|
||||
dev: true
|
||||
|
||||
/bundle-require/4.0.1_esbuild@0.17.7:
|
||||
resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
peerDependencies:
|
||||
esbuild: '>=0.17'
|
||||
dependencies:
|
||||
esbuild: 0.17.7
|
||||
load-tsconfig: 0.2.3
|
||||
dev: true
|
||||
|
||||
/bytes/3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dev: false
|
||||
|
||||
/cac/6.7.14:
|
||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/call-bind/1.0.2:
|
||||
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
|
||||
dependencies:
|
||||
@@ -840,8 +876,8 @@ packages:
|
||||
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
|
||||
dev: true
|
||||
|
||||
/chatgpt/4.2.0:
|
||||
resolution: {integrity: sha512-HYQ65GCa8PGtmmUB+XSAa17/IKTy/EEj8QU9HGU8UAsGBtKZushiozC0JpNcTyG+ivpuwzdduXJyL6ELnqkY4A==}
|
||||
/chatgpt/4.3.2:
|
||||
resolution: {integrity: sha512-5+Kh0mdP/pDJTL3kA6C6Dp43EO8T8sILPJbbQwOu3J4dK+n/tYpSXsmG6VZkmitAVOffeTonXTGDJwslc66orw==}
|
||||
engines: {node: '>=18'}
|
||||
dependencies:
|
||||
eventsource-parser: 0.0.5
|
||||
@@ -852,6 +888,21 @@ packages:
|
||||
uuid: 9.0.0
|
||||
dev: false
|
||||
|
||||
/chokidar/3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
dependencies:
|
||||
anymatch: 3.1.3
|
||||
braces: 3.0.2
|
||||
glob-parent: 5.1.2
|
||||
is-binary-path: 2.1.0
|
||||
is-glob: 4.0.3
|
||||
normalize-path: 3.0.0
|
||||
readdirp: 3.6.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/ci-info/3.8.0:
|
||||
resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -885,6 +936,11 @@ packages:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
dev: true
|
||||
|
||||
/commander/4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/concat-map/0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
dev: true
|
||||
@@ -1576,6 +1632,21 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/execa/5.1.1:
|
||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
get-stream: 6.0.1
|
||||
human-signals: 2.1.0
|
||||
is-stream: 2.0.1
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 4.0.1
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
dev: true
|
||||
|
||||
/express/4.18.2:
|
||||
resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
@@ -1753,6 +1824,11 @@ packages:
|
||||
has: 1.0.3
|
||||
has-symbols: 1.0.3
|
||||
|
||||
/get-stream/6.0.1:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/get-symbol-description/1.0.0:
|
||||
resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -1779,6 +1855,17 @@ packages:
|
||||
is-glob: 4.0.3
|
||||
dev: true
|
||||
|
||||
/glob/7.1.6:
|
||||
resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==}
|
||||
dependencies:
|
||||
fs.realpath: 1.0.0
|
||||
inflight: 1.0.6
|
||||
inherits: 2.0.4
|
||||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: true
|
||||
|
||||
/glob/7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
dependencies:
|
||||
@@ -1896,6 +1983,11 @@ packages:
|
||||
toidentifier: 1.0.1
|
||||
dev: false
|
||||
|
||||
/human-signals/2.1.0:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
dev: true
|
||||
|
||||
/iconv-lite/0.4.24:
|
||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1979,6 +2071,13 @@ packages:
|
||||
has-bigints: 1.0.2
|
||||
dev: true
|
||||
|
||||
/is-binary-path/2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
binary-extensions: 2.2.0
|
||||
dev: true
|
||||
|
||||
/is-boolean-object/1.1.2:
|
||||
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2068,6 +2167,11 @@ packages:
|
||||
call-bind: 1.0.2
|
||||
dev: true
|
||||
|
||||
/is-stream/2.0.1:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-string/1.0.7:
|
||||
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2103,6 +2207,11 @@ packages:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/joycon/3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/js-sdsl/4.3.0:
|
||||
resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==}
|
||||
dev: true
|
||||
@@ -2176,10 +2285,20 @@ packages:
|
||||
type-check: 0.4.0
|
||||
dev: true
|
||||
|
||||
/lilconfig/2.0.6:
|
||||
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/lines-and-columns/1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: true
|
||||
|
||||
/load-tsconfig/0.2.3:
|
||||
resolution: {integrity: sha512-iyT2MXws+dc2Wi6o3grCFtGXpeMvHmJqS27sMPGtV2eUu4PeFnG+33I8BlFK1t1NWMjOpcx9bridn5yxLDX2gQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/local-pkg/0.4.3:
|
||||
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
||||
engines: {node: '>=14'}
|
||||
@@ -2203,6 +2322,10 @@ packages:
|
||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||
dev: true
|
||||
|
||||
/lodash.sortby/4.7.0:
|
||||
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
|
||||
dev: true
|
||||
|
||||
/lodash/4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
dev: true
|
||||
@@ -2239,6 +2362,10 @@ packages:
|
||||
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
|
||||
dev: false
|
||||
|
||||
/merge-stream/2.0.0:
|
||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||
dev: true
|
||||
|
||||
/merge2/1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -2284,6 +2411,11 @@ packages:
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/mimic-fn/2.1.0:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/min-indent/1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -2310,6 +2442,14 @@ packages:
|
||||
/ms/2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
/mz/2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
object-assign: 4.1.1
|
||||
thenify-all: 1.6.0
|
||||
dev: true
|
||||
|
||||
/natural-compare-lite/1.4.0:
|
||||
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
||||
dev: true
|
||||
@@ -2332,12 +2472,29 @@ packages:
|
||||
validate-npm-package-license: 3.0.4
|
||||
dev: true
|
||||
|
||||
/normalize-path/3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/npm-run-path/4.0.1:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
dev: true
|
||||
|
||||
/nth-check/2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
dependencies:
|
||||
boolbase: 1.0.0
|
||||
dev: true
|
||||
|
||||
/object-assign/4.1.1:
|
||||
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/object-inspect/1.12.3:
|
||||
resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==}
|
||||
|
||||
@@ -2378,6 +2535,13 @@ packages:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/onetime/5.1.2:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
engines: {node: '>=6'}
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
dev: true
|
||||
|
||||
/optionator/0.9.1:
|
||||
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
@@ -2494,11 +2658,32 @@ packages:
|
||||
engines: {node: '>=8.6'}
|
||||
dev: true
|
||||
|
||||
/pirates/4.0.5:
|
||||
resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/pluralize/8.0.0:
|
||||
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/postcss-load-config/3.1.4:
|
||||
resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==}
|
||||
engines: {node: '>= 10'}
|
||||
peerDependencies:
|
||||
postcss: '>=8.0.9'
|
||||
ts-node: '>=9.0.0'
|
||||
peerDependenciesMeta:
|
||||
postcss:
|
||||
optional: true
|
||||
ts-node:
|
||||
optional: true
|
||||
dependencies:
|
||||
lilconfig: 2.0.6
|
||||
yaml: 1.10.2
|
||||
dev: true
|
||||
|
||||
/postcss-selector-parser/6.0.11:
|
||||
resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -2575,6 +2760,13 @@ packages:
|
||||
type-fest: 0.6.0
|
||||
dev: true
|
||||
|
||||
/readdirp/3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/regexp-tree/0.1.24:
|
||||
resolution: {integrity: sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==}
|
||||
hasBin: true
|
||||
@@ -2606,6 +2798,11 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/resolve-from/5.0.0:
|
||||
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/resolve/1.22.1:
|
||||
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
|
||||
hasBin: true
|
||||
@@ -2627,6 +2824,20 @@ packages:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rimraf/4.1.2:
|
||||
resolution: {integrity: sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/rollup/3.15.0:
|
||||
resolution: {integrity: sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==}
|
||||
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: true
|
||||
|
||||
/run-parallel/1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
dependencies:
|
||||
@@ -2729,6 +2940,10 @@ packages:
|
||||
get-intrinsic: 1.2.0
|
||||
object-inspect: 1.12.3
|
||||
|
||||
/signal-exit/3.0.7:
|
||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||
dev: true
|
||||
|
||||
/slash/3.0.0:
|
||||
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2746,6 +2961,13 @@ packages:
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/source-map/0.8.0-beta.0:
|
||||
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
whatwg-url: 7.1.0
|
||||
dev: true
|
||||
|
||||
/spdx-correct/3.1.1:
|
||||
resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==}
|
||||
dependencies:
|
||||
@@ -2801,6 +3023,11 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/strip-final-newline/2.0.0:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/strip-indent/3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2813,6 +3040,19 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/sucrase/3.29.0:
|
||||
resolution: {integrity: sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==}
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: 4.1.1
|
||||
glob: 7.1.6
|
||||
lines-and-columns: 1.2.4
|
||||
mz: 2.7.0
|
||||
pirates: 4.0.5
|
||||
ts-interface-checker: 0.1.13
|
||||
dev: true
|
||||
|
||||
/supports-color/5.5.0:
|
||||
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
|
||||
engines: {node: '>=4'}
|
||||
@@ -2836,6 +3076,19 @@ packages:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
dev: true
|
||||
|
||||
/thenify-all/1.6.0:
|
||||
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
|
||||
engines: {node: '>=0.8'}
|
||||
dependencies:
|
||||
thenify: 3.3.1
|
||||
dev: true
|
||||
|
||||
/thenify/3.3.1:
|
||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
dev: true
|
||||
|
||||
/to-regex-range/5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
@@ -2848,6 +3101,21 @@ packages:
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/tr46/1.0.1:
|
||||
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
|
||||
dependencies:
|
||||
punycode: 2.3.0
|
||||
dev: true
|
||||
|
||||
/tree-kill/1.2.2:
|
||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/ts-interface-checker/0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
dev: true
|
||||
|
||||
/tsconfig-paths/3.14.1:
|
||||
resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==}
|
||||
dependencies:
|
||||
@@ -2861,6 +3129,42 @@ packages:
|
||||
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
|
||||
dev: true
|
||||
|
||||
/tsup/6.6.2_typescript@4.9.5:
|
||||
resolution: {integrity: sha512-+yQ6SI4rVtp1+YpcYOePumJLEVQ896CDNRt9dJ2L/DeMnLf1+FTOCVw5eioLBH0xLdHgogO9NQ6vPNF5MfkSJw==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@swc/core': ^1
|
||||
postcss: ^8.4.12
|
||||
typescript: ^4.1.0
|
||||
peerDependenciesMeta:
|
||||
'@swc/core':
|
||||
optional: true
|
||||
postcss:
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
dependencies:
|
||||
bundle-require: 4.0.1_esbuild@0.17.7
|
||||
cac: 6.7.14
|
||||
chokidar: 3.5.3
|
||||
debug: 4.3.4
|
||||
esbuild: 0.17.7
|
||||
execa: 5.1.1
|
||||
globby: 11.1.0
|
||||
joycon: 3.1.1
|
||||
postcss-load-config: 3.1.4
|
||||
resolve-from: 5.0.0
|
||||
rollup: 3.15.0
|
||||
source-map: 0.8.0-beta.0
|
||||
sucrase: 3.29.0
|
||||
tree-kill: 1.2.2
|
||||
typescript: 4.9.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: true
|
||||
|
||||
/tsutils/3.21.0_typescript@4.9.5:
|
||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -2996,6 +3300,18 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/webidl-conversions/4.0.2:
|
||||
resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
|
||||
dev: true
|
||||
|
||||
/whatwg-url/7.1.0:
|
||||
resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==}
|
||||
dependencies:
|
||||
lodash.sortby: 4.7.0
|
||||
tr46: 1.0.1
|
||||
webidl-conversions: 4.0.2
|
||||
dev: true
|
||||
|
||||
/which-boxed-primitive/1.0.2:
|
||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||
dependencies:
|
||||
@@ -3053,6 +3369,11 @@ packages:
|
||||
yaml: 2.2.1
|
||||
dev: true
|
||||
|
||||
/yaml/1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yaml/2.2.1:
|
||||
resolution: {integrity: sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==}
|
||||
engines: {node: '>= 14'}
|
||||
|
@@ -15,67 +15,31 @@ const apiKey = process.env.OPENAI_API_KEY
|
||||
if (apiKey === undefined)
|
||||
throw new Error('OPENAI_API_KEY is not defined')
|
||||
|
||||
const chatContext = new Set<ChatContext>()
|
||||
|
||||
/**
|
||||
* More Info: https://github.com/transitive-bullshit/chatgpt-api
|
||||
*/
|
||||
const api = new ChatGPTAPI({ apiKey })
|
||||
const api = new ChatGPTAPI({ apiKey, debug: false })
|
||||
|
||||
async function chatReply(message: string) {
|
||||
async function chatReply(
|
||||
message: string,
|
||||
lastContext?: { conversationId?: string; parentMessageId?: string },
|
||||
) {
|
||||
if (!message)
|
||||
return sendResponse({ type: 'Fail', message: 'Message is empty' })
|
||||
|
||||
try {
|
||||
// Get the last context from the chat context
|
||||
let options: SendMessageOptions = {}
|
||||
|
||||
const lastContext = Array.from(chatContext).pop()
|
||||
|
||||
if (lastContext)
|
||||
options = { ...lastContext }
|
||||
|
||||
const response = await api.sendMessage(message, { ...options })
|
||||
|
||||
const { conversationId, id } = response
|
||||
|
||||
// Add the new context to the chat context
|
||||
if (conversationId && id)
|
||||
chatContext.add({ conversationId, parentMessageId: id })
|
||||
|
||||
return sendResponse({ type: 'Success', data: response })
|
||||
}
|
||||
catch (error: any) {
|
||||
global.console.log(error)
|
||||
return sendResponse({ type: 'Fail', message: error.message })
|
||||
}
|
||||
}
|
||||
|
||||
async function chatReplayOne(message: string, options?: ChatContext) {
|
||||
if (!message)
|
||||
return sendResponse({ type: 'Fail', message: 'Message is empty' })
|
||||
|
||||
try {
|
||||
let messageOptions: SendMessageOptions = {}
|
||||
|
||||
if (options) {
|
||||
const { conversationId, parentMessageId } = options
|
||||
messageOptions = { conversationId, parentMessageId }
|
||||
|
||||
const response = await api.sendMessage(message, { ...messageOptions })
|
||||
|
||||
return sendResponse({ type: 'Success', data: response })
|
||||
}
|
||||
}
|
||||
catch (error: any) {
|
||||
return sendResponse({ type: 'Fail', message: error.message })
|
||||
}
|
||||
}
|
||||
|
||||
async function clearChatContext() {
|
||||
// Clear the chat context
|
||||
chatContext.clear()
|
||||
return sendResponse({ type: 'Success', message: 'Chat context cleared' })
|
||||
}
|
||||
|
||||
export { chatReply, chatReplayOne, clearChatContext }
|
||||
export { chatReply }
|
||||
|
@@ -1,35 +1,22 @@
|
||||
import express from 'express'
|
||||
import type { ChatContext } from './chatgpt'
|
||||
import { chatReplayOne, chatReply, clearChatContext } from './chatgpt'
|
||||
import { chatReply } from './chatgpt'
|
||||
|
||||
const app = express()
|
||||
|
||||
app.use(express.json())
|
||||
|
||||
app.all('*', (req, res, next) => {
|
||||
app.all('*', (_, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', '*')
|
||||
res.header('Access-Control-Allow-Headers', 'Content-Type')
|
||||
res.header('Access-Control-Allow-Methods', '*')
|
||||
next()
|
||||
})
|
||||
|
||||
app.listen(3002, () => globalThis.console.log('Server is running on port 3002'))
|
||||
|
||||
app.post('/chat', async (req, res) => {
|
||||
try {
|
||||
const { prompt } = req.body as { prompt: string }
|
||||
const response = await chatReply(prompt)
|
||||
res.send(response)
|
||||
}
|
||||
catch (error) {
|
||||
res.send(error)
|
||||
}
|
||||
})
|
||||
|
||||
app.post('./chatOne', async (req, res) => {
|
||||
try {
|
||||
const { prompt, options = {} } = req.body as { prompt: string; options?: ChatContext }
|
||||
const response = await chatReplayOne(prompt, options)
|
||||
const response = await chatReply(prompt, options)
|
||||
res.send(response)
|
||||
}
|
||||
catch (error) {
|
||||
@@ -37,7 +24,4 @@ app.post('./chatOne', async (req, res) => {
|
||||
}
|
||||
})
|
||||
|
||||
app.post('/clear', async (req, res) => {
|
||||
const response = await clearChatContext()
|
||||
res.send(response)
|
||||
})
|
||||
app.listen(3002, () => globalThis.console.log('Server is running on port 3002'))
|
||||
|
27
service/tsconfig.json
Normal file
27
service/tsconfig.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"baseUrl": ".",
|
||||
"outDir": "build",
|
||||
"noEmit": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build"
|
||||
],
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
13
service/tsup.config.ts
Normal file
13
service/tsup.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from 'tsup'
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
outDir: 'build',
|
||||
target: 'es2020',
|
||||
format: ['cjs'],
|
||||
splitting: false,
|
||||
sourcemap: true,
|
||||
minify: false,
|
||||
shims: true,
|
||||
dts: false,
|
||||
})
|
@@ -1,9 +1,12 @@
|
||||
import { post } from '@/utils/request'
|
||||
|
||||
export function fetchChatAPI<T = any>(prompt: string) {
|
||||
export function fetchChatAPI<T = any>(
|
||||
prompt: string,
|
||||
options?: { conversationId?: string; parentMessageId?: string },
|
||||
) {
|
||||
return post<T>({
|
||||
url: '/chat',
|
||||
data: { prompt },
|
||||
data: { prompt, options },
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -1,52 +0,0 @@
|
||||
<script setup lang='ts'>
|
||||
import { SvgIcon } from '@/components/common'
|
||||
|
||||
interface Props {
|
||||
text: string
|
||||
}
|
||||
|
||||
interface Emit {
|
||||
(e: 'click',): void
|
||||
(e: 'edit',): void
|
||||
(e: 'delete',): void
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<Emit>()
|
||||
|
||||
function handleClick(event: Event) {
|
||||
emit('click')
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
emit('edit')
|
||||
}
|
||||
|
||||
function handleDelete() {
|
||||
emit('delete')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a
|
||||
class="relative flex items-center gap-3 px-3 py-3 break-all rounded-md cursor-pointer bg-neutral-50 pr-14 hover:bg-neutral-100 group"
|
||||
@click="handleClick"
|
||||
>
|
||||
<span>
|
||||
<SvgIcon icon="ri:message-3-line" />
|
||||
</span>
|
||||
<div class="relative flex-1 overflow-hidden break-all text-ellipsis whitespace-nowrap max-h-5">
|
||||
<span>{{ text }}</span>
|
||||
</div>
|
||||
<div class="absolute z-10 flex visible right-1">
|
||||
<button class="p-1" @click="handleEdit">
|
||||
<SvgIcon icon="ri:edit-line" />
|
||||
</button>
|
||||
<button class="p-1" @click="handleDelete">
|
||||
<SvgIcon icon="ri:delete-bin-line" />
|
||||
</button>
|
||||
</div>
|
||||
</a>
|
||||
</template>
|
@@ -9,7 +9,7 @@ defineProps<Props>()
|
||||
|
||||
<template>
|
||||
<div class="p-2 mt-2 rounded-md" :class="[reversal ? 'bg-[#d2f9d1]' : 'bg-[#f4f6f8]']">
|
||||
<span class="leading-relaxed whitespace-pre-wrap" :class="[{ 'text-red-400': error }]">
|
||||
<span class="leading-relaxed whitespace-pre-wrap" :class="[{ 'text-red-500': error }]">
|
||||
<slot />
|
||||
</span>
|
||||
</div>
|
||||
|
@@ -1,4 +1,3 @@
|
||||
import Message from './Message/index.vue'
|
||||
import ListItem from './ListItem/index.vue'
|
||||
|
||||
export { Message, ListItem }
|
||||
export { Message }
|
||||
|
@@ -1,50 +1,27 @@
|
||||
<script setup lang='ts'>
|
||||
import { nextTick, onMounted, ref } from 'vue'
|
||||
import { computed, nextTick, onMounted, ref } from 'vue'
|
||||
import { NButton, NInput, useMessage } from 'naive-ui'
|
||||
import type { ChatOptions, ChatProps } from './types'
|
||||
import { Message } from './components'
|
||||
import { Layout } from './layout'
|
||||
import { clearConversations, fetchChatAPI } from '@/api'
|
||||
import { fetchChatAPI } from '@/api'
|
||||
import { HoverButton, SvgIcon } from '@/components/common'
|
||||
|
||||
interface ListProps {
|
||||
dateTime: string
|
||||
message: string
|
||||
reversal?: boolean
|
||||
error?: boolean
|
||||
}
|
||||
|
||||
const scrollRef = ref<HTMLDivElement>()
|
||||
|
||||
const ms = useMessage()
|
||||
|
||||
const prompt = ref('')
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const list = ref<ListProps[]>([])
|
||||
|
||||
onMounted(initChat)
|
||||
const list = ref<ChatProps[]>([])
|
||||
const chatList = computed(() => list.value.filter(item => (!item.reversal && !item.error)))
|
||||
|
||||
function initChat() {
|
||||
addMessage('Hi, I am ChatGPT, a chatbot based on GPT-3.', false)
|
||||
addMessage('Hi, I am ChatGPT, a chatbot based on GPT-3.')
|
||||
}
|
||||
|
||||
async function handleClear() {
|
||||
try {
|
||||
const { message } = await clearConversations()
|
||||
ms.success(message ?? 'Success')
|
||||
}
|
||||
catch (error) {
|
||||
ms.error('Clear failed, please try again later.')
|
||||
list.value = []
|
||||
setTimeout(initChat, 100)
|
||||
}
|
||||
}
|
||||
|
||||
function handleEnter(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter')
|
||||
handleSubmit()
|
||||
}
|
||||
onMounted(initChat)
|
||||
|
||||
async function handleSubmit() {
|
||||
if (loading.value)
|
||||
@@ -57,26 +34,51 @@ async function handleSubmit() {
|
||||
return
|
||||
}
|
||||
|
||||
addMessage(message, true)
|
||||
addMessage(message, { reversal: true })
|
||||
prompt.value = ''
|
||||
|
||||
let options: ChatOptions = {}
|
||||
const lastContext = chatList.value[chatList.value.length - 1]?.options
|
||||
|
||||
if (lastContext)
|
||||
options = { ...lastContext }
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const { data } = await fetchChatAPI(message)
|
||||
addMessage(data?.text ?? '', false)
|
||||
const { data } = await fetchChatAPI(message, options)
|
||||
addMessage(data?.text ?? '', { options: { conversationId: data.conversationId, parentMessageId: data.id } })
|
||||
}
|
||||
catch (error: any) {
|
||||
addMessage(`Error: ${error.message ?? 'Request failed, please try again later.'}`, false, true)
|
||||
addMessage(`Error: ${error.message ?? 'Request failed, please try again later.'}`, { error: true })
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function addMessage(message: string, reversal = false, error = false) {
|
||||
list.value.push({ dateTime: new Date().toLocaleString(), message, reversal, error })
|
||||
function handleEnter(event: KeyboardEvent) {
|
||||
if (event.key === 'Enter')
|
||||
handleSubmit()
|
||||
}
|
||||
|
||||
function addMessage(
|
||||
message: string,
|
||||
args?: { reversal?: boolean; error?: boolean; options?: ChatOptions },
|
||||
) {
|
||||
list.value.push({
|
||||
dateTime: new Date().toLocaleString(),
|
||||
message,
|
||||
reversal: args?.reversal ?? false,
|
||||
error: args?.error ?? false,
|
||||
options: args?.options ?? undefined,
|
||||
})
|
||||
nextTick(() => scrollRef.value && (scrollRef.value.scrollTop = scrollRef.value.scrollHeight))
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
list.value = []
|
||||
setTimeout(initChat, 100)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -86,12 +88,8 @@ function addMessage(message: string, reversal = false, error = false) {
|
||||
<div ref="scrollRef" class="h-full p-4 overflow-hidden overflow-y-auto">
|
||||
<div>
|
||||
<Message
|
||||
v-for="(item, index) of list"
|
||||
:key="index"
|
||||
:date-time="item.dateTime"
|
||||
:message="item.message"
|
||||
:reversal="item.reversal"
|
||||
:error="item.error"
|
||||
v-for="(item, index) of list" :key="index" :date-time="item.dateTime" :message="item.message"
|
||||
:reversal="item.reversal" :error="item.error"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
12
src/components/business/Chat/types.ts
Normal file
12
src/components/business/Chat/types.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface ChatOptions {
|
||||
conversationId?: string
|
||||
parentMessageId?: string
|
||||
}
|
||||
|
||||
export interface ChatProps {
|
||||
dateTime: string
|
||||
message: string
|
||||
reversal?: boolean
|
||||
error?: boolean
|
||||
options?: ChatOptions
|
||||
}
|
@@ -18,5 +18,5 @@
|
||||
},
|
||||
"types": ["vite/client", "node", "naive-ui/volar"]
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
"exclude": ["node_modules", "dist", "service"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user