diff --git a/.eslintignore b/.eslintignore index 22b38d8..53c37a1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,6 +1 @@ -node_modules -packages/cli/node_modules -root -docs -*.md -packages/cli/lib/**/* \ No newline at end of file +dist \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 45a2969..0c5a0bb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,28 +1,17 @@ /** @type {import('eslint').Linter.BaseConfig} */ -const config = { +module.exports = { env: { node: true, - commonjs: true + es6: true }, - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'prettier'], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - 'prettier' - ], parserOptions: { ecmaVersion: 'latest', - sourceType: 'script' // 对于 CommonJS + sourceType: 'module' }, + parser: '@typescript-eslint/parser', + plugins: ['prettier'], + extends: ['prettier', 'plugin:oxlint/recommended'], rules: { - 'prettier/prettier': 'error' /** check prettier lint */, - '@typescript-eslint/no-var-requires': 'off' /** only run with commonjs */, - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/ban-ts-comment': - 'off' /** quickly ban all error unnecessary */ + 'prettier/prettier': 'error' /** check prettier lint */ } } - -module.exports = config diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh deleted file mode 100644 index cec959a..0000000 --- a/.husky/_/husky.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env sh -if [ -z "$husky_skip_init" ]; then - debug () { - if [ "$HUSKY_DEBUG" = "1" ]; then - echo "husky (debug) - $1" - fi - } - - readonly hook_name="$(basename -- "$0")" - debug "starting $hook_name..." - - if [ "$HUSKY" = "0" ]; then - debug "HUSKY env variable is set to 0, skipping hook" - exit 0 - fi - - if [ -f ~/.huskyrc ]; then - debug "sourcing ~/.huskyrc" - . ~/.huskyrc - fi - - readonly husky_skip_init=1 - export husky_skip_init - sh -e "$0" "$@" - exitCode="$?" - - if [ $exitCode != 0 ]; then - echo "husky - $hook_name hook exited with code $exitCode (error)" - fi - - if [ $exitCode = 127 ]; then - echo "husky - command not found in PATH=$PATH" - fi - - exit $exitCode -fi diff --git a/.husky/commit-msg b/.husky/commit-msg index b5a5eb0..406ef5f 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,4 +1,2 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" npx commitlint --edit "$1" diff --git a/.husky/pre-commit b/.husky/pre-commit index d24fdfc..a4198c3 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,3 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" -npx lint-staged +# npx lint-staged +# npx tsc --noEmit \ No newline at end of file diff --git a/.swcrc b/.swcrc new file mode 100644 index 0000000..608c4f8 --- /dev/null +++ b/.swcrc @@ -0,0 +1,16 @@ +{ + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": false, + "dynamicImport": false + }, + "target": "esnext", + "loose": false, + "externalHelpers": false, + "keepClassNames": true + }, + "module": { + "type": "es6" + } +} diff --git a/README.md b/README.md index a013187..339bfdb 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,9 @@ | Docker Tag | latest | windows | | **<发送消息>** | ✅ 单条 / 多条 / 群发 | ✅ 单条 / 多条 / 群发 | | 发文字 | ✅ | ✅ | -| 发图片 | ✅ 本地图片 / url图片解析 | ✅ 本地图片 / url图片解析 | -| 发视频(mp4) | ✅ 本地视频 / url视频解析 | | -| 发文件 | ✅ 本地文件 / url文件解析 | ✅ 本地文件 / url文件解析 | +| 发图片 | ✅ 本地图片 / url图片解析 / base64 | ✅ 本地图片 / url图片解析 / base64 | +| 发视频(mp4) | ✅ 本地视频 / url视频解析 / base64 | | +| 发文件 | ✅ 本地文件 / url文件解析 / base64 | ✅ 本地文件 / url文件解析 / base64 | | **<接收消息>** | | | | 接收文字 | ✅ | ✅ | | 接收语音 | ✅ | | @@ -84,401 +84,15 @@ curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN --data '{ "to": "测试昵称", data: { "content": "Hello World!" }}' ``` -## 🔧 开发 +## 🔧 开发 or 调试 > [!IMPORTANT] > 包管理器迁移已至 pnpm,安装依赖请使用它,以支持一些不定时的临时包修补(patches)和加速依赖安装 -## ⛰️ 部署 Deploy(推荐) +# 📖 部署 / API +[wechatbot‐webhook API 文档](https://github.com/danni-cool/wechatbot-webhook/wiki/wechatbot%E2%80%90webhook-%E6%96%87%E6%A1%A3) -#### 1.使用 docker 部署 - -##### 拉取最新镜像 - -``` -docker pull dannicool/docker-wechatbot-webhook -``` - -##### docker 部署 - -```bash -# 启动容器并映射日志目录,日志按天维度生成,e.g: app.2024-01-01.log -docker run -d --name wxBotWebhook -p 3001:3001 \ --v ~/wxBot_logs:/app/log \ -dannicool/docker-wechatbot-webhook -``` - -##### 使用 compose 部署 (可选) - -```bash -wget -O docker-compose.yml https://cdn.jsdelivr.net/gh/danni-cool/wechatbot-webhook@main/docker-compose.yml && docker-compose down && docker-compose -p wx_bot_webhook up -``` - -#### 2.登录 - -```bash -docker logs -f wxBotWebhook -``` - -找到二维码登录地址,图下 url 部分,浏览器访问,扫码登录wx - - - -#### 可选 env 参数 - -> Tips:需要增加参数使用 -e,多行用 \ 隔开,例如 -e RECVD_MSG_API="" \ - -| 功能 | 变量 | 备注 | -|--|--|--| -| 日志级别 | LOG_LEVEL=info | 日志级别,默认 info,只影响当前日志输出,详细输出考虑使用 debug。无论该值如何变化,日志文件总是记录debug级别的日志 | -| 收消息 API | RECVD_MSG_API= | 如果想自己处理收到消息的逻辑,比如根据消息联动,填上你的处理逻辑 url | -| 收消息 API 接受自己发的消息 | ACCEPT_RECVD_MSG_MYSELF=false | RECVD_MSG_API 是否接收来自自己发的消息(设置为true,即接收, 默认false) | -| 自定义登录 API token | LOGIN_API_TOKEN=abcdefg123 | 你也可以自定义一个自己的登录令牌,不配置的话,默认会生成一个 | -| 禁用自动登录 | DISABLE_AUTO_LOGIN=true | **非微信踢下线账号,可以依靠当前登录的session免登**, 如果想每次都扫码登陆,则增加该条配置 | - -## 🛠️ API - -### 1. 推消息 API - -> v2版本接口增加了群发功能,v1 版本接口请移步 [legacy-api](./docs/legacy-api.md) - -- Url: -- Methods: `POST` -- ContentType: `application/json` -- Body: 格式见下面表格 - -#### `payload` 结构 - -> 发文字或文件外链, 外链会解析成图片或者文件 - -| 参数 | 说明 | 数据类型 | 默认值 | 可否为空 | 可选参数 | -| -- | -- | -- | -- | -- | -- | -| to | **消息接收方**,传入`String` 默认是发给昵称(群名同理), 传入`Object` 结构支持发给备注过的人,比如:`{alias: '备注名'}`,群名不支持备注名 | `String` `Object` | - | N | - | -| isRoom | **是否发给群消息**,这个参数决定了找人的时候找的是群还是人,因为昵称其实和群名相同在技术处理上 | `Boolean` | `false` | Y | `true` `false` | -| data | 消息体结构,见下方 `payload.data` | `Object` `Array` | `false` | N | `true` `false` | - -#### `payload.data` 结构 - -| 参数 | 说明 | 数据类型 | 默认值 | 可否为空 | 可选参数 | -| -- | -- | -- | -- | -- | -- | -| type | **消息类型**, 字段留空解析为纯文本 | `String` `text` | - | Y | `text` `fileUrl` | 支持 **文字** 和 **文件**, | -| content | **消息内容**,如果希望发多个Url并解析,type 指定为 fileUrl 同时,content 里填 url 以英文逗号分隔 | `String` | - | N | - | - -#### Example(curl) - -##### 发单条消息 - -```bash -curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]' \ ---header 'Content-Type: application/json' \ ---data '{ - "to": "testUser", - "data": { "content": "你好👋" } -}' -``` - -##### 发文件 url 同时支持修改成目标文件名 - -> 有些情况下,直接发送 url 文件名可能不是我们想要的,给 url 拼接 query 参数 `$alias` 可用于指定发送给目标的文件名(注意:别名不做文件转换) - -```bash -curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]' \ ---header 'Content-Type: application/json' \ ---data '{ - "to": "testUser", - "data": { - "type": "fileUrl" , - "content": "https://download.samplelib.com/jpeg/sample-clouds-400x300.jpg?$alias=cloud.jpg" - } -}' -``` - -##### 发给群消息 - -```bash -curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]' \ ---header 'Content-Type: application/json' \ ---data '{ - "to": "testGroup", - "isRoom": true, - "data": { "type": "fileUrl" , "content": "https://download.samplelib.com/jpeg/sample-clouds-400x300.jpg" }, -}' -``` - -##### 同一对象多条消息(群消息同理) - -```bash -curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]' \ ---header 'Content-Type: application/json' \ ---data '{ - "to": "testUser", - "data": [ - { - "type": "text", - "content": "你好👋" - }, - { - "type": "fileUrl", - "content": "https://samplelib.com/lib/preview/mp3/sample-3s.mp3" - } - ] -}' -``` - -##### 群发消息 - -``` bash -curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN]' \ ---header 'Content-Type: application/json' \ ---data '[ - { - "to": "testUser1", - "data": { - "content": "你好👋" - } - }, - { - "to": "testUser2", - "data": [ - { - "content": "你好👋" - }, - { - "content": "近况如何?" - } - ] - } -]' -``` - -#### 返回值 `response` 结构 - -- **`success`**: 消息发送成功与否,群发消息即使部份发送成功也会返回 `true` -- **`message`**: 出错时提示的消息 - - 消息发送成功: Message sent successfully - - 参数校验不通过: Some params is not valid, sending task is suspend... - - 消息都发送失败: All Messages [number] sent failed... - - 部份发送成功: Part of the message sent successfully... -- **`task`**: 发送任务详细信息 - - `task.successCount`: 发送成功条数 - - `task.totalCount`: 总消息条数 - - `task.failedCount`: 发送失败条数 - - `task.reject`: 因为参数校验不通过的参数和 error 提示 - - `task.sentFailed`: 因为发送失败和 error 提示 - - `task.notFound`: 因为未找到用户或者群和 error 提示 - -> 确保消息单次发送一致性,某一条参数校验失败会终止所有消息发送任务 - -```json -{ - "success": true, - "message": "", - "task": { - "successCount": 0, - "totalCount": 0, - "failedCount": 0, - "reject": [], - "sentFailed": [], - "notFound": [] - } -} -``` - -#### 读文件发送 - -> 读文件暂时只支持单条发送 - -- Url: -- Methods: `POST` -- ContentType: `multipart/form-data` -- FormData: 格式见下面表格 - -##### `payload` 结构 - -| 参数 | 说明 | 数据类型 | 默认值 | 可否为空 | 可选值 | -| ------- | -------------------------------------------------------------------------------- | -------- | ------ | -------- | ------- | -| to | 消息接收方,传入`String` 默认是发给昵称(群名同理), 传入 Json String 结构支持发给备注过的人,比如:--form 'to="{alias: \"小号\"}"',群名不支持备注名称 | `String` | - | N | - | -| isRoom | **是否发的群消息**,formData纯文本只能使用 `String` 类型,`1`代表是,`0`代表否, | `String` | `0` | Y | `1` `0` | -| content | **文件**,本地文件一次只能发一个,多个文件手动调用多次 | `Binary` | - | N | - | - -##### Curl - -```bash -curl --location --request POST 'http://localhost:3001/webhook/msg?token=[YOUR_PERSONAL_TOKEN]' \ ---form 'to=testGroup' \ ---form content=@"$HOME/demo.jpg" \ ---form 'isRoom=1' -``` - -#### 返回值 `response` 结构 - -```json -{ - "success": true, - "message": "Message sent successfully" -} -``` - -### 2. 收消息 API - -#### `payload` 结构 - - Methods: `POST` - - ContentType: `multipart/form-data` - - Form格式如下 - -| formData | 说明 | 数据类型 | 可选值 | 示例 | -| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----------------------- | ------------------------------------------------ | -| type |
功能类型
  • ✅ 文字(text)
  • ✅ 链接卡片(urlLink)
  • ✅ 图片(file)
  • ✅ 视频(file)
  • ✅ 附件(file)
  • ✅ 语音(file)
  • ✅ 添加好友邀请(friendship)
其他类型
  • 未实现的消息类型(unknown)
系统类型
  • ✅ 登录(system_event_login)
  • ✅ 登出(system_event_logout)
  • ✅ 异常报错(system_event_error)
  • ✅ 快捷回复后消息推送状态通知(system_event_push_notify)
| `String` | `text` `file` `urlLink` `friendship` `unknown` `system_event_login` `system_event_logout` `system_event_error` `system_event_push_notify`| - | -| content | 传输的内容, 文本或传输的文件共用这个字段,结构映射请看示例 | `String` `Binary` | | [示例](docs/recvdApi.example.md#formdatacontent) | -| source | 消息的相关发送方数据, JSON String | `String` | | [示例](docs/recvdApi.example.md#formdatasource) | -| isMentioned | 该消息是@我的消息 [#38](https://github.com/danni-cool/wechatbot-webhook/issues/38) | `String` | `1` `0` | - | -| isMsgFromSelf | 是否是来自自己的消息 [#159](https://github.com/danni-cool/wechatbot-webhook/issues/159) | `String` | `1` `0` | - | - -**服务端处理 formData 一般需要对应的处理程序,假设你已经完成这一步,你将得到以下 request** - -```json - { - "type": "text", - "content": "你好", - "source": "{\"room\":\"\",\"to\":{\"_events\":{},\"_eventsCount\":0,\"id\":\"@f387910fa45\",\"payload\":{\"alias\":\"\",\"avatar\":\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1302335654&username=@f38bfd1e0567910fa45&skey=@crypaafc30\",\"friend\":false,\"gender\":1,\"id\":\"@f38bfd1e10fa45\",\"name\":\"ch.\",\"phone\":[],\"star\":false,\"type\":1}},\"from\":{\"_events\":{},\"_eventsCount\":0,\"id\":\"@6b5111dcc269b6901fbb58\",\"payload\":{\"address\":\"\",\"alias\":\"\",\"avatar\":\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=123234564&username=@6b5dbb58&skey=@crypt_ec356afc30\",\"city\":\"Mars\",\"friend\":false,\"gender\":1,\"id\":\"@6b5dbd3facb58\",\"name\":\"Daniel\",\"phone\":[],\"province\":\"Earth\",\"signature\":\"\",\"star\":false,\"weixin\":\"\",\"type\":1}}}", - "isMentioned": "0", - "isMsgFromSelf": "0", - "isSystemEvent": "0" // 考虑废弃,请使用type类型判断系统消息 - } -``` - -**收消息 api curl示例(直接导入postman调试)** - -```curl -curl --location 'https://your.recvdapi.com' \ ---form 'type="file"' \ ---form 'content=@"/Users/Downloads/13482835.jpeg"' \ ---form 'source="{\\\"room\\\":\\\"\\\",\\\"to\\\":{\\\"_events\\\":{},\\\"_eventsCount\\\":0,\\\"id\\\":\\\"@f387910fa45\\\",\\\"payload\\\":{\\\"alias\\\":\\\"\\\",\\\"avatar\\\":\\\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1302335654&username=@f38bfd1e0567910fa45&skey=@crypaafc30\\\",\\\"friend\\\":false,\\\"gender\\\":1,\\\"id\\\":\\\"@f38bfd1e10fa45\\\",\\\"name\\\":\\\"ch.\\\",\\\"phone\\\":[],\\\"star\\\":false,\\\"type\\\":1}},\\\"from\\\":{\\\"_events\\\":{},\\\"_eventsCount\\\":0,\\\"id\\\":\\\"@6b5111dcc269b6901fbb58\\\",\\\"payload\\\":{\\\"address\\\":\\\"\\\",\\\"alias\\\":\\\"\\\",\\\"avatar\\\":\\\"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=123234564&username=@6b5dbb58&skey=@crypt_ec356afc30\\\",\\\"city\\\":\\\"Mars\\\",\\\"friend\\\":false,\\\"gender\\\":1,\\\"id\\\":\\\"@6b5dbd3facb58\\\",\\\"name\\\":\\\"Daniel\\\",\\\"phone\\\":[],\\\"province\\\":\\\"Earth\\\",\\\"signature\\\":\\\"\\\",\\\"star\\\":false,\\\"weixin\\\":\\\"\\\",\\\"type\\\":1}}}"' \ ---form 'isMentioned="0"' -``` - - -#### 返回值 `response` 结构(可选) - -> 如果期望用 `RECVD_MSG_API` 收消息后立即回复(**快捷回复**),请按以下结构返回返回值,无返回值则不会回复消息 - -- ContentType: `json` - -| 参数 | 说明 | 数据类型 | 默认值 | 可否为空 | 可选参数 | -| -- | -- | -- | -- | -- | -- | -| success | 该条请求成功与否,返回 false 或者无该字段,不会处理回复,**有一些特殊消息也通过这个字段控制,比如加好友邀请,返回 `true` 则会通过好友请求** | `Boolean` | - | Y | `true` `false` | -| data | 如果需要回复消息的话,需要定义data字段 | `Object` `Object Array` | - | Y | | - -#### `response.data` 结构 - -| 参数 | 说明 | 数据类型 | 默认值 | 可否为空 | 可选参数 | -| -- | -- | -- | -- | -- | -- | -| type | **消息类型**,该字段不填默认当文本类型传输 | `String` | `text` | Y | `text` `fileUrl` | 支持 **文字** 和 **文件**, | -| content | **消息内容**,如果希望发多个Url并解析,type 指定为 fileUrl 同时,content 里填 url 以英文逗号分隔 | `String` | - | N | - | - -如果回复单条消息 - -```json - { - "success": true, - "data": { - "type": "text", - "content": "hello world!" - } - } -``` - -组合回复多条消息 - -```json - { - "success": true, - "data": [ - { - "type": "text", - "content": "hello world!" - }, - { - "type": "fileUrl", - "content": "https://samplelib.com/lib/preview/mp3/sample-3s.mp3" - } - ] - } -``` - -### 3. 其他API - -#### token 配置说明 -> 除了在 docker 启动时配置token,在默认缺省 token 的情况,会默认生成一个写入 `.env` 文件中 - -#### 3.1 获取登录二维码接口 -- **地址**:`/login` -- **methods**: `GET` -- **query**: token -- **status**: `200` -- **example**: http://localhost:3001/login?token=[YOUR_PERSONAL_TOKEN] - -##### 登录成功 - -返回 json 包含当前用户 - -```json -{"success":true,"message":"Contactis already login"} -``` - -##### 登录失败 - -展示微信登录扫码页面 - -#### 3.2 健康检测接口 - -可以主动轮询该接口,检查服务是否正常运行 - -- **地址**:`/healthz` -- **methods**: `GET` -- **query**: token -- **status**: `200` -- **example**: http://localhost:3001/healthz?token=[YOUR_PERSONAL_TOKEN] - -微信已登录, 返回纯文本 `healthy`,否则返回 `unHealthy` - -#### 3.3 获取静态资源接口 - -从 2.8.0 版本开始,可以通过本接口访问到头像等静态资源,具体见 [recvd_api 数据结构示例的 avatar 字段](/docs/recvdApi.example.md#2-formdatasource-string) - -注意所有上报 recvd_api 的静态资源地址不会默认带上 token, 需要自己拼接,否则会返回 401 错误, 请确保自己微信已登录,需要通过登录态去获取资源 - -- **地址**:`/resouces` -- **methods**: `GET` -- **query**: - - token: 登录token - - media: encode过的相对路径,比如 `/avatar/1234567890.jpg` encode为 `avatar%2F1234567890.jpg` -- **status**: `200` `404` `401` - -- **example**:http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxgetheadimg%3Fseq%3D83460%26username%3D%40%4086815a%26skey%3D&token=[YOUR_PERSONAL_TOKEN] - -##### status: `200` - -成功获取资源, 返回静态资源文件 - -##### status: `404` - -获取资源失败 - -##### status: `401` 未携带登录token - -```json -{"success":false, "message":"Unauthorized: Access is denied due to invalid credentials."} -``` - -##### status: `401` 微信登录态已过期 - -```json -{ - "success": false, "message": "you must login first" -} -``` ## 🌟 Star History diff --git a/commitlint.config.js b/commitlint.config.ts similarity index 100% rename from commitlint.config.js rename to commitlint.config.ts diff --git a/.dockerignore b/docker/.dockerignore similarity index 100% rename from .dockerignore rename to docker/.dockerignore diff --git a/docker-compose.yml b/docker/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to docker/docker-compose.yml diff --git a/dockerfile b/docker/dockerfile similarity index 100% rename from dockerfile rename to docker/dockerfile diff --git a/docs/recvdApi.example.md b/docs/recvdApi.example.md index 40869ca..ff0611b 100644 --- a/docs/recvdApi.example.md +++ b/docs/recvdApi.example.md @@ -73,7 +73,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 "friend": false, "gender": 1, "id": "@xxx", @@ -98,7 +98,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 "friend": false, "gender": 1, "id": "@xxx", @@ -125,7 +125,7 @@ "id": "@xxxasdfsf", "payload": { "alias": "", - "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 "friend": false, "gender": 1, "id": "@xxx", @@ -168,7 +168,7 @@ "memberList": [ { id: '@xxxx', - avatar: "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + avatar: "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 name:'昵称', alias: '备注名'/** 个人备注名,非群备注名 */ } ] @@ -185,7 +185,7 @@ "payload": { "alias": "", //备注名 - "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 "friend": false, "gender": 1, "id": "@xxx", @@ -206,7 +206,7 @@ "payload": { "alias": "", - "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //请配合 token=[YOUR_PERSONAL_TOKEN] 解密 + "avatar": "http://localhost:3001/resouces?media=%2Fcgi-bin%2Fmmwebwx-bixxx", //拼接参数 token=[YOUR_PERSONAL_TOKEN] 访问 "city": "北京", "friend": true, "gender": 1, diff --git a/main.js b/main.js deleted file mode 100644 index e899ae5..0000000 --- a/main.js +++ /dev/null @@ -1,18 +0,0 @@ -require('dotenv').config({ - path: process.env.homeEnvCfg /** 兼容cli调用 */ ?? './.env' -}) -require('./src/utils/index').proxyConsole() -const { PORT } = process.env -const { Hono } = require('hono') -const { serve } = require('@hono/node-server') -const wechatBotInit = require('./src/wechaty/init') -const registerRoute = require('./src/route') -const bot = wechatBotInit() -const app = new Hono() - -registerRoute({ app, bot }) - -serve({ - fetch: app.fetch, - port: Number(PORT) -}) diff --git a/package.json b/package.json index ca9a23c..40353f8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,18 @@ { "name": "wechatbot-webhook", "version": "2.8.0", - "description": "一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于 http 请求", + "description": "微信机器人webhook,帮你抹平了很多自己开发的障碍,基于 http 请求", + "main": "index.js", + "scripts": { + "watch": "tsc -w", + "lint": "npx oxlint && npx eslint", + "build": "tsc && swc src -d dist/esm", + "prepare": "husky" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/danni-cool/wechatbot-webhook.git" + }, "keywords": [ "wechat", "bot", @@ -9,74 +20,32 @@ "wechaty", "http-service" ], - "main": "main.js", - "scripts": { - "prestart": "node ./scripts/preStart", - "start": "node main", - "build:cli": "pnpm --filter wechatbot-webhook run build" - }, - "engines": { - "node": ">=18.14.1" - }, - "author": { - "name": "danni-cool", - "email": "contact@danni.cool" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/danni-cool/wechatbot-webhook.git" - }, - "lint-staged": { - "**/*.{js,jsx,ts,tsx}": [ - "./scripts/tsc-lint.sh", - "eslint --fix", - "prettier --write" - ] - }, + "author": "", + "license": "MIT", "husky": { "hooks": { "pre-commit": "lint-staged" } }, - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.3.3", - "chalk": "^4.1.2", - "dotenv": "^16.3.1", - "file-box": "1.4.15", - "form-data": "^4.0.0", - "gerror": "^1.0.16", - "hono": "^3.11.11", - "lodash.clonedeep": "^4.5.0", - "log4js": "^6.9.1", - "mime": "^3.0.0", - "node-fetch-commonjs": "^3.3.2", - "qrcode-terminal": "^0.12.0", - "wechaty": "^1.20.2" + "lint-staged": { + "**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}": [ + "oxlint", + "prettier --write" + ] }, "devDependencies": { - "@commitlint/config-conventional": "^18.1.0", - "@types/eslint": "^8.56.0", - "@types/mime": "^3.0.4", - "@types/qrcode-terminal": "^0.12.2", - "@typescript-eslint/eslint-plugin": "^6.16.0", + "@commitlint/config-conventional": "^19.2.2", + "@swc/cli": "^0.3.10", + "@swc/core": "^1.4.11", + "@types/node": "^20.11.30", "@typescript-eslint/parser": "^6.16.0", - "eslint": "^8.56.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.2", - "husky": "^8.0.3", - "i": "^0.3.7", - "npm": "^10.5.0", - "prettier": "^3.1.1", - "tsc-files": "^1.1.4", - "typescript": "^5.3.3", - "wechaty-puppet-mock": "^1.18.2" - }, - "pnpm": { - "patchedDependencies": { - "wechat4u@0.7.14": "patches/wechat4u@0.7.14.patch", - "wechaty-puppet-wechat4u@1.14.13": "patches/wechaty-puppet-wechat4u@1.14.13.patch", - "wechaty-puppet@1.20.2": "patches/wechaty-puppet@1.20.2.patch" - } + "eslint-plugin-oxlint": "^0.2.9", + "eslint-plugin-prettier": "^5.2.1", + "husky": "^9.1.1", + "oxlint": "^0.2.18", + "prettier": "^3.3.3", + "typescript": "^5.5.3" } } diff --git a/packages/cli/README.md b/packages/cli/README.md index 101d2e2..ca58460 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,5 +1,5 @@
- + ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/danni-cool/wechatbot-webhook/release.yml) ![npm dowloads](https://img.shields.io/npm/dm/wechatbot-webhook?label=npm/downloads) ![Docker Pulls](https://img.shields.io/docker/pulls/dannicool/docker-wechatbot-webhook) ![GitHub release (with filter)](https://img.shields.io/github/v/release/danni-cool/wechatbot-webhook) @@ -70,7 +70,7 @@ curl --location 'http://localhost:3001/webhook/msg/v2?token=[YOUR_PERSONAL_TOKEN ## 🛠️ API -[API Reference](https://github.com/danni-cool/docker-wechatbot-webhook#%EF%B8%8F-api) +[API Reference](https://github.com/danni-cool/wechatbot-webhook/wiki) ## ⏫ 更新日志 diff --git a/.env.example b/packages/core/.env.example similarity index 100% rename from .env.example rename to packages/core/.env.example diff --git a/typings/global.d.ts b/packages/core/global.d.ts similarity index 88% rename from typings/global.d.ts rename to packages/core/global.d.ts index 402e37f..d99b9c4 100644 --- a/typings/global.d.ts +++ b/packages/core/global.d.ts @@ -25,9 +25,22 @@ type pushMsgValidPayload = { type payloadFormFile = File & { convertName: string } -type pushMsgUnitPayload = { type: 'text' | 'fileUrl'; content: string } +type pushMsgUnitPayload = { + type: 'text' | 'fileUrl' | 'file' | 'base64' + content: string + fileAlias?: string +} + +type pushMsgUnitTypeOpt = { + type?: 'text' | 'fileUrl' | 'file' | 'base64' + content?: string + fileAlias?: string +} -type pushMsgUnitTypeOpt = { type?: 'text' | 'fileUrl'; content?: string } +type msgData = { + success?: boolean + error?: never +} & pushMsgUnitTypeOpt type toType = string | { alias: string } @@ -91,7 +104,10 @@ type msg2SingleRejectReason = { type failedTaskType = { to: toType isRoom?: boolean - data: pushMsgUnitTypeOpt | pushMsgUnitTypeOpt[] | [] + data: + | (pushMsgUnitTypeOpt & { error?: never }) + | (pushMsgUnitTypeOpt & { error?: never })[] + | [] } type sendingTaskType = { diff --git a/packages/core/hono.d.ts b/packages/core/hono.d.ts new file mode 100644 index 0000000..14aed8b --- /dev/null +++ b/packages/core/hono.d.ts @@ -0,0 +1,7 @@ +import { wxProviderInterface } from '@/utils/types' + +declare module 'hono' { + interface Context { + wxProvider: wxProviderInterface + } +} diff --git a/packages/core/index.ts b/packages/core/index.ts new file mode 100644 index 0000000..6f0fefe --- /dev/null +++ b/packages/core/index.ts @@ -0,0 +1,38 @@ +// require('dotenv').config({ +// path: process.env.homeEnvCfg /** 兼容cli调用 */ ?? './.env' +// }) +// require('./src/utils/index').proxyConsole() +import { envType, wxProviderInterface } from '@/utils/types' +import { Hono } from 'hono' +import { serve } from '@hono/node-server' +import registerRoute from '@/core/src/route' + +export default class WXBotHttpService { + public config: envType + private wxProvider: wxProviderInterface + + constructor({ + envCfg = {} as envType, + wxProvider = {} as wxProviderInterface + }) { + this.config = envCfg + this.wxProvider = wxProvider + } + + use(wxProvider: wxProviderInterface) { + this.wxProvider = wxProvider + return this + } + + start() { + const app = new Hono() + // const wechatBotInit = require('./src/wechaty/init') + // const bot = wechatBotInit() + registerRoute({ app, bot }) + + serve({ + fetch: app.fetch, + port: Number(this.config.PORT) + }) + } +} diff --git a/typings/lodash.d.ts b/packages/core/lodash.d.ts similarity index 100% rename from typings/lodash.d.ts rename to packages/core/lodash.d.ts diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..3010523 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,5 @@ +{ + "name": "@wechatbot-webhook/core", + "version": "0.0.1", + "main": "index.ts" +} \ No newline at end of file diff --git a/src/config/const.js b/packages/core/src/config/const.ts similarity index 98% rename from src/config/const.js rename to packages/core/src/config/const.ts index d43cd72..be26352 100644 --- a/src/config/const.js +++ b/packages/core/src/config/const.ts @@ -1,5 +1,5 @@ const path = require('path') -const { PORT } = process.env +// const { PORT } = process.env const config = { /** diff --git a/src/config/log4jsFilter.js b/packages/core/src/config/log4jsFilter.ts similarity index 100% rename from src/config/log4jsFilter.js rename to packages/core/src/config/log4jsFilter.ts diff --git a/src/config/valid.js b/packages/core/src/config/valid.ts similarity index 98% rename from src/config/valid.js rename to packages/core/src/config/valid.ts index 9173c61..9b24c84 100644 --- a/src/config/valid.js +++ b/packages/core/src/config/valid.ts @@ -38,7 +38,7 @@ module.exports = { val: type, required: false, type: 'string', - enum: ['text', 'fileUrl'], + enum: ['text', 'fileUrl', 'base64'], unValidReason: '' }, { diff --git a/packages/core/src/middleware/index.ts b/packages/core/src/middleware/index.ts new file mode 100644 index 0000000..fca96d1 --- /dev/null +++ b/packages/core/src/middleware/index.ts @@ -0,0 +1,7 @@ +import { loginCheck } from './loginCheck' +import { verifyToken } from './verifyToken' + +export default { + loginCheck, + verifyToken +} diff --git a/packages/core/src/middleware/loginCheck.ts b/packages/core/src/middleware/loginCheck.ts new file mode 100644 index 0000000..0323da0 --- /dev/null +++ b/packages/core/src/middleware/loginCheck.ts @@ -0,0 +1,13 @@ +import { type Context, type Next } from 'hono' + +export const loginCheck = async (c: Context, next: Next) => { + if (!c.bot.isLoggedIn) { + c.status(401) + return c.json({ + success: false, + message: 'you must login first' + }) + } + + await next() +} diff --git a/src/middleware/verifyToken.js b/packages/core/src/middleware/verifyToken.ts similarity index 59% rename from src/middleware/verifyToken.js rename to packages/core/src/middleware/verifyToken.ts index c63ef22..d480cf9 100644 --- a/src/middleware/verifyToken.js +++ b/packages/core/src/middleware/verifyToken.ts @@ -1,9 +1,6 @@ -/** - * middleware of token verification - * @param {import('hono').Context} c - * @param {import('hono').Next} next - */ -module.exports.verifyToken = async (c, next) => { +import { type Context, type Next } from 'hono' + +export const verifyToken = async (c: Context, next: Next) => { const { token } = c.req.query() if (token !== process.env.globalLoginToken) { diff --git a/packages/core/src/model/contact.ts b/packages/core/src/model/contact.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/core/src/model/room.ts b/packages/core/src/model/room.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/core/src/route/index.ts b/packages/core/src/route/index.ts new file mode 100644 index 0000000..d3a665a --- /dev/null +++ b/packages/core/src/route/index.ts @@ -0,0 +1,24 @@ +import { type Hono, type Context, type Next } from 'hono' +import Middleware from '../middleware/index' +import { wxProviderInterface } from '@/utils/types' + +export function registerRoute({ + app, + wxProvider = {} as wxProviderInterface +}: { + app: Hono + wxProvider: wxProviderInterface +}) { + const attachData = (ctx: Context, next: Next) => { + ctx.wxProvider = wxProvider + return next() + } + // 挂载wecahty实例到全局路由 + app.use('*', attachData) + // 全局鉴权 + app.use(Middleware.verifyToken) + + require('./msg')({ app, bot }) + require('./login')({ app, bot }) + require('./resouces')({ app, bot }) +} diff --git a/src/route/login.js b/packages/core/src/route/login.ts similarity index 100% rename from src/route/login.js rename to packages/core/src/route/login.ts diff --git a/src/route/msg.js b/packages/core/src/route/msg.ts similarity index 95% rename from src/route/msg.js rename to packages/core/src/route/msg.ts index 00100ea..19bdf13 100644 --- a/src/route/msg.js +++ b/packages/core/src/route/msg.ts @@ -1,4 +1,5 @@ const Service = require('../service') +const { formatAndSendMsg } = require('../service/core') const Utils = require('../utils/index.js') const rules = require('../config/valid') const middleware = require('../middleware') @@ -12,7 +13,9 @@ function registerPushHook({ app, bot }) { // 处理 POST 请求 V2 支持多发模式 app.post('/webhook/msg/v2', middleware.loginCheck, async (c) => { let body + // 如果是formData + //如果是json try { body = await c.req.json() } catch (e) { @@ -149,11 +152,13 @@ function registerPushHook({ app, bot }) { ) if (msgReceiver !== undefined) { - const { success, error } = await Service.formatAndSendMsg({ + const { success, error } = await formatAndSendMsg({ isRoom, bot, - type, - content, + msgData: { + type, + content + }, msgInstance: msgReceiver }) diff --git a/src/route/resouces.js b/packages/core/src/route/resouces.ts similarity index 100% rename from src/route/resouces.js rename to packages/core/src/route/resouces.ts diff --git a/src/service/cache.js b/packages/core/src/service/cache.ts similarity index 100% rename from src/service/cache.js rename to packages/core/src/service/cache.ts diff --git a/packages/core/src/service/core.ts b/packages/core/src/service/core.ts new file mode 100644 index 0000000..6163936 --- /dev/null +++ b/packages/core/src/service/core.ts @@ -0,0 +1,116 @@ +/** + * 使用此功能调用 wechaty 发消息 + */ +const chalk = require('chalk') +const { MSG_TYPE_ENUM } = require('../config/const.js') +const Utils = require('../utils/index.js') +const { sendMsg2RecvdApi } = require('./msgUploader.js') + +/** + * 发送消息核心。这个处理程序将数据转换为标准格式,然后使用 wechaty 发送消息。 + * @type {{ + * (payload:{ + * isRoom?: boolean,bot:import('wechaty/impls').WechatyInterface, + * msgInstance: msgInstanceType, + * msgData: msgData + * }) : Promise<{success:boolean, error:any}>; + * }} + */ +module.exports.formatAndSendMsg = async function ({ + isRoom = false, + bot, + msgData: { type = 'text', fileAlias, content }, + msgInstance +}) { + let success = false + let error + /** @type {msgStructurePayload} */ + const emitPayload = { + content: '', + type: { + text: MSG_TYPE_ENUM.TEXT, + fileUrl: MSG_TYPE_ENUM.ATTACHMENT, + file: MSG_TYPE_ENUM.ATTACHMENT, + base64: MSG_TYPE_ENUM.ATTACHMENT + }[type], + type_display: { + text: '消息', + fileUrl: '文件', + file: '文件', + base64: '文件' + }[type], + self: true, + from: bot.currentUser, + to: msgInstance, + // @ts-ignore 此处一定是 roomInstance + room: isRoom ? msgInstance : '' + } + + try { + switch (type) { + // 纯文本 + case 'text': + //@ts-expect-errors 重载不是很好使,手动判断 + await msgInstance.say(content) + //@ts-expect-errors 重载不是很好使,手动判断 + emitPayload.content = content + msgSenderCallback(emitPayload) + break + + case 'base64': { + const file = await Utils.getMediaFromBase64(content, fileAlias) + //@ts-expect-errors 重载不是很好使,手动判断 + emitPayload.content = file + await msgInstance.say(file) + msgSenderCallback(emitPayload) + break + } + + case 'fileUrl': { + //@ts-expect-errors 重载不是很好使,手动判断 + const file = await Utils.getMediaFromUrl(content, fileAlias) + //@ts-expect-errors 重载不是很好使,手动判断 + emitPayload.content = file + await msgInstance.say(file) + msgSenderCallback(emitPayload) + break + } + + // 文件 + case 'file': + { + //@ts-expect-errors 重载不是很好使,手动判断 + const file = await Utils.getBufferFile(content) + await msgInstance.say(file) + //@ts-expect-errors 重载不是很好使,手动判断 + emitPayload.content = file + msgSenderCallback(emitPayload) + } + break + + default: + throw new Error('发送消息 type 不能为空') + } + success = true + } catch (/** @type {any} */ e) { + error = Utils.filterUseFulHttpError(e) + Utils.logger.error(e) + } + + return { success, error } +} + +/** 推消息api发送后 + * @param {msgStructurePayload} payload + */ +const msgSenderCallback = async (payload) => { + Utils.logger.info( + `调用 bot api 发送 ${payload.type_display} 给 ${chalk.blue(payload.to)}:`, + typeof payload.content === 'object' + ? payload.content._name ?? 'unknown file' + : payload.content + ) + + if (process.env.ACCEPT_RECVD_MSG_MYSELF !== 'true') return + sendMsg2RecvdApi(new Utils.ApiMsg(payload)) +} diff --git a/src/service/friendship.js b/packages/core/src/service/friendship.ts similarity index 100% rename from src/service/friendship.js rename to packages/core/src/service/friendship.ts diff --git a/src/service/index.js b/packages/core/src/service/index.ts similarity index 100% rename from src/service/index.js rename to packages/core/src/service/index.ts diff --git a/src/service/login.js b/packages/core/src/service/login.ts similarity index 100% rename from src/service/login.js rename to packages/core/src/service/login.ts diff --git a/src/service/msgSender.js b/packages/core/src/service/msgSender.ts similarity index 80% rename from src/service/msgSender.js rename to packages/core/src/service/msgSender.ts index 682e34d..a128164 100644 --- a/src/service/msgSender.js +++ b/packages/core/src/service/msgSender.ts @@ -1,5 +1,8 @@ +/** + * 处理发送单条、群发消息的校验、快捷回复、加好友等功能 + */ const Utils = require('../utils/index.js') -const chalk = require('chalk') +const { formatAndSendMsg } = require('./core.js') const { sendMsg2RecvdApi } = require('./msgUploader.js') const { MSG_TYPE_ENUM } = require('../config/const.js') const rules = require('../config/valid.js') @@ -382,20 +385,18 @@ const handleMsg2Single = async function (body, { bot, messageReceiver }) { if (msgReceiver) { if (Array.isArray(payload.data) && payload.data.length) { - /**@type {(pushMsgUnitTypeOpt & {success?:boolean, error?:string})[]} */ + /**@type { msgData[]} */ let msgArr = payload.data for (let i = 0; i < msgArr.length; i++) { const { success, error } = await formatAndSendMsg({ bot, isRoom, - type: msgArr[i].type || 'text', - // @ts-ignore - content: msgArr[i].content, + msgData: msgArr[i], msgInstance: msgReceiver }) msgArr[i].success = success if (!success) { - msgArr[i].error = error.toString() + msgArr[i].error = error } } @@ -418,12 +419,10 @@ const handleMsg2Single = async function (body, { bot, messageReceiver }) { : null } } else if (!Array.isArray(payload.data)) { - const { success } = await formatAndSendMsg({ + const { success, error } = await formatAndSendMsg({ isRoom, bot, - type: payload.data.type ?? 'text', - // @ts-ignore - content: payload.data.content, + msgData: payload.data, msgInstance: msgReceiver }) @@ -436,7 +435,7 @@ const handleMsg2Single = async function (body, { bot, messageReceiver }) { : { to, ...(isRoom !== undefined ? { isRoom } : {}), - data: [payload.data] + data: [{ ...payload.data, error }] } } } @@ -473,115 +472,6 @@ const getPushMsgUnitUnvalidStr = function ({ type, content }) { .join(',') } -/** - * 发送消息核心。这个处理程序将数据转换为标准格式,然后使用 wechaty 发送消息。 - * @type {{ - * (payload:{ isRoom?: boolean,bot:import('wechaty/impls').WechatyInterface, type: 'text' | 'fileUrl'|'file', content: string| payloadFormFile, msgInstance: msgInstanceType }) : Promise<{success:boolean, error:any}>; - * }} - */ -const formatAndSendMsg = async function ({ - isRoom = false, - bot, - type, - content, - msgInstance -}) { - let success = false - let error - /** @type {msgStructurePayload} */ - const emitPayload = { - content: '', - type: { - text: MSG_TYPE_ENUM.TEXT, - fileUrl: MSG_TYPE_ENUM.ATTACHMENT, - file: MSG_TYPE_ENUM.ATTACHMENT - }[type], - type_display: { - text: '消息', - fileUrl: '文件', - file: '文件' - }[type], - self: true, - from: bot.currentUser, - to: msgInstance, - // @ts-ignore 此处一定是 roomInstance - room: isRoom ? msgInstance : '' - } - - try { - switch (type) { - // 纯文本 - case 'text': - //@ts-expect-errors 重载不是很好使,手动判断 - await msgInstance.say(content) - //@ts-expect-errors 重载不是很好使,手动判断 - emitPayload.content = content - msgSenderCallback(emitPayload) - break - - case 'fileUrl': { - //@ts-expect-errors 重载不是很好使,手动判断 - const fileUrlArr = content.split(',') - - // 单文件 - if (fileUrlArr.length === 1) { - //@ts-expect-errors 重载不是很好使,手动判断 - const file = await Utils.getMediaFromUrl(content) - //@ts-expect-errors 重载不是很好使,手动判断 - emitPayload.content = file - await msgInstance.say(file) - msgSenderCallback(emitPayload) - break - } - - // 多个文件的情况 - for (let i = 0; i < fileUrlArr.length; i++) { - const file = await Utils.getMediaFromUrl(fileUrlArr[i]) - //@ts-expect-errors 重载不是很好使,手动判断 - emitPayload.content = file - await msgInstance.say(file) - msgSenderCallback(emitPayload) - } - break - } - // 文件 - case 'file': - { - //@ts-expect-errors 重载不是很好使,手动判断 - const file = await Utils.getBufferFile(content) - await msgInstance.say(file) - //@ts-expect-errors 重载不是很好使,手动判断 - emitPayload.content = file - msgSenderCallback(emitPayload) - } - break - default: - throw new Error('发送消息 type 不能为空') - } - success = true - } catch (/** @type {any} */ e) { - error = e - Utils.logger.error(e) - } - - return { success, error } -} - -/** 推消息api发送后 - * @param {msgStructurePayload} payload - */ -const msgSenderCallback = async (payload) => { - Utils.logger.info( - `调用 bot api 发送 ${payload.type_display} 给 ${chalk.blue(payload.to)}:`, - typeof payload.content === 'object' - ? payload.content._name ?? 'unknown file' - : payload.content - ) - - if (process.env.ACCEPT_RECVD_MSG_MYSELF !== 'true') return - sendMsg2RecvdApi(new Utils.ApiMsg(payload)) -} - /** * 接受 Service.sendMsg2RecvdApi 的response 回调以便回复或作出其他动作 * @param {Object} payload @@ -699,7 +589,6 @@ const onRecvdMessage = async (msg, bot) => { } module.exports = { - formatAndSendMsg, handleResSendMsg, onRecvdMessage, getPushMsgUnitUnvalidStr, diff --git a/src/service/msgUploader.js b/packages/core/src/service/msgUploader.ts similarity index 81% rename from src/service/msgUploader.js rename to packages/core/src/service/msgUploader.ts index f71d431..8fcd33a 100644 --- a/src/service/msgUploader.js +++ b/packages/core/src/service/msgUploader.ts @@ -4,7 +4,7 @@ const { config, systemMsgEnumMap } = require('../config/const') const FormData = require('form-data') const { LOCAL_RECVD_MSG_API, RECVD_MSG_API } = process.env const { MSG_TYPE_ENUM } = require('../config/const') -const cacheTool = require('../service/cache') +const cacheTool = require('./cache') const cloneDeep = require('lodash.clonedeep') /** * 收到消息上报接受url @@ -122,36 +122,21 @@ async function sendMsg2RecvdApi(msg) { formData.append('isMsgFromSelf', msg.self() ? '1' : '0') switch (msg.type()) { - case MSG_TYPE_ENUM.ATTACHMENT: + case MSG_TYPE_ENUM.ATTACHMENT: { + // hack, 如果附件类型消息 + try { + dealWithFileMsg(formData, msg) + } catch (e) { + /** 已知场景转发会进入这个逻辑,但好像还是没法显示转发内容,当unknown处理 */ + formData.append('type', 'unknown') + formData.append('content', msg.text()) /** 当前不支持该消息展示 */ + } + break + } case MSG_TYPE_ENUM.VOICE: case MSG_TYPE_ENUM.PIC: case MSG_TYPE_ENUM.VIDEO: { - // 视频 - formData.append('type', 'file') - /**@type {import('file-box').FileBox} */ - //@ts-expect-errors 这里msg一定是wechaty的msg - const steamFile = msg.toFileBox ? await msg.toFileBox() : msg.content() - - let fileInfo = { - // @ts-ignore - ext: steamFile._name.split('.').pop() ?? '', - // @ts-ignore - mime: steamFile._mediaType ?? 'Unknown', - // @ts-ignore - filename: steamFile._name ?? 'UnknownFile' - } - - formData.append( - 'content', - //@ts-expect-errors 需要用到私有属性 - steamFile.buffer /** 发送一个文件 */ ?? - //@ts-expect-errors 需要用到私有属性 - steamFile.stream /** 同一个文件转发 */, - { - filename: fileInfo.filename, - contentType: fileInfo.mime - } - ) + dealWithFileMsg(formData, msg) break } // 分享的Url @@ -220,6 +205,40 @@ async function sendMsg2RecvdApi(msg) { return response } +/** + * 抽离附件上传公共逻辑 + * @param {import('form-data')} formData + * @param {extendedMsg} msg + */ +async function dealWithFileMsg(formData, msg) { + /**@type {import('file-box').FileBox} */ + //@ts-expect-errors 这里msg一定是wechaty的msg + const steamFile = msg.toFileBox ? await msg.toFileBox() : msg.content() + // 上面尝试转化文件报错就不会进入以下逻辑 + formData.append('type', 'file') + + let fileInfo = { + // @ts-ignore + ext: steamFile._name.split('.').pop() ?? '', + // @ts-ignore + mime: steamFile._mediaType ?? 'Unknown', + // @ts-ignore + filename: steamFile._name ?? 'UnknownFile' + } + + formData.append( + 'content', + //@ts-expect-errors 需要用到私有属性 + steamFile.buffer /** 发送一个文件 */ ?? + //@ts-expect-errors 需要用到私有属性 + steamFile.stream /** 同一个文件转发 */, + { + filename: fileInfo.filename, + contentType: fileInfo.mime + } + ) +} + module.exports = { sendMsg2RecvdApi } diff --git a/src/utils/index.js b/packages/core/src/utils/index.ts similarity index 66% rename from src/utils/index.js rename to packages/core/src/utils/index.ts index 9f4e19f..017d8e3 100644 --- a/src/utils/index.js +++ b/packages/core/src/utils/index.ts @@ -1,12 +1,55 @@ const { FileBox } = require('file-box') const MIME = require('mime') -const { logger } = require('./log') +const { logger } = require('./log.js') const { URL } = require('url') +/** + * 转化base64为buffer, 并尝试获取文件类型content-type + * @param {string} base64 + * @returns {Promise<{buffer?: Buffer, fileName?: string}>} + */ +const base64ToBuffer = async (base64) => { + let mimeType = null + + /*** + * 提取并解析 MIME 类型(如果存在) + * @param {string} base64 + */ + const getMimeTypeFromUri = (base64) => { + const matches = base64.match(/^data:(.*?);base64,/) + if (matches) { + return matches[1] + } + return null + } + + // 检查是否包含 Data URI scheme + mimeType = getMimeTypeFromUri(base64) + + // 如果没有 Data URI scheme,处理纯 Base64 字符串 + const base64StringWithoutPrefix = base64.replace(/^data:.*?;base64,/, '') + const buffer = Buffer.from(base64StringWithoutPrefix, 'base64') + // commonjs require esm module + const { fileTypeFromBuffer } = await import('file-type') + + if (!mimeType) { + const fileType = await fileTypeFromBuffer(buffer) + mimeType = fileType ? fileType.mime : 'unknown' + } + + const extName = MIME.getExtension(mimeType) + + return { + buffer, + fileName: `${Date.now()}.${extName}` + } +} + /** * 下载媒体文件转化为Buffer * @param {string} fileUrl - * @returns {Promise<{buffer?: Buffer, fileName?: string, fileNameAlias?: string, contentType?: null | string}>} + * @param {*} headers + * @returns {Promise<{buffer?: Buffer, fileName?: string, contentType?: null | string}>} */ const downloadFile = async (fileUrl, headers = {}) => { try { @@ -15,7 +58,7 @@ const downloadFile = async (fileUrl, headers = {}) => { if (response.ok) { const buffer = Buffer.from(await response.arrayBuffer()) // 使用自定义文件名,解决URL无文件后缀名时,文件被微信解析成不正确的后缀问题 - let { fileName, query } = getFileInfoFromUrl(fileUrl) + let { fileName } = getFileInfoFromUrl(fileUrl) let contentType = response.headers.get('content-type') // deal with unValid Url format like https://pangji-home.com/Fi5DimeGHBLQ3KcELn3DolvENjVU @@ -29,8 +72,7 @@ const downloadFile = async (fileUrl, headers = {}) => { return { buffer, fileName, - contentType, - fileNameAlias: query?.$alias + contentType } } @@ -70,10 +112,24 @@ const getFileInfoFromUrl = (url) => { /** * 根据url下载文件并转化成FileBox的标准格式 * @param {string} url + * @param {string} fileNameAlias * @returns {Promise} */ -const getMediaFromUrl = async (url) => { - const { buffer, fileName, fileNameAlias } = await downloadFile(url) +const getMediaFromUrl = async (url, fileNameAlias) => { + const { buffer, fileName } = await downloadFile(url) + //@ts-expect-errors buffer 解析是吧的情况 + return FileBox.fromBuffer(buffer, fileNameAlias || fileName) +} + +/** + * 传入base64 返回文件 buffer + * @param {*} base64Str + * @param {*} fileNameAlias + * @returns + */ +const getMediaFromBase64 = async (base64Str, fileNameAlias) => { + const { buffer, fileName } = await base64ToBuffer(base64Str) + //@ts-expect-errors buffer 解析是吧的情况 return FileBox.fromBuffer(buffer, fileNameAlias || fileName) } @@ -182,28 +238,46 @@ const sleep = async (ms) => { } /** - * 删除登录缓存文件 + * 过滤有价值的发送消息报错信息 + * @param {*} error */ -// const deleteMemoryCard = () => { -// //@ts-expect-errors 必定是 pathlike -// if (fs.existsSync(memoryCardPath)) { -// //@ts-expect-errors 必定是 pathlike -// fs.unlinkSync(memoryCardPath) -// } -// } +const filterUseFulHttpError = (error) => { + let newErrorObj = {} + + if (error.tips) { + newErrorObj.tips = error.tips + newErrorObj.code = error.code + newErrorObj.stack = error.stack + + if (error.response) { + newErrorObj.response = {} + newErrorObj.response.status = error.response.status + newErrorObj.response.statusText = error.response.statusText + newErrorObj.response.url = error.response.url + newErrorObj.response.method = error.response.method + newErrorObj.response.method = error.response.method + newErrorObj.response.data = error.response.data + } + return newErrorObj + } else { + return error + } +} module.exports = { ...require('./msg.js'), ...require('./nextTick.js'), ...require('./paramsValid.js'), ...require('./log.js'), - ...require('./res'), + ...require('./res.js'), downloadFile, + getMediaFromBase64, getMediaFromUrl, getBufferFile, generateToken, parseJsonLikeStr, tryConvertCnCharToUtf8Char, sleep, - Defer + Defer, + filterUseFulHttpError } diff --git a/src/utils/log.js b/packages/core/src/utils/log.ts similarity index 100% rename from src/utils/log.js rename to packages/core/src/utils/log.ts diff --git a/src/utils/msg.js b/packages/core/src/utils/msg.ts similarity index 100% rename from src/utils/msg.js rename to packages/core/src/utils/msg.ts diff --git a/src/utils/nextTick.js b/packages/core/src/utils/nextTick.ts similarity index 100% rename from src/utils/nextTick.js rename to packages/core/src/utils/nextTick.ts diff --git a/src/utils/paramsValid.js b/packages/core/src/utils/paramsValid.ts similarity index 100% rename from src/utils/paramsValid.js rename to packages/core/src/utils/paramsValid.ts diff --git a/src/utils/res.js b/packages/core/src/utils/res.ts similarity index 100% rename from src/utils/res.js rename to packages/core/src/utils/res.ts diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..d6fe94c --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,4 @@ +{ + "name": "@wechatbot-webhook/utils", + "version": "0.0.1" +} \ No newline at end of file diff --git a/packages/utils/types/contact.d.ts b/packages/utils/types/contact.d.ts new file mode 100644 index 0000000..55158be --- /dev/null +++ b/packages/utils/types/contact.d.ts @@ -0,0 +1,20 @@ +export type contactType = { + /** 唯一动态id,为了避免两个人同一个昵称的情况,但是不要过于依赖该字段,每次启动程序都会变,是属于方便程序找到当前环境唯一用户增加 */ + uuid: string + /** 联系人微信id,web微信没有该字段 */ + wxid: string + /** 微信昵称 */ + name: string + /** 微信备注 */ + remark: string + /** 性别 */ + gentle: '男' | '女' | '未知' + /** 手机号 */ + phone: string + /** 地区 */ + home: string + /** 年龄 */ + age: number + /** 头像 (需要用户自己获取)*/ + avatar: string +} diff --git a/packages/utils/types/env.d.ts b/packages/utils/types/env.d.ts new file mode 100644 index 0000000..58247ee --- /dev/null +++ b/packages/utils/types/env.d.ts @@ -0,0 +1,17 @@ +declare namespace NodeJS { + interface ProcessEnv { + /** 服务启动的端口 */ + PORT: string | number + /** 运行时提示的消息等级(默认info,想有更详细的日志,可以指定为debug) */ + LOG_LEVEL: 'info' | 'debug' + /** 如果不希望登录一次后就记住当前账号,想每次都扫码登陆(仅对web协议生效)*/ + DISABLE_AUTO_LOGIN: 'true' | 'false' + /** RECVD_MSG_API 是否接收来自自己发的消息 */ + ACCEPT_RECVD_MSG_MYSELF: 'true' | 'false' + /** 如果想自己处理收到消息的逻辑,在下面填上你的API地址, 默认为空 */ + LOCAL_RECVD_MSG_API: string + /** 登录地址Token访问地址: http://localhost:3001/login?token=[LOCAL_LOGIN_API_TOKEN] */ + LOCAL_LOGIN_API_TOKEN: string + // 添加其他环境变量 + } +} diff --git a/packages/utils/types/index.d.ts b/packages/utils/types/index.d.ts new file mode 100644 index 0000000..0553ba6 --- /dev/null +++ b/packages/utils/types/index.d.ts @@ -0,0 +1,4 @@ +export * from './msg' +export * from './contact' +export * from './env' +export { default as wxProviderInterface } from './provider-define.d' diff --git a/packages/utils/types/msg.d.ts b/packages/utils/types/msg.d.ts new file mode 100644 index 0000000..0cc7c8a --- /dev/null +++ b/packages/utils/types/msg.d.ts @@ -0,0 +1,104 @@ +import { RequireOne } from './utils' + +type msgTextBase = { + uuid: string + /** 需要艾特人的集合,群聊时可用,数组里必须填 wxid */ + atList?: string[] + /** 要发送的文字 */ + content: string +} + +export type msgText = msgTextBase & + RequireOne< + { + /** 微信wxid, 查找优先级 wxid > name > remark */ + wxid?: string + /** 微信昵称or群名,查找优先级 wxid > name > remark */ + name?: string + /** 备注(非群昵称备注),查找优先级 wxid > name > remark */ + remark?: string + }, + 'wxid' | 'name' | 'remark' + > + +type msgFileBase = { + /** 需要艾特人的集合,群聊时可用,数组里必须填 wxid */ + atList?: string[] + /** 要发送的文字 */ + content: File +} + +export type msgFile = msgFileBase & + RequireOne< + { + /** 微信wxid, 查找优先级 wxid > name > remark */ + wxid?: string + /** 微信昵称or群名,查找优先级 wxid > name > remark */ + name?: string + /** 备注(非群昵称备注),查找优先级 wxid > name > remark */ + remark?: string + }, + 'wxid' | 'name' | 'remark' + > + +/** + * 所有消息类型枚举 + */ +export enum msgType { + /** 未知 */ + UNKNOWN = 0, + /** 各种文件 */ + ATTACHMENT = 1, //共享实时位置、文件、转账、链接 wcferry 3 + /** 语音 */ + VOICE = 2, // 语音 wcferry 9999 + /** 表情包 */ + EMOTION = 5, // wcferry 62, + /** 图片 */ + PIC = 6, // wcferry 34 + /** 文本 */ + TEXT = 7, + /** 公众号链接 */ + MEDIA_URL = 14, + /** 视频 */ + VIDEO = 15, + /** 红包、系统的信息 */ + WECHAT_SYSTEM = 37, + /** 撤回消息 */ + MSG_RECALL = 40, + /** 位置 */ + POSITION = 42, + /** 小视频 */ + MINI_VIDEO = 43, + /** 石头剪刀布 */ + ROCK_PAPER_SCISSORS = 47, + /** 好友确认 */ + FRIENDSHIP_CONFIRM = 48, + /** 名片 */ + CALLING_CARD = 49, + /** 系统提示 */ + SYSNOTICE = 52, + /** 网络电话通知 */ + VOIPNOTIFY = 51, + /** 好友邀请 or 好友通过消息(自定义类型) */ + // CUSTOM_FRIENDSHIP = 99, + /** 可能是朋友的消息 */ + POSSIBLEFRIEND_MSG = 10000, + + /** 系统消息类型 */ + /** 登录事件 */ + SYSTEM_EVENT_LOGIN = 1000, + /** 登出事件 */ + SYSTEM_EVENT_LOGOUT = 1001, + /** 错误事件 */ + SYSTEM_EVENT_ERROR = 1002 + /** @desperate 推送通知事件 */ + // SYSTEM_EVENT_PUSH_NOTIFY = 1003 +} + +/** + * 收到消息的返回体 + */ +export type msgRes = { + type: msgType + data: any +} diff --git a/packages/utils/types/provider-define.d.ts b/packages/utils/types/provider-define.d.ts new file mode 100644 index 0000000..8c7cadc --- /dev/null +++ b/packages/utils/types/provider-define.d.ts @@ -0,0 +1,24 @@ +import { msgText, msgFile, msgRes, contactType, contactCoreType } from '.' + +export default interface wxProviderInterface { + /** 显示当前provider的版本号 */ + version: string + /** 个人信息 */ + selfInfo: contactType | null + /** 是否已经登录 */ + get isLogin(): boolean + /** 是否初始化完成(比如windows协议是否连上rpc) */ + get isInitd(): boolean + /** 启动应用, 连接服务,返回sdk初始化状态 */ + run(): boolean + /** 重启应用, 重新登录或者更新所有联系人列表 */ + restart(): void + /** 销毁应用,解绑事件等,断开连接,登出 */ + destroy(): void + /** 发送文字消息 */ + sendTextMsg(data: msgText): Promise + /** 发送文件 */ + sendFile(data: msgFile): Promise + /** 监听消息 */ + on(event: 'message', callback: (data: msgRes) => void): this +} diff --git a/packages/utils/types/utils.d.ts b/packages/utils/types/utils.d.ts new file mode 100644 index 0000000..9c11655 --- /dev/null +++ b/packages/utils/types/utils.d.ts @@ -0,0 +1,11 @@ +/** 可选属性里面3选一必填 */ +export type RequireOne = Omit & + { + [K in Keys]: Required> & Partial, never>> + }[Keys] + +export type ToPlainType< + T extends { + toObject: () => unknown + } +> = Required> diff --git a/packages/web/package.json b/packages/web/package.json new file mode 100644 index 0000000..93fdc19 --- /dev/null +++ b/packages/web/package.json @@ -0,0 +1,82 @@ +{ + "name": "@wechatbot-webhook/web", + "version": "2.8.0", + "description": "一个小小的微信机器人webhook,帮你抹平了很多自己开发的障碍,基于 http 请求", + "keywords": [ + "wechat bot", + "rpa", + "webhook", + "wechaty", + "wechatFerry" + ], + "main": "main.js", + "scripts": { + "start": "node main", + "build:cli": "pnpm --filter wechatbot-webhook run build" + }, + "engines": { + "node": ">=18.14.1" + }, + "author": { + "name": "danni-cool", + "email": "contact@danni.cool" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/danni-cool/wechatbot-webhook.git" + }, + "lint-staged": { + "**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx}": [ + "./scripts/tsc-lint.sh", + "oxlint", + "prettier --write" + ] + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.3.3", + "@wcferry/core": "^0.1.6", + "chalk": "^4.1.2", + "dotenv": "^16.3.1", + "file-box": "1.4.15", + "file-type": "^19.0.0", + "form-data": "^4.0.0", + "gerror": "^1.0.16", + "hono": "^3.11.11", + "lodash.clonedeep": "^4.5.0", + "log4js": "^6.9.1", + "mime": "^3.0.0", + "node-fetch-commonjs": "^3.3.2", + "qrcode-terminal": "^0.12.0", + "wechaty": "^1.20.2" + }, + "devDependencies": { + "@commitlint/config-conventional": "^18.1.0", + "@types/eslint": "^8.56.0", + "@types/mime": "^3.0.4", + "@types/qrcode-terminal": "^0.12.2", + "@typescript-eslint/eslint-plugin": "^6.16.0", + "@typescript-eslint/parser": "^6.16.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.2", + "husky": "^8.0.3", + "npm": "^10.5.0", + "prettier": "^3.1.1", + "tsc-files": "^1.1.4", + "typescript": "^5.3.3", + "wechaty-puppet-mock": "^1.18.2" + }, + "pnpm": { + "patchedDependencies": { + "wechat4u@0.7.14": "patches/wechat4u@0.7.14.patch", + "wechaty-puppet-wechat4u@1.14.13": "patches/wechaty-puppet-wechat4u@1.14.13.patch", + "wechaty-puppet@1.20.2": "patches/wechaty-puppet@1.20.2.patch" + } + } +} diff --git a/patches/wechat4u@0.7.14.patch b/packages/web/patches/wechat4u@0.7.14.patch similarity index 100% rename from patches/wechat4u@0.7.14.patch rename to packages/web/patches/wechat4u@0.7.14.patch diff --git a/patches/wechaty-puppet-wechat4u@1.14.13.patch b/packages/web/patches/wechaty-puppet-wechat4u@1.14.13.patch similarity index 100% rename from patches/wechaty-puppet-wechat4u@1.14.13.patch rename to packages/web/patches/wechaty-puppet-wechat4u@1.14.13.patch diff --git a/patches/wechaty-puppet@1.20.2.patch b/packages/web/patches/wechaty-puppet@1.20.2.patch similarity index 100% rename from patches/wechaty-puppet@1.20.2.patch rename to packages/web/patches/wechaty-puppet@1.20.2.patch diff --git a/packages/web/uos.ts b/packages/web/uos.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/wechaty/init.js b/packages/web/wechaty/init.ts similarity index 100% rename from src/wechaty/init.js rename to packages/web/wechaty/init.ts diff --git a/packages/windows/.env.example b/packages/windows/.env.example new file mode 100644 index 0000000..3981fdd --- /dev/null +++ b/packages/windows/.env.example @@ -0,0 +1,17 @@ +# 启动服务的端口 +PORT=3001 + +# 运行时提示的消息等级(默认info,想有更详细的日志,可以指定为debug) +LOG_LEVEL=info + +# 如果不希望登录一次后就记住当前账号,想每次都扫码登陆,填 true +DISABLE_AUTO_LOGIN= + +# RECVD_MSG_API 是否接收来自自己发的消息 +ACCEPT_RECVD_MSG_MYSELF=false + +# 如果想自己处理收到消息的逻辑,在下面填上你的API地址, 默认为空 +LOCAL_RECVD_MSG_API= + +# 登录地址Token访问地址: http://localhost:3001/login?token=[LOCAL_LOGIN_API_TOKEN] +LOCAL_LOGIN_API_TOKEN= \ No newline at end of file diff --git a/packages/windows/env.d.ts b/packages/windows/env.d.ts new file mode 100644 index 0000000..42e3d42 --- /dev/null +++ b/packages/windows/env.d.ts @@ -0,0 +1,6 @@ +declare namespace NodeJS { + interface ProcessEnv { + /** 是否接受朋友圈消息 */ + RECVD_PYQ?: 'true' | 'false' + } +} diff --git a/packages/windows/impl.ts b/packages/windows/impl.ts new file mode 100644 index 0000000..15e7bd4 --- /dev/null +++ b/packages/windows/impl.ts @@ -0,0 +1,91 @@ +import { Wcferry } from '@wcferry/core' +import { UserInfo } from '@wcferry/core' +import { + contactType, + msgText, + contactCoreType, + wxProviderInterface +} from '@/utils/types' + +export default class WinProviderImpl implements wxProviderInterface { + public config: { + host: string + port: number + recvPyq: boolean + } + public version: string + public selfInfo: contactType | null + public contactList: contactType[] | [] + + private client: Wcferry | null + private destroyFn: (() => void) | null + + constructor({ host = '127.0.0.1', port = 10086, recvPyq = false }) { + this.client = null + this.config = { host, port, recvPyq } + this.selfInfo = null + this.contactList = [] + this.version = '' + this.destroyFn = null + } + + get getSelfInfo() { + return this.selfInfo + } + + get isLogin() { + return this.client?.isLogin() || false + } + + get isInitd() { + return this.client?.connected || false + } + + setSelfInfo(data: UserInfo) { + this.selfInfo = { + uuid: data.uuid, + wxid: '', + name: '', + remark: '', + gentle: '未知', + phone: '', + home: '', + age: 0, + avatar: '' + } + } + + run() { + const { host, port, recvPyq } = this.config + this.client = new Wcferry({ host, port, recvPyq }) + + this.client.start() + + this.isLogin && this.setSelfInfo(this.client.getUserInfo()) + + this.destroyFn = this.client.on((msg) => { + console.log('received message:', msg) + }) + + return this.isInitd + } + + restart() { + this.destroy() + this.run() + } + + destroy(): void { + this.destroyFn?.() + //TODO: 更新联系人列表等 + } + + on(key: 'message', callback) {} + + async sendTextMsg(data: msgText) { + // data.atList + return + } + + async sendFile() {} +} diff --git a/packages/windows/index.ts b/packages/windows/index.ts new file mode 100644 index 0000000..186aac3 --- /dev/null +++ b/packages/windows/index.ts @@ -0,0 +1,4 @@ +import httpService from '@wechatbot-webhook/core' +import wxProvider from './impl' + +httpService.use({provider: wxProvider}).start() \ No newline at end of file diff --git a/packages/windows/package.json b/packages/windows/package.json new file mode 100644 index 0000000..6d5bde6 --- /dev/null +++ b/packages/windows/package.json @@ -0,0 +1,8 @@ +{ + "name": "@wechatbot-webhook/windows", + "dependencies": { + "@wcferry/core": "^0.1.6", + "@wechatbot-webhook/core": "workspace:^", + "@wechatbot-webhook/utils": "workspace:^" + } +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d5c3b0..2027e43 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,24 +4,76 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -patchedDependencies: - wechat4u@0.7.14: - hash: mmirz2kximouh53sl2jk76abxe - path: patches/wechat4u@0.7.14.patch - wechaty-puppet-wechat4u@1.14.13: - hash: nq4vns7vah46g6vxziyzqg5jey - path: patches/wechaty-puppet-wechat4u@1.14.13.patch - wechaty-puppet@1.20.2: - hash: wwr5xvwazgbyb26ud6vwdruala - path: patches/wechaty-puppet@1.20.2.patch - importers: .: + devDependencies: + '@commitlint/config-conventional': + specifier: ^19.2.2 + version: 19.2.2 + '@swc/cli': + specifier: ^0.3.10 + version: 0.3.14(@swc/core@1.7.0) + '@swc/core': + specifier: ^1.4.11 + version: 1.7.0 + '@types/node': + specifier: ^20.11.30 + version: 20.14.11 + '@typescript-eslint/parser': + specifier: ^6.16.0 + version: 6.16.0(eslint@8.57.0)(typescript@5.5.3) + eslint: + specifier: ^8.57.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-oxlint: + specifier: ^0.2.9 + version: 0.2.9 + eslint-plugin-prettier: + specifier: ^5.2.1 + version: 5.2.1(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.3.3) + husky: + specifier: ^9.1.1 + version: 9.1.1 + oxlint: + specifier: ^0.2.18 + version: 0.2.18 + prettier: + specifier: ^3.3.3 + version: 3.3.3 + typescript: + specifier: ^5.5.3 + version: 5.5.3 + + packages/cli: + dependencies: + commander: + specifier: ^11.1.0 + version: 11.1.0 + wechaty: + specifier: ^1.20.2 + version: 1.20.2(@swc/core@1.7.0)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) + wechaty-grpc: + specifier: ^1.0.1 + version: 1.0.1 + devDependencies: + esbuild: + specifier: ^0.19.10 + version: 0.19.10 + + packages/core: {} + + packages/provide-web: dependencies: '@hono/node-server': specifier: ^1.3.3 version: 1.3.3 + '@wcferry/core': + specifier: ^0.1.6 + version: 0.1.6 chalk: specifier: ^4.1.2 version: 4.1.2 @@ -31,6 +83,9 @@ importers: file-box: specifier: 1.4.15 version: 1.4.15 + file-type: + specifier: ^19.0.0 + version: 19.0.0 form-data: specifier: ^4.0.0 version: 4.0.0 @@ -57,7 +112,7 @@ importers: version: 0.12.0 wechaty: specifier: ^1.20.2 - version: 1.20.2(@swc/core@1.3.101)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) + version: 1.20.2(@swc/core@1.7.0)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) devDependencies: '@commitlint/config-conventional': specifier: ^18.1.0 @@ -73,56 +128,145 @@ importers: version: 0.12.2 '@typescript-eslint/eslint-plugin': specifier: ^6.16.0 - version: 6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.56.0)(typescript@5.3.3) + version: 6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/parser': specifier: ^6.16.0 - version: 6.16.0(eslint@8.56.0)(typescript@5.3.3) + version: 6.16.0(eslint@8.57.0)(typescript@5.5.3) eslint: specifier: ^8.56.0 - version: 8.56.0 + version: 8.57.0 eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@8.56.0) + version: 9.1.0(eslint@8.57.0) eslint-plugin-prettier: specifier: ^5.1.2 - version: 5.1.2(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1) + version: 5.2.1(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.3.3) husky: specifier: ^8.0.3 version: 8.0.3 - i: - specifier: ^0.3.7 - version: 0.3.7 npm: specifier: ^10.5.0 version: 10.5.0 prettier: specifier: ^3.1.1 - version: 3.1.1 + version: 3.3.3 tsc-files: specifier: ^1.1.4 - version: 1.1.4(typescript@5.3.3) + version: 1.1.4(typescript@5.5.3) typescript: specifier: ^5.3.3 - version: 5.3.3 + version: 5.5.3 wechaty-puppet-mock: specifier: ^1.18.2 version: 1.18.2(wechaty-puppet@1.20.2) - packages/cli: + packages/utils: {} + + packages/web: dependencies: - commander: - specifier: ^11.1.0 - version: 11.1.0 + '@hono/node-server': + specifier: ^1.3.3 + version: 1.3.3 + '@wcferry/core': + specifier: ^0.1.6 + version: 0.1.6 + chalk: + specifier: ^4.1.2 + version: 4.1.2 + dotenv: + specifier: ^16.3.1 + version: 16.3.1 + file-box: + specifier: 1.4.15 + version: 1.4.15 + file-type: + specifier: ^19.0.0 + version: 19.0.0 + form-data: + specifier: ^4.0.0 + version: 4.0.0 + gerror: + specifier: ^1.0.16 + version: 1.0.16 + hono: + specifier: ^3.11.11 + version: 3.11.11 + lodash.clonedeep: + specifier: ^4.5.0 + version: 4.5.0 + log4js: + specifier: ^6.9.1 + version: 6.9.1 + mime: + specifier: ^3.0.0 + version: 3.0.0 + node-fetch-commonjs: + specifier: ^3.3.2 + version: 3.3.2 + qrcode-terminal: + specifier: ^0.12.0 + version: 0.12.0 wechaty: specifier: ^1.20.2 - version: 1.20.2(@swc/core@1.3.101)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) - wechaty-grpc: - specifier: ^1.0.1 - version: 1.0.1 + version: 1.20.2(@swc/core@1.7.0)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) devDependencies: - esbuild: - specifier: ^0.19.10 - version: 0.19.10 + '@commitlint/config-conventional': + specifier: ^18.1.0 + version: 18.4.3 + '@types/eslint': + specifier: ^8.56.0 + version: 8.56.0 + '@types/mime': + specifier: ^3.0.4 + version: 3.0.4 + '@types/qrcode-terminal': + specifier: ^0.12.2 + version: 0.12.2 + '@typescript-eslint/eslint-plugin': + specifier: ^6.16.0 + version: 6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': + specifier: ^6.16.0 + version: 6.16.0(eslint@8.57.0)(typescript@5.5.3) + eslint: + specifier: ^8.56.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-plugin-prettier: + specifier: ^5.1.2 + version: 5.2.1(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.3.3) + husky: + specifier: ^8.0.3 + version: 8.0.3 + npm: + specifier: ^10.5.0 + version: 10.5.0 + prettier: + specifier: ^3.1.1 + version: 3.3.3 + tsc-files: + specifier: ^1.1.4 + version: 1.1.4(typescript@5.5.3) + typescript: + specifier: ^5.3.3 + version: 5.5.3 + wechaty-puppet-mock: + specifier: ^1.18.2 + version: 1.18.2(wechaty-puppet@1.20.2) + + packages/windows: + dependencies: + '@wcferry/core': + specifier: ^0.1.6 + version: 0.1.6 + '@wechatbot-webhook/core': + specifier: workspace:^ + version: link:../core + '@wechatbot-webhook/utils': + specifier: workspace:^ + version: link:../utils packages: @@ -148,6 +292,22 @@ packages: conventional-changelog-conventionalcommits: 7.0.2 dev: true + /@commitlint/config-conventional@19.2.2: + resolution: {integrity: sha512-mLXjsxUVLYEGgzbxbxicGPggDuyWNkf25Ht23owXIH+zV2pv1eJuzLK3t1gDY5Gp6pxdE60jZnWUY5cvgL3ufw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 19.0.3 + conventional-changelog-conventionalcommits: 7.0.2 + dev: true + + /@commitlint/types@19.0.3: + resolution: {integrity: sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==} + engines: {node: '>=v18'} + dependencies: + '@types/conventional-commits-parser': 5.0.0 + chalk: 5.3.0 + dev: true + /@esbuild/aix-ppc64@0.19.10: resolution: {integrity: sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q==} engines: {node: '>=12'} @@ -355,13 +515,13 @@ packages: dev: true optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.56.0 + eslint: 8.57.0 eslint-visitor-keys: 3.4.3 dev: true @@ -387,21 +547,29 @@ packages: - supports-color dev: true - /@eslint/js@8.56.0: - resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@grpc/grpc-js@1.11.1: + resolution: {integrity: sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==} + engines: {node: '>=12.10.0'} + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + dev: false + /@grpc/grpc-js@1.9.13: resolution: {integrity: sha512-OEZZu9v9AA+7/tghMDE8o5DAMD5THVnwSqDWuh7PPYO5287rTyqy0xEHT6/e4pbqSrhyLPdQFsam4TwFQVVIIw==} engines: {node: ^8.13.0 || >=10.10.0} dependencies: - '@grpc/proto-loader': 0.7.10 - '@types/node': 20.10.5 + '@grpc/proto-loader': 0.7.13 + '@types/node': 20.14.11 dev: false - /@grpc/proto-loader@0.7.10: - resolution: {integrity: sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==} + /@grpc/proto-loader@0.7.13: + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} engines: {node: '>=6'} hasBin: true dependencies: @@ -416,11 +584,12 @@ packages: engines: {node: '>=18.14.1'} dev: false - /@humanwhocodes/config-array@0.11.13: - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead dependencies: - '@humanwhocodes/object-schema': 2.0.1 + '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: @@ -432,8 +601,9 @@ packages: engines: {node: '>=12.22'} dev: true - /@humanwhocodes/object-schema@2.0.1: - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead dev: true /@jimp/bmp@0.16.13(@jimp/custom@0.16.13): @@ -780,6 +950,24 @@ packages: '@babel/runtime': 7.23.6 regenerator-runtime: 0.13.11 + /@js-sdsl/ordered-map@4.4.2: + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + dev: false + + /@mole-inc/bin-wrapper@8.0.1: + resolution: {integrity: sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bin-check: 4.1.0 + bin-version-check: 5.1.0 + content-disposition: 0.5.4 + ext-name: 5.0.0 + file-type: 17.1.6 + filenamify: 5.1.1 + got: 11.8.6 + os-filter-obj: 2.0.0 + dev: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -801,6 +989,70 @@ packages: fastq: 1.16.0 dev: true + /@oxlint/darwin-arm64@0.2.18: + resolution: {integrity: sha512-DpPId0O8hHh1/PjbtJSMi3DvgK5ol49hB+jiogYGXvBPOF2/8/tG1v7dtbACx4pcorUMu4EHHKHigasnx114cQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@oxlint/darwin-x64@0.2.18: + resolution: {integrity: sha512-hdnPhG/nxF2F8YI9lg3uYMH1ZYxSKiDPu2srey1Xvo2LZChNnvbvxXNS5UYAxG9f/U6VbH4WYfUcqbNZW5Tnzw==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@oxlint/linux-arm64-gnu@0.2.18: + resolution: {integrity: sha512-bhCHYlIn8I5bw5AulQKhYJzanLFoi7mgIkqzfiJibCrGrQh3IKv3h0k8bWHqLEYMmufhGz7yhS96oY3Pe0K1Aw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oxlint/linux-arm64-musl@0.2.18: + resolution: {integrity: sha512-TbZONlryL36xWLUCNRhYZ0m92io6hiN0Ho8ez4T5BoTWwaKwyTdAvpbH7vFDlVDAsp33GB81DXsFSAjPq8PIng==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oxlint/linux-x64-gnu@0.2.18: + resolution: {integrity: sha512-Leupfl0E85BC1t8zB+vqUeeKami+Lo/8HiihLUQAbjz+O8J2WuNaOmt/GURK5jINQhEASBw8dnhNFBMKYe6ZgA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oxlint/linux-x64-musl@0.2.18: + resolution: {integrity: sha512-THG4LZ8KeCy87E4tHqC765acRW0dyXdgzqERi3idjSupCH8juTpk9UfZVcpxcqEicXnEuZDkBQpO8nboyFng3Q==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@oxlint/win32-arm64@0.2.18: + resolution: {integrity: sha512-X/boJsMQiuO2Wfu3eabWefFlb0+O5oSXjcG0gmIE9aySNMy/pVyCno2/RGy+0f4xSjBZXmamCsEoQp/E8NeDQQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@oxlint/win32-x64@0.2.18: + resolution: {integrity: sha512-LmwDhDaZYd20WKmHPeITYNazGVUBFvs7D9+WJ+ecx+bX/6euFp8j+e/4sUzxR5gk6pecqyA6WEld52Gy6W92jg==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@pipeletteio/nop@1.0.5: resolution: {integrity: sha512-ZnSPIltu/KFPTJXRpeoLGgtJZbUjmImx8n1AP6fWQ5RgxWfiF5EcbNGUA6VZglQ/SOQ+vyvhRTYnffwCCTR46w==} engines: {node: '>= 12.0.0'} @@ -853,132 +1105,234 @@ packages: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} dev: false - /@swc/core-darwin-arm64@1.3.101: - resolution: {integrity: sha512-mNFK+uHNPRXSnfTOG34zJOeMl2waM4hF4a2NY7dkMXrPqw9CoJn4MwTXJcyMiSz1/BnNjjTCHF3Yhj0jPxmkzQ==} - engines: {node: '>=10'} + /@rustup/nng-darwin-arm64@0.1.2: + resolution: {integrity: sha512-l12FqjYgdgLsdUj9ckBJCEIJyfB57bSk1Y8fhLQvy9ThYm2Ptn8Rg7bEB6lxpLPFiYwjMZ9qJewaaTzHmF+eqQ==} + engines: {node: '>= 10'} cpu: [arm64] os: [darwin] requiresBuild: true dev: false optional: true - /@swc/core-darwin-x64@1.3.101: - resolution: {integrity: sha512-B085j8XOx73Fg15KsHvzYWG262bRweGr3JooO1aW5ec5pYbz5Ew9VS5JKYS03w2UBSxf2maWdbPz2UFAxg0whw==} - engines: {node: '>=10'} + /@rustup/nng-darwin-universal@0.1.2: + resolution: {integrity: sha512-hWPGZymav3ST8aLX62+VNGEtWxBRrQDVrwjVaqBWd4CmlqztRpsBId2P73ZsQ+ncQQGf1n0SNuJqSHKVMDuccQ==} + engines: {node: '>= 10'} + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@rustup/nng-darwin-x64@0.1.2: + resolution: {integrity: sha512-RvchyP+Ux6OS9NNM38QRaGbcYTH3n9jLwq5w43nR8Uc6uk4eG/5iDA3XRPyhP2DMt18J2Q1ioW/QNglyiUiyXQ==} + engines: {node: '>= 10'} cpu: [x64] os: [darwin] requiresBuild: true dev: false optional: true - /@swc/core-linux-arm-gnueabihf@1.3.101: - resolution: {integrity: sha512-9xLKRb6zSzRGPqdz52Hy5GuB1lSjmLqa0lST6MTFads3apmx4Vgs8Y5NuGhx/h2I8QM4jXdLbpqQlifpzTlSSw==} + /@rustup/nng-linux-x64-gnu@0.1.2: + resolution: {integrity: sha512-HMMYOqhMKj9/Sc0x7E7MRLBvXCq3mAQtj//a1qoqtUaoHXZcUb3WI+D2CS5wBc4a8tPjUZ/m1A9nREiMlQw/zQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rustup/nng-win32-x64-msvc@0.1.2: + resolution: {integrity: sha512-w8AwLM1IOaCX5vgPwkApHJPWSc5rGVFd+gLqRPyYr2S4dkZ9OshgMnuS3jvBH4QtXXv7GBQIFzvTe15d0xgWeA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@rustup/nng@0.1.2: + resolution: {integrity: sha512-cEt3r3r2JJic0G6QIM8qP9UbdYlhAiB36ZIArMzWvdH7wjDqFyi+d+JUas1FMa8eYUtHXZq0J9SbxtCvgGj/kQ==} + engines: {node: '>= 10'} + dependencies: + typescript: 5.5.3 + optionalDependencies: + '@rustup/nng-darwin-arm64': 0.1.2 + '@rustup/nng-darwin-universal': 0.1.2 + '@rustup/nng-darwin-x64': 0.1.2 + '@rustup/nng-linux-x64-gnu': 0.1.2 + '@rustup/nng-win32-x64-msvc': 0.1.2 + dev: false + + /@sindresorhus/is@4.6.0: + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + dev: true + + /@swc/cli@0.3.14(@swc/core@1.7.0): + resolution: {integrity: sha512-0vGqD6FSW67PaZUZABkA+ADKsX7OUY/PwNEz1SbQdCvVk/e4Z36Gwh7mFVBQH9RIsMonTyhV1RHkwkGnEfR3zQ==} + engines: {node: '>= 16.14.0'} + hasBin: true + peerDependencies: + '@swc/core': ^1.2.66 + chokidar: ^3.5.1 + peerDependenciesMeta: + chokidar: + optional: true + dependencies: + '@mole-inc/bin-wrapper': 8.0.1 + '@swc/core': 1.7.0 + '@swc/counter': 0.1.3 + commander: 8.3.0 + fast-glob: 3.3.2 + minimatch: 9.0.3 + piscina: 4.6.1 + semver: 7.5.4 + slash: 3.0.0 + source-map: 0.7.4 + dev: true + + /@swc/core-darwin-arm64@1.7.0: + resolution: {integrity: sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + + /@swc/core-darwin-x64@1.7.0: + resolution: {integrity: sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + + /@swc/core-linux-arm-gnueabihf@1.7.0: + resolution: {integrity: sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==} engines: {node: '>=10'} cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true - /@swc/core-linux-arm64-gnu@1.3.101: - resolution: {integrity: sha512-oE+r1lo7g/vs96Weh2R5l971dt+ZLuhaUX+n3BfDdPxNHfObXgKMjO7E+QS5RbGjv/AwiPCxQmbdCp/xN5ICJA==} + /@swc/core-linux-arm64-gnu@1.7.0: + resolution: {integrity: sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true - /@swc/core-linux-arm64-musl@1.3.101: - resolution: {integrity: sha512-OGjYG3H4BMOTnJWJyBIovCez6KiHF30zMIu4+lGJTCrxRI2fAjGLml3PEXj8tC3FMcud7U2WUn6TdG0/te2k6g==} + /@swc/core-linux-arm64-musl@1.7.0: + resolution: {integrity: sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==} engines: {node: '>=10'} cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true - /@swc/core-linux-x64-gnu@1.3.101: - resolution: {integrity: sha512-/kBMcoF12PRO/lwa8Z7w4YyiKDcXQEiLvM+S3G9EvkoKYGgkkz4Q6PSNhF5rwg/E3+Hq5/9D2R+6nrkF287ihg==} + /@swc/core-linux-x64-gnu@1.7.0: + resolution: {integrity: sha512-SY3HA0K0Dpqt1HIfMLGpwL4hd4UaL2xHP5oZXPlRQPhUDZrbb4PbI3ZJnh66c63eL4ZR8EJ+HRFI0Alx5p69Zw==} engines: {node: '>=10'} cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true - /@swc/core-linux-x64-musl@1.3.101: - resolution: {integrity: sha512-kDN8lm4Eew0u1p+h1l3JzoeGgZPQ05qDE0czngnjmfpsH2sOZxVj1hdiCwS5lArpy7ktaLu5JdRnx70MkUzhXw==} + /@swc/core-linux-x64-musl@1.7.0: + resolution: {integrity: sha512-cEJ2ebtV1v/5Ilb55E05J6F5SrHKQWzUttIhR5Mkayyo+yvPslcpByuFC3D+J7X1ebziTOBpWuMpUdjLfh3SMQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true - /@swc/core-win32-arm64-msvc@1.3.101: - resolution: {integrity: sha512-9Wn8TTLWwJKw63K/S+jjrZb9yoJfJwCE2RV5vPCCWmlMf3U1AXj5XuWOLUX+Rp2sGKau7wZKsvywhheWm+qndQ==} + /@swc/core-win32-arm64-msvc@1.7.0: + resolution: {integrity: sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==} engines: {node: '>=10'} cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true - /@swc/core-win32-ia32-msvc@1.3.101: - resolution: {integrity: sha512-onO5KvICRVlu2xmr4//V2je9O2XgS1SGKpbX206KmmjcJhXN5EYLSxW9qgg+kgV5mip+sKTHTAu7IkzkAtElYA==} + /@swc/core-win32-ia32-msvc@1.7.0: + resolution: {integrity: sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==} engines: {node: '>=10'} cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true - /@swc/core-win32-x64-msvc@1.3.101: - resolution: {integrity: sha512-T3GeJtNQV00YmiVw/88/nxJ/H43CJvFnpvBHCVn17xbahiVUOPOduh3rc9LgAkKiNt/aV8vU3OJR+6PhfMR7UQ==} + /@swc/core-win32-x64-msvc@1.7.0: + resolution: {integrity: sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==} engines: {node: '>=10'} cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true - /@swc/core@1.3.101: - resolution: {integrity: sha512-w5aQ9qYsd/IYmXADAnkXPGDMTqkQalIi+kfFf/MHRKTpaOL7DHjMXwPp/n8hJ0qNjRvchzmPtOqtPBiER50d8A==} + /@swc/core@1.7.0: + resolution: {integrity: sha512-d4vMzH6ICllDwlPuhset2h8gu/USHdbyfJim+2hQEdxC0UONtfpmu38XBgNqRjStrji1Q5M10jfeUZL3cu1i8g==} engines: {node: '>=10'} requiresBuild: true peerDependencies: - '@swc/helpers': ^0.5.0 + '@swc/helpers': '*' peerDependenciesMeta: '@swc/helpers': optional: true dependencies: - '@swc/counter': 0.1.2 - '@swc/types': 0.1.5 + '@swc/counter': 0.1.3 + '@swc/types': 0.1.9 optionalDependencies: - '@swc/core-darwin-arm64': 1.3.101 - '@swc/core-darwin-x64': 1.3.101 - '@swc/core-linux-arm-gnueabihf': 1.3.101 - '@swc/core-linux-arm64-gnu': 1.3.101 - '@swc/core-linux-arm64-musl': 1.3.101 - '@swc/core-linux-x64-gnu': 1.3.101 - '@swc/core-linux-x64-musl': 1.3.101 - '@swc/core-win32-arm64-msvc': 1.3.101 - '@swc/core-win32-ia32-msvc': 1.3.101 - '@swc/core-win32-x64-msvc': 1.3.101 + '@swc/core-darwin-arm64': 1.7.0 + '@swc/core-darwin-x64': 1.7.0 + '@swc/core-linux-arm-gnueabihf': 1.7.0 + '@swc/core-linux-arm64-gnu': 1.7.0 + '@swc/core-linux-arm64-musl': 1.7.0 + '@swc/core-linux-x64-gnu': 1.7.0 + '@swc/core-linux-x64-musl': 1.7.0 + '@swc/core-win32-arm64-msvc': 1.7.0 + '@swc/core-win32-ia32-msvc': 1.7.0 + '@swc/core-win32-x64-msvc': 1.7.0 + + /@swc/counter@0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + /@swc/helpers@0.5.12: + resolution: {integrity: sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==} + dependencies: + tslib: 2.6.2 dev: false - /@swc/counter@0.1.2: - resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} - dev: false + /@swc/types@0.1.9: + resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==} + dependencies: + '@swc/counter': 0.1.3 - /@swc/types@0.1.5: - resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} - dev: false + /@szmarczak/http-timer@4.0.6: + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + dependencies: + defer-to-connect: 2.0.1 + dev: true /@tokenizer/token@0.3.0: resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + /@types/cacheable-request@6.0.3: + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + dependencies: + '@types/http-cache-semantics': 4.0.4 + '@types/keyv': 3.1.4 + '@types/node': 20.14.11 + '@types/responselike': 1.0.3 + dev: true + + /@types/conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} + dependencies: + '@types/node': 20.14.11 + dev: true + /@types/eslint@8.56.0: resolution: {integrity: sha512-FlsN0p4FhuYRjIxpbdXovvHQhtlG05O1GG/RNWvdAxTboR438IOTwmrY/vLA+Xfgg06BTkP045M3vpFwTMv1dg==} dependencies: @@ -990,10 +1344,20 @@ packages: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true + /@types/http-cache-semantics@4.0.4: + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + dev: true + /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} dev: true + /@types/keyv@3.1.4: + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + dependencies: + '@types/node': 20.14.11 + dev: true + /@types/mime@3.0.4: resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} dev: true @@ -1005,21 +1369,26 @@ packages: /@types/node@16.9.1: resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} - /@types/node@20.10.5: - resolution: {integrity: sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==} + /@types/node@20.14.11: + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} dependencies: undici-types: 5.26.5 - dev: false /@types/qrcode-terminal@0.12.2: resolution: {integrity: sha512-v+RcIEJ+Uhd6ygSQ0u5YYY7ZM+la7GgPbs0V/7l/kFs2uO4S8BcIUEMoP7za4DNIqNnUD5npf0A/7kBhrCKG5Q==} dev: true + /@types/responselike@1.0.3: + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + dependencies: + '@types/node': 20.14.11 + dev: true + /@types/semver@7.5.6: resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} dev: true - /@typescript-eslint/eslint-plugin@6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.56.0)(typescript@5.3.3): + /@typescript-eslint/eslint-plugin@6.16.0(@typescript-eslint/parser@6.16.0)(eslint@8.57.0)(typescript@5.5.3): resolution: {integrity: sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -1031,24 +1400,24 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 6.16.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.16.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/scope-manager': 6.16.0 - '@typescript-eslint/type-utils': 6.16.0(eslint@8.56.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.16.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/type-utils': 6.16.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 6.16.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/visitor-keys': 6.16.0 debug: 4.3.4 - eslint: 8.56.0 + eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.0 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.3.3) - typescript: 5.3.3 + ts-api-utils: 1.0.3(typescript@5.5.3) + typescript: 5.5.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@6.16.0(eslint@8.56.0)(typescript@5.3.3): + /@typescript-eslint/parser@6.16.0(eslint@8.57.0)(typescript@5.5.3): resolution: {integrity: sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -1060,11 +1429,11 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.16.0 '@typescript-eslint/types': 6.16.0 - '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.5.3) '@typescript-eslint/visitor-keys': 6.16.0 debug: 4.3.4 - eslint: 8.56.0 - typescript: 5.3.3 + eslint: 8.57.0 + typescript: 5.5.3 transitivePeerDependencies: - supports-color dev: true @@ -1077,7 +1446,7 @@ packages: '@typescript-eslint/visitor-keys': 6.16.0 dev: true - /@typescript-eslint/type-utils@6.16.0(eslint@8.56.0)(typescript@5.3.3): + /@typescript-eslint/type-utils@6.16.0(eslint@8.57.0)(typescript@5.5.3): resolution: {integrity: sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -1087,12 +1456,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.16.0(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.5.3) + '@typescript-eslint/utils': 6.16.0(eslint@8.57.0)(typescript@5.5.3) debug: 4.3.4 - eslint: 8.56.0 - ts-api-utils: 1.0.3(typescript@5.3.3) - typescript: 5.3.3 + eslint: 8.57.0 + ts-api-utils: 1.0.3(typescript@5.5.3) + typescript: 5.5.3 transitivePeerDependencies: - supports-color dev: true @@ -1102,7 +1471,7 @@ packages: engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@6.16.0(typescript@5.3.3): + /@typescript-eslint/typescript-estree@6.16.0(typescript@5.5.3): resolution: {integrity: sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -1118,25 +1487,25 @@ packages: is-glob: 4.0.3 minimatch: 9.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.3.3) - typescript: 5.3.3 + ts-api-utils: 1.0.3(typescript@5.5.3) + typescript: 5.5.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils@6.16.0(eslint@8.56.0)(typescript@5.3.3): + /@typescript-eslint/utils@6.16.0(eslint@8.57.0)(typescript@5.5.3): resolution: {integrity: sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@types/json-schema': 7.0.15 '@types/semver': 7.5.6 '@typescript-eslint/scope-manager': 6.16.0 '@typescript-eslint/types': 6.16.0 - '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.3.3) - eslint: 8.56.0 + '@typescript-eslint/typescript-estree': 6.16.0(typescript@5.5.3) + eslint: 8.57.0 semver: 7.5.4 transitivePeerDependencies: - supports-color @@ -1155,6 +1524,18 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true + /@wcferry/core@0.1.6: + resolution: {integrity: sha512-v2okbcwKi5vvWfSeiHSXJwU5PpRwZqvNy7KXIFZKRdZ4TwFu3Y9iMwS9A6/zq4uQBi0yN4/bFDf55OOqTn9AFg==} + dependencies: + '@rustup/nng': 0.1.2 + '@swc/helpers': 0.5.12 + debug: 4.3.4 + google-protobuf: 3.21.2 + mime: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /abstract-leveldown@7.2.0: resolution: {integrity: sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==} engines: {node: '>=10'} @@ -1202,6 +1583,10 @@ packages: /any-base@1.1.0: resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} + /arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + dev: true + /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true @@ -1263,11 +1648,36 @@ packages: /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - /bcrypt-pbkdf@1.0.2: - resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: false + + /bin-check@4.1.0: + resolution: {integrity: sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==} + engines: {node: '>=4'} + dependencies: + execa: 0.7.0 + executable: 4.1.1 + dev: true + + /bin-version-check@5.1.0: + resolution: {integrity: sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g==} + engines: {node: '>=12'} + dependencies: + bin-version: 6.0.0 + semver: 7.5.4 + semver-truncate: 3.0.0 + dev: true + + /bin-version@6.0.0: + resolution: {integrity: sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw==} + engines: {node: '>=12'} dependencies: - tweetnacl: 0.14.5 - dev: false + execa: 5.1.1 + find-versions: 5.1.0 + dev: true /bl@1.2.3: resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} @@ -1325,6 +1735,24 @@ packages: ieee754: 1.2.1 dev: false + /cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + dev: true + + /cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + dev: true + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -1350,6 +1778,11 @@ packages: ansi-styles: 4.3.0 supports-color: 7.2.0 + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /cheerio@0.22.0: resolution: {integrity: sha512-8/MzidM6G/TgRelkzDG13y3Y9LxBjCb+8yOEZ9+wwq5gVF2w2pV0wmHvjfT0RvuxGyR7UEuK36r+yYMbT4uKgA==} engines: {node: '>= 0.6'} @@ -1396,6 +1829,12 @@ packages: resolution: {integrity: sha512-Ysivmcmx+6+YcWsVK7GS5n+zf4vbF8QtrC5oZYXOB1EbqlraGebsks51WqP2HjPZe40rnZpVI/l9EVXEUmN3Vg==} engines: {node: '>=16', npm: '>=7'} + /clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + dependencies: + mimic-response: 1.0.1 + dev: true + /cmd-ts@0.10.2: resolution: {integrity: sha512-r+2vLOLcGq1sNJ6NnLWdb8bXjpHK6LGDGyX13Mytj+4VGD1ODEPS4BGubJUIQb/0z5tgJ+M1M31w8UrluHXRdA==} dependencies: @@ -1444,6 +1883,11 @@ packages: engines: {node: '>=16'} dev: false + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: true + /compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} dependencies: @@ -1454,6 +1898,13 @@ packages: /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: true + /conventional-changelog-conventionalcommits@7.0.2: resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} engines: {node: '>=16'} @@ -1469,6 +1920,14 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: false + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1532,10 +1991,22 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + dev: true + /deferred-leveldown@7.0.0: resolution: {integrity: sha512-QKN8NtuS3BC6m0B8vAnBls44tX1WXAFATUsJlruyAYbZpysWV3siH6o/i3g9DCHauzodksO60bdj5NazNbjCmg==} engines: {node: '>=10'} @@ -1650,6 +2121,12 @@ packages: level-errors: 3.0.1 dev: false + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + /entities@1.1.2: resolution: {integrity: sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==} dev: false @@ -1699,17 +2176,26 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-prettier@9.1.0(eslint@8.56.0): + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.57.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.56.0 + eslint: 8.57.0 + dev: true + + /eslint-plugin-oxlint@0.2.9: + resolution: {integrity: sha512-K3aILcHVSSbjJ5W7YxdbMLmoB9G4GHdbDXl9qlPwuWF69BVV2e7/Bpy9osLT+bylv8Y+J6WltsqwXL/Z7sxMgA==} dev: true - /eslint-plugin-prettier@5.1.2(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1): - resolution: {integrity: sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==} + /eslint-plugin-prettier@5.2.1(@types/eslint@8.56.0)(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.3.3): + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1723,11 +2209,11 @@ packages: optional: true dependencies: '@types/eslint': 8.56.0 - eslint: 8.56.0 - eslint-config-prettier: 9.1.0(eslint@8.56.0) - prettier: 3.1.1 + eslint: 8.57.0 + eslint-config-prettier: 9.1.0(eslint@8.57.0) + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 dev: true /eslint-scope@7.2.2: @@ -1743,16 +2229,16 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.56.0: - resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -1823,9 +2309,59 @@ packages: engines: {node: '>=0.10.0'} dev: true + /execa@0.7.0: + resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} + engines: {node: '>=4'} + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + dev: true + + /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 + + /executable@4.1.1: + resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} + engines: {node: '>=4'} + dependencies: + pify: 2.3.0 + dev: true + /exif-parser@0.1.12: resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==} + /ext-list@2.2.2: + resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} + engines: {node: '>=0.10.0'} + dependencies: + mime-db: 1.52.0 + dev: true + + /ext-name@5.0.0: + resolution: {integrity: sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==} + engines: {node: '>=4'} + dependencies: + ext-list: 2.2.2 + sort-keys-length: 1.0.1 + dev: true + /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: false @@ -1917,6 +2453,38 @@ packages: strtok3: 6.3.0 token-types: 4.2.1 + /file-type@17.1.6: + resolution: {integrity: sha512-hlDw5Ev+9e883s0pwUsuuYNu4tD7GgpUnOvykjv1Gya0ZIjuKumthDRua90VUn6/nlRKAjcxLUnHNTIUWwWIiw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + readable-web-to-node-stream: 3.0.2 + strtok3: 7.0.0 + token-types: 5.0.1 + dev: true + + /file-type@19.0.0: + resolution: {integrity: sha512-s7cxa7/leUWLiXO78DVVfBVse+milos9FitauDLG1pI7lNaJ2+5lzPnr2N24ym+84HVwJL6hVuGfgVE+ALvU8Q==} + engines: {node: '>=18'} + dependencies: + readable-web-to-node-stream: 3.0.2 + strtok3: 7.0.0 + token-types: 5.0.1 + dev: false + + /filename-reserved-regex@3.0.0: + resolution: {integrity: sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /filenamify@5.1.1: + resolution: {integrity: sha512-M45CbrJLGACfrPOkrTp3j2EcO9OBkKUYME0eiqOCa7i2poaklU0jhlIaMlr8ijLorT0uLAzrn3qXOp5684CkfA==} + engines: {node: '>=12.20'} + dependencies: + filename-reserved-regex: 3.0.0 + strip-outer: 2.0.0 + trim-repeated: 2.0.0 + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1939,6 +2507,13 @@ packages: path-exists: 4.0.0 dev: true + /find-versions@5.1.0: + resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==} + engines: {node: '>=12'} + dependencies: + semver-regex: 4.0.5 + dev: true + /flash-store@1.3.5: resolution: {integrity: sha512-4PAwmGw701dfizqd9vzH1D/U7G4jgorz3ZT1KRK1jU5daKQu8KRXfL18Upd3jfwgIkEtbmMDbtb2Gql9am6S9g==} engines: {node: '>=14'} @@ -2034,6 +2609,23 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false + /get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + dev: true + + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + /getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: @@ -2099,6 +2691,23 @@ packages: resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} dev: false + /got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + dev: true + /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} dev: false @@ -2141,6 +2750,10 @@ packages: readable-stream: 3.6.2 dev: false + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + /http-signature@1.2.0: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} engines: {node: '>=0.8', npm: '>=1.3.7'} @@ -2150,15 +2763,29 @@ packages: sshpk: 1.18.0 dev: false + /http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + /husky@8.0.3: resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} engines: {node: '>=14'} hasBin: true dev: true - /i@0.3.7: - resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==} - engines: {node: '>=0.4'} + /husky@9.1.1: + resolution: {integrity: sha512-fCqlqLXcBnXa/TJXmT93/A36tJsjdJkibQ1MuIiFyCCYUlpYpIaj2mv1w+3KR6Rzu1IC3slFTje5f6DUp2A2rg==} + engines: {node: '>=18'} + hasBin: true dev: true /ieee754@1.2.1: @@ -2235,6 +2862,21 @@ packages: engines: {node: '>=8'} dev: true + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + /is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: false @@ -2530,6 +3172,18 @@ packages: resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} dev: false + /lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + dev: true + + /lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: true + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -2551,6 +3205,10 @@ packages: async-map-like: 1.0.2 brolog: 1.14.2 + /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'} @@ -2567,7 +3225,6 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: false /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} @@ -2586,6 +3243,21 @@ packages: engines: {node: '>=10.0.0'} hasBin: true + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + dev: true + + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true + /min-document@2.19.0: resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} dependencies: @@ -2627,6 +3299,22 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /nice-napi@1.0.2: + resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} + os: ['!win32'] + requiresBuild: true + dependencies: + node-addon-api: 3.2.1 + node-gyp-build: 4.7.1 + dev: true + optional: true + + /node-addon-api@3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + requiresBuild: true + dev: true + optional: true + /node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -2643,12 +3331,30 @@ packages: /node-gyp-build@4.7.1: resolution: {integrity: sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==} hasBin: true - dev: false /nop@1.0.0: resolution: {integrity: sha512-XdkOuXGx0DTwlqb0DWTcDqelgU/F3YyZ+PTRaecpDVpkYskcnh3OeUYKfvjcRQ2D1diTIGxi/a3eHVjW5yPupQ==} dev: false + /normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + dev: true + + /npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + /npm@10.5.0: resolution: {integrity: sha512-Ejxwvfh9YnWVU2yA5FzoYLTW52vxHCz+MHrOFg9Cc8IFgF/6f5AGPAvb5WTay5DIUP1NIfN3VBZ0cLlGO0Ys+A==} engines: {node: ^18.17.0 || >=20.5.0} @@ -2744,6 +3450,13 @@ packages: dependencies: wrappy: 1.0.2 + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + /open-graph@0.2.6: resolution: {integrity: sha512-L4lTD3fcPkNclAZFukhr8ZAF8+kBqXJqUb/HNSdIoxVMTdaqSwSroYdBiFb56yPdr4GrltECiL5lRHYIJbpY/A==} dependencies: @@ -2763,6 +3476,38 @@ packages: type-check: 0.4.0 dev: true + /os-filter-obj@2.0.0: + resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} + engines: {node: '>=4'} + dependencies: + arch: 2.2.0 + dev: true + + /oxlint@0.2.18: + resolution: {integrity: sha512-/6tR2hm9vN/cjJarItkDPeSWDqPbkQ6pVDzePR2La5cNA+kn1Gt7k0ZHxcpTuhZOI/lhRD2z4C0v/m9kja/0cQ==} + engines: {node: '>=14.*'} + hasBin: true + optionalDependencies: + '@oxlint/darwin-arm64': 0.2.18 + '@oxlint/darwin-x64': 0.2.18 + '@oxlint/linux-arm64-gnu': 0.2.18 + '@oxlint/linux-arm64-musl': 0.2.18 + '@oxlint/linux-x64-gnu': 0.2.18 + '@oxlint/linux-x64-musl': 0.2.18 + '@oxlint/win32-arm64': 0.2.18 + '@oxlint/win32-x64': 0.2.18 + dev: true + + /p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + dev: true + + /p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + dev: true + /p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -2826,6 +3571,11 @@ packages: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} + /path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: true + /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -2839,6 +3589,10 @@ packages: resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} engines: {node: '>=8'} + /peek-readable@5.0.0: + resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} + engines: {node: '>=14.16'} + /performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} dev: false @@ -2851,6 +3605,17 @@ packages: engines: {node: '>=8.6'} dev: true + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /piscina@4.6.1: + resolution: {integrity: sha512-z30AwWGtQE+Apr+2WBZensP2lIvwoaMcOPkQlIEmSGMJNUvaYACylPYrQM6wSdUNJlnDVMSpLv7xTMJqlVshOA==} + optionalDependencies: + nice-napi: 1.0.2 + dev: true + /pixelmatch@4.0.2: resolution: {integrity: sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==} hasBin: true @@ -2877,8 +3642,8 @@ packages: fast-diff: 1.3.0 dev: true - /prettier@3.1.1: - resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + /prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true dev: true @@ -2914,7 +3679,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.10.5 + '@types/node': 20.14.11 long: 5.2.3 dev: false @@ -2922,10 +3687,21 @@ packages: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: true + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: false + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2953,6 +3729,11 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + /readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} dependencies: @@ -3035,11 +3816,21 @@ packages: /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + /resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: true + /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} dev: true + /responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + dependencies: + lowercase-keys: 2.0.0 + dev: true + /retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -3099,6 +3890,18 @@ packages: /sax@1.3.0: resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + /semver-regex@4.0.5: + resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} + engines: {node: '>=12'} + dev: true + + /semver-truncate@3.0.0: + resolution: {integrity: sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==} + engines: {node: '>=12'} + dependencies: + semver: 7.5.4 + dev: true + /semver@7.5.4: resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} engines: {node: '>=10'} @@ -3109,21 +3912,56 @@ packages: /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + /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'} dev: true + /sort-keys-length@1.0.1: + resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} + engines: {node: '>=0.10.0'} + dependencies: + sort-keys: 1.1.2 + dev: true + + /sort-keys@1.1.2: + resolution: {integrity: sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==} + engines: {node: '>=0.10.0'} + dependencies: + is-plain-obj: 1.1.0 + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + /sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} @@ -3211,11 +4049,26 @@ packages: dependencies: ansi-regex: 5.0.1 + /strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: true + /strip-outer@2.0.0: + resolution: {integrity: sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + /strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} dev: false @@ -3231,14 +4084,21 @@ packages: '@tokenizer/token': 0.3.0 peek-readable: 4.1.0 + /strtok3@7.0.0: + resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==} + engines: {node: '>=14.16'} + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 5.0.0 + /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 - /synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + /synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} dependencies: '@pkgr/core': 0.1.0 @@ -3269,6 +4129,13 @@ packages: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + /token-types@5.0.1: + resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} + engines: {node: '>=14.16'} + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + /tough-cookie@2.5.0: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} @@ -3277,22 +4144,29 @@ packages: punycode: 2.3.1 dev: false - /ts-api-utils@1.0.3(typescript@5.3.3): + /trim-repeated@2.0.0: + resolution: {integrity: sha512-QUHBFTJGdOwmp0tbOG505xAgOp/YliZP/6UgafFXYZ26WT1bvQmSMJUvkeVSASuJJHbqsFbynTvkd5W8RBTipg==} + engines: {node: '>=12'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /ts-api-utils@1.0.3(typescript@5.5.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.3.3 + typescript: 5.5.3 dev: true - /tsc-files@1.1.4(typescript@5.3.3): + /tsc-files@1.1.4(typescript@5.5.3): resolution: {integrity: sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==} hasBin: true peerDependencies: typescript: '>=3' dependencies: - typescript: 5.3.3 + typescript: 5.5.3 dev: true /tslib@2.1.0: @@ -3333,15 +4207,13 @@ packages: resolution: {integrity: sha512-bna6Yi1pRznoo6Bz1cE6btB/Yy8Xywytyfrzu/wc+NFW3ZF0I+2iCGImhBsoYYCOWuICtRO4yHcnDlzgo1AdNg==} engines: {node: '>= 4'} - /typescript@5.3.3: - resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + /typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true - dev: true /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: false /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} @@ -3396,7 +4268,7 @@ packages: engines: {node: '>= 8'} dev: false - /wechat4u@0.7.14(patch_hash=mmirz2kximouh53sl2jk76abxe): + /wechat4u@0.7.14: resolution: {integrity: sha512-BDEHSL1drGX8f9QdclOiTQcL6EtaIQWZ0MVsTeFkxGM1xVikqqlK7WcJp2IOpK0RczG4lFvXwDmOgzyZnA1waQ==} dependencies: axios: 1.6.2(debug@2.6.9) @@ -3408,7 +4280,6 @@ packages: transitivePeerDependencies: - supports-color dev: false - patched: true /wechaty-grpc@1.0.1: resolution: {integrity: sha512-a7mvz5DOz6qsbW1HI3mTv3HROJzxaP5gGJk1GVa5KjwVta4iSd7XzN8NNKrr8RoVjEtsPTXiZpW5HqhZjSfH2Q==} @@ -3423,7 +4294,7 @@ packages: resolution: {integrity: sha512-oOXU62oDf8/LIg8wAqSoZogZ+NFSGIAJvYuTewR6x5Ia4iWjbfrlwy7NHjWGBLkKM2EpnxgOAjyxhAb1iMxTJg==} engines: {node: '>=16', npm: '>=7'} dependencies: - '@grpc/grpc-js': 1.9.13 + '@grpc/grpc-js': 1.11.1 google-protobuf: 3.21.2 stronger-typed-streams: 0.2.0 dev: false @@ -3438,7 +4309,7 @@ packages: faker: 5.5.3 file-box: 1.4.15 typed-emitter: 1.5.0-from-event - wechaty-puppet: 1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1) + wechaty-puppet: 1.20.2(rxjs@7.8.1) dev: true /wechaty-puppet-service@1.19.9(brolog@1.14.2)(redux@4.2.1)(wechaty-puppet@1.20.2)(wechaty@1.20.2): @@ -3458,7 +4329,7 @@ packages: stronger-typed-streams: 0.2.0 uuid: 8.3.2 wechaty-grpc: 1.5.2 - wechaty-puppet: 1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1) + wechaty-puppet: 1.20.2(rxjs@7.8.1) wechaty-redux: 1.20.2(brolog@1.14.2)(wechaty-puppet@1.20.2)(wechaty@1.20.2) wechaty-token: 1.1.2 transitivePeerDependencies: @@ -3468,7 +4339,7 @@ packages: - wechaty dev: false - /wechaty-puppet-wechat4u@1.14.13(patch_hash=nq4vns7vah46g6vxziyzqg5jey)(@swc/core@1.3.101)(wechaty-puppet@1.20.2): + /wechaty-puppet-wechat4u@1.14.13(@swc/core@1.7.0)(wechaty-puppet@1.20.2): resolution: {integrity: sha512-aLm0Hp0VrmQB4POoFTzBKRQMmtdv4gMQUSUocfqL0JWAutsVwzWkm4Utbt8rnN7Jg2qxT5ooH4hkWDUlUKnKyw==} engines: {node: '>=16', npm: '>=7'} peerDependencies: @@ -3476,18 +4347,17 @@ packages: wechaty-puppet: ^1.20.2 dependencies: '@alloc/quick-lru': 5.2.0 - '@swc/core': 1.3.101 + '@swc/core': 1.7.0 fast-xml-parser: 3.21.1 promise-retry: 2.0.1 - wechat4u: 0.7.14(patch_hash=mmirz2kximouh53sl2jk76abxe) - wechaty-puppet: 1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1) + wechat4u: 0.7.14 + wechaty-puppet: 1.20.2(rxjs@7.8.1) xml2js: 0.4.23 transitivePeerDependencies: - supports-color dev: false - patched: true - /wechaty-puppet@1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1): + /wechaty-puppet@1.20.2(rxjs@7.8.1): resolution: {integrity: sha512-IXcnUc9A3hGIT+9CEF8KLkbdld+AQPfVlWLeUXmmSvm3I9NbSbVfU43FZvKMjvLCexvN5DZq2+JZdASESohI5Q==} engines: {node: '>=16', npm: '>=7'} dependencies: @@ -3505,7 +4375,6 @@ packages: watchdog: 0.9.2 transitivePeerDependencies: - rxjs - patched: true /wechaty-redux@1.20.2(brolog@1.14.2)(wechaty-puppet@1.20.2)(wechaty@1.20.2): resolution: {integrity: sha512-XAhSmdCDa1yaAMRYPiYqbX3BL0T1Owyf+77HxLY+450AFAyjM4xak5ZLStLWIA3zEktgzn6KwEthtu7mmZ7n3g==} @@ -3524,8 +4393,8 @@ packages: typesafe-actions: 5.1.0 utility-types: 3.10.0 uuid: 8.3.2 - wechaty: 1.20.2(@swc/core@1.3.101)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) - wechaty-puppet: 1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1) + wechaty: 1.20.2(@swc/core@1.7.0)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1) + wechaty-puppet: 1.20.2(rxjs@7.8.1) transitivePeerDependencies: - brolog dev: false @@ -3543,7 +4412,7 @@ packages: - supports-color dev: false - /wechaty@1.20.2(@swc/core@1.3.101)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1): + /wechaty@1.20.2(@swc/core@1.7.0)(brolog@1.14.2)(redux@4.2.1)(rxjs@7.8.1): resolution: {integrity: sha512-bIZ8m2lOya4SKnxVunbMGemE8JyZdnXhnLnfXtBAZV997ef6uqP4pJxuwiJnV0qbXGyIE+F3B2b8yjQOZh43lQ==} engines: {node: '>=16', npm: '>=7'} hasBin: true @@ -3563,9 +4432,9 @@ packages: rx-queue: 1.0.5 state-switch: 1.6.3(brolog@1.14.2)(gerror@1.0.16)(rxjs@7.8.1) uuid: 8.3.2 - wechaty-puppet: 1.20.2(patch_hash=wwr5xvwazgbyb26ud6vwdruala)(rxjs@7.8.1) + wechaty-puppet: 1.20.2(rxjs@7.8.1) wechaty-puppet-service: 1.19.9(brolog@1.14.2)(redux@4.2.1)(wechaty-puppet@1.20.2)(wechaty@1.20.2) - wechaty-puppet-wechat4u: 1.14.13(patch_hash=nq4vns7vah46g6vxziyzqg5jey)(@swc/core@1.3.101)(wechaty-puppet@1.20.2) + wechaty-puppet-wechat4u: 1.14.13(@swc/core@1.7.0)(wechaty-puppet@1.20.2) wechaty-token: 1.1.2 ws: 8.15.1 transitivePeerDependencies: @@ -3581,6 +4450,13 @@ packages: /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + /which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3658,6 +4534,10 @@ packages: engines: {node: '>=10'} dev: false + /yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: true + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} diff --git a/scripts/tsc-lint.sh b/scripts/tsc-lint.sh deleted file mode 100755 index f7d9536..0000000 --- a/scripts/tsc-lint.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -npx tsc --noEmit \ No newline at end of file diff --git a/src/middleware/index.js b/src/middleware/index.js deleted file mode 100644 index 3069928..0000000 --- a/src/middleware/index.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - ...require('./verifyToken.js'), - ...require('./loginCheck.js') -} diff --git a/src/middleware/loginCheck.js b/src/middleware/loginCheck.js deleted file mode 100644 index f812d9b..0000000 --- a/src/middleware/loginCheck.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * middleware of login Check - * @param {import('hono').Context} c - * @param {import('hono').Next} next - */ -module.exports.loginCheck = async (c, next) => { - if (!c.bot.isLoggedIn) { - c.status(401) - return c.json({ - success: false, - message: 'you must login first' - }) - } - - await next() -} diff --git a/src/route/index.js b/src/route/index.js deleted file mode 100644 index 5efd50d..0000000 --- a/src/route/index.js +++ /dev/null @@ -1,25 +0,0 @@ -const Middleware = require('../middleware/index') -/** - * 注册路由 - * @param {Object} param - * @param {import('hono').Hono} param.app - * @param {import('wechaty').Wechaty} param.bot - */ -module.exports = function registerRoute({ app, bot }) { - /** - * @param {import('hono').Context} ctx - * @param {import('hono').Next} next - */ - const attachData = (ctx, next) => { - ctx.bot = bot - return next() - } - // 挂载wecahty实例到全局路由 - app.use('*', attachData) - // 全局鉴权 - app.use(Middleware.verifyToken) - - require('./msg')({ app, bot }) - require('./login')({ app, bot }) - require('./resouces')({ app, bot }) -} diff --git a/tsconfig.json b/tsconfig.json index b0a7050..a57e4b0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,17 @@ { "include": ["**/*"], - "exclude": ["packages/**/*"], + "exclude": ["node_modules", "**/*.spec.ts","dist/**/*"], "compilerOptions": { - "baseUrl": ".", + "outDir": "dist/esm", "paths": { - "@src/*": ["src/*"] + "@/*": ["./packages/*"] }, - "rootDir": "./", + "lib": [ + "esnext", + ], "target": "ESNext", - "module": "CommonJS", - "moduleResolution": "node", - "allowJs": true, - "checkJs": true, + "module": "ESNext", + "moduleResolution": "node", "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, diff --git a/typings/hono.d.ts b/typings/hono.d.ts deleted file mode 100644 index d56077a..0000000 --- a/typings/hono.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { WechatyInterface } from 'wechaty/impls' - -declare module 'hono' { - interface Context { - bot: WechatyInterface - } -}