├── .gitignore ├── FUNC.md ├── LICENSE ├── README.CN.md ├── README.md ├── app.js ├── docker ├── Dockerfile ├── app.js ├── fetchsse.js └── package.json ├── images ├── 20230307122958.png ├── 20230307123053.png ├── 20230307123511.png ├── 20230307123910.png ├── 20230307123957.png ├── 20230307124127.png ├── 202303071241272.png ├── 20230307124853.png ├── 20230307131517.png └── 20230307203401.png ├── package.json ├── stream-moderation.mov ├── stream-moderation.mp4 ├── yarn-error.log └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | RoboFile.php -------------------------------------------------------------------------------- /FUNC.md: -------------------------------------------------------------------------------- 1 | # 此Proxy可以部署到腾讯云函数 2 | 3 | > ⚠️ 由于腾讯云自身规则,虽然代码本身支持SSE,但部署为云函数后可能无法正常工作 4 | 5 | ① 进入[云函数创建面板](https://console.cloud.tencent.com/scf/list-create?rid=5&ns=default&createType=empty),选择日本/新加坡(有issue反馈因为unsupported location被封号,虽然无法完全确定原因,但建议不再使用~~中国香港~~)、web函数、NodeJS 16。 6 | 7 | ![](images/20230307122958.png) 8 | 9 | ② 在函数代码处点击`app.js`将本项目 [app.js](/app.js) 的代码粘贴进去。 10 | 11 | ![](images/20230307123053.png) 12 | 13 | 其他不用改,点创建。 14 | 15 | ③ 创建完成后,点击「函数管理」→「函数代码」。等编辑器把函数代码加载完成后 CloudStudio → 终端 → 新终端,打开一个新终端。 16 | 17 | ![](images/20230307123511.png) 18 | 19 | ④ 在出现的终端中粘贴以下代码 20 | 21 | ```bash 22 | cd src && yarn add body-parser@1.20.2 cross-fetch@3.1.5 eventsource-parser@0.1.0 express@4.18.2 multer@1.4.5-lts.1 tencentcloud-sdk-nodejs@4.0.567 cors@2.8.5 23 | ``` 24 | 25 | ![](images/20230307123910.png) 26 | 27 | ⑤ 点编辑器右上角的「部署」,等待部署完成。 28 | 29 | ![](images/20230307123957.png) 30 | 31 | ⑥ 下拉或者进入「触发管理」可以看到云函数的访问地址。 32 | 33 | ![](images/202303071241272.png) 34 | 35 | 36 | ⑦ 调整函数执行超时时间,默认的3s会经常超时,建议调整为30s;同时添加环境变量 `TIMEOUT`(单位为毫秒,如30000) 37 | ![](images/20230307203401.png) 38 | 39 | ⑧ 如果你想绑定自己的域名,需要在「触发管理」中开启「标准API网关」,按腾讯云教程进行配置。 40 | 41 | ## Proxy的使用 42 | 43 | 使用时将 `https://api.openai.com/` 替换为该路径即可,如 `https://api.openai.com/v1/chat/completions` 替换为 `https://xxxxx.apigw.tencentcs.com/release/v1/chat/completions` 44 | 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Easy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.CN.md: -------------------------------------------------------------------------------- 1 | > ⚠️ 这是代理的服务器端,不是客户端。需要部署到可以联通 openai api 的网络环境后访问。 2 | 3 | ## 特色功能 4 | 5 | 1. 支持SSE流式输出 6 | 1. 内置文本安全审核(需要配置腾讯云KEY) 7 | 8 | ## NodeJS部署 9 | 10 | 你可以把 ./app.js 部署到所有支持 nodejs 14+ 的环境,比如云函数和边缘计算平台。 11 | 12 | 1. 复制 app.js 和 package.json 到目录 13 | 1. yarn install 安装依赖 14 | 1. node app.js 启动服务 15 | 16 | ## Docker部署 17 | 18 | ``` 19 | docker run -p 9000:9000 easychen/ai.level06.com:latest 20 | ``` 21 | 22 | Proxy地址为 http://${IP}:9000 23 | 24 | ### 可用环境变量 25 | 26 | 1. PORT: 服务端口 27 | 1. PROXY_KEY: 代理访问KEY,用于限制访问 28 | 1. TIMEOUT:请求超时时间,默认30秒 29 | 1. TENCENT_CLOUD_SID:腾讯云secret_id 30 | 1. TENCENT_CLOUD_SKEY:腾讯云secret_key 31 | 1. TENCENT_CLOUD_AP:腾讯云区域(如:ap-singapore 新加坡) 32 | 33 | ## 接口使用方法 34 | 35 | 1. 将原来项目中 openai 的请求地址( 比如 https://api.openai.com )中的域名变更为本 proxy 的域名/IP(注意带上端口号) 36 | 1. 如果设置了PROXY_KEY,在 openai 的 key 后加上 `:`,如果没有设置,则不需修改 37 | 1. moderation:true 开启审核,false 关闭审核 38 | 1. moderation_level:high 中断所有审核结果不为 Pass 的句子,low 只中断审核结果为 Block 的句子 39 | 40 | ## 说明 41 | 42 | 1. 只支持 GET 和 POST 方法的接口,不支持文件相关接口 43 | 1. ~~当前不支持SSE,因此需要关掉 stream 相关的选项~~ 已支持 44 | 45 | ## 客户端使用实例 46 | 47 | 以 `https://www.npmjs.com/package/chatgpt` 为例 48 | 49 | ```js 50 | chatApi= new gpt.ChatGPTAPI({ 51 | apiKey: 'sk.....:', 52 | apiBaseUrl: "http://localhost:9001/v1", // 替换代理域名/IP 53 | }); 54 | 55 | ``` 56 | 57 | ## 致谢 58 | 59 | 1. SSE参考了[chatgpt-api项目相关代码](https://github.com/transitive-bullshit/chatgpt-api/blob/main/src/fetch-sse.ts) 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # openai-api-proxy 2 | 3 | 可以部署到docker和云函数的OpenAI API代理 4 | Simple proxy for OpenAi api via a one-line docker command 5 | 6 | 🌳 如果你懒得自己搭建,那么可以试试[国内可以访问、可以微信充值的第三方OpenAI API服务:API2D.com](https://api2d.com/r/186008),支持Chat酱、OpenCat、NextWeb、VSCode插件。 7 | 8 | 9 | - [腾讯云函数部署教程](FUNC.md) 🔥 腾讯云函数从4月25日起已经全地域支持SSE,推荐使用 10 | - [简体中文使用说明](README.CN.md) 11 | - [《如何快速开发一个OpenAI/GPT应用:国内开发者笔记》](https://github.com/easychen/openai-gpt-dev-notes-for-cn-developer) 12 | 13 | 🎉 已经支持SSE,可以实时返回内容 14 | 15 | 以下英文由GPT翻译。The following English was translated by GPT. 16 | 17 | ⚠️ This is the server-side of the proxy, not the client-side. It needs to be deployed to a network environment that can access the openai api. 18 | 19 | ## Features 20 | 21 | 1. Supports SSE streaming output 22 | 2. Built-in text moderation (requires Tencent Cloud KEY configuration) 23 | 3. 💪 SSE streaming output supports text moderation, that's how powerful it is. 24 | 25 | ## NodeJS Deployment 26 | 27 | You can deploy ./app.js to any environment that supports nodejs 14+, such as cloud functions and edge computing platforms. 28 | 29 | 1. Copy app.js and package.json to the directory 30 | 2. Install dependencies with yarn install 31 | 3. Start the service with node app.js 32 | 33 | ## Docker Deployment 34 | 35 | ``` 36 | docker run -p 9000:9000 easychen/ai.level06.com:latest 37 | ``` 38 | 39 | The proxy address is http://${IP}:9000 40 | 41 | ### Available Environment Variables 42 | 43 | 1. PORT: Service port 44 | 2. PROXY_KEY: Proxy access key, used to restrict access 45 | 3. TIMEOUT: Request timeout, default 30 seconds 46 | 4. TENCENT_CLOUD_SID: Tencent Cloud secret_id 47 | 5. TENCENT_CLOUD_SKEY: Tencent Cloud secret_key 48 | 6. TENCENT_CLOUD_AP: Tencent Cloud region (e.g. ap-singapore Singapore) 49 | 50 | ## API Usage 51 | 52 | 1. Change the domain/IP (with port number) of the openai request address in the original project (e.g. https://api.openai.com) to the domain/IP of this proxy. 53 | 2. If PROXY_KEY is set, add `:` after the openai key. If not set, no modification is required. 54 | 3. moderation: true enables moderation, false disables moderation 55 | 4. moderation_level: high interrupts all sentences whose moderation result is not Pass, low only interrupts sentences whose moderation result is Block. 56 | 57 | ## Notes 58 | 59 | 1. Only supports GET and POST methods, not file-related interfaces. 60 | 2. ~~SSE is not currently supported, so stream-related options need to be turned off~~ Now supported. 61 | 62 | ## Client-side Usage Example 63 | 64 | Using `https://www.npmjs.com/package/chatgpt` as an example: 65 | 66 | ```js 67 | chatApi= new gpt.ChatGPTAPI({ 68 | apiKey: 'sk.....:', 69 | apiBaseUrl: "http://localhost:9001/v1", // Replace with proxy domain/IP 70 | }); 71 | 72 | ``` 73 | 74 | ## Acknowledgements 75 | 76 | 1. SSE reference to [chatgpt-api project related code](https://github.com/transitive-bullshit/chatgpt-api/blob/main/src/fetch-sse.ts) 77 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const fetch = require('cross-fetch') 3 | const app = express() 4 | var multer = require('multer'); 5 | var forms = multer({limits: { fieldSize: 10*1024*1024 }}); 6 | app.use(forms.array()); 7 | const cors = require('cors'); 8 | app.use(cors()); 9 | 10 | const bodyParser = require('body-parser') 11 | app.use(bodyParser.json({limit : '50mb' })); 12 | app.use(bodyParser.urlencoded({ extended: true })); 13 | 14 | const tencentcloud = require("tencentcloud-sdk-nodejs"); 15 | const TmsClient = tencentcloud.tms.v20201229.Client; 16 | const clientConfig = { 17 | credential: { 18 | secretId: process.env.TENCENT_CLOUD_SID, 19 | secretKey: process.env.TENCENT_CLOUD_SKEY, 20 | }, 21 | region: process.env.TENCENT_CLOUD_AP||"ap-singapore", 22 | profile: { 23 | httpProfile: { 24 | endpoint: "tms.tencentcloudapi.com", 25 | }, 26 | }, 27 | }; 28 | const mdClient = process.env.TENCENT_CLOUD_SID && process.env.TENCENT_CLOUD_SKEY ? new TmsClient(clientConfig) : false; 29 | 30 | const controller = new AbortController(); 31 | 32 | app.all(`*`, async (req, res) => { 33 | 34 | if(req.originalUrl) req.url = req.originalUrl; 35 | let url = `https://api.openai.com${req.url}`; 36 | // 从 header 中取得 Authorization': 'Bearer 后的 token 37 | const token = req.headers.authorization?.split(' ')[1]; 38 | if( !token ) return res.status(403).send('Forbidden'); 39 | 40 | const openai_key = process.env.OPENAI_KEY||token.split(':')[0]; 41 | if( !openai_key ) return res.status(403).send('Forbidden'); 42 | if( openai_key.startsWith("fk") ) url = url.replaceAll( "api.openai.com", "openai.api2d.net" ); 43 | 44 | const proxy_key = token.split(':')[1]||""; 45 | console.log("PROXY_KEY:" + proxy_key); 46 | const validProxyKeys = process.env.PROXY_KEY ? process.env.PROXY_KEY.split(',') : []; 47 | // 检查传入的proxy_key是否在有效的PROXY_KEY列表中 48 | if (process.env.PROXY_KEY && !validProxyKeys.includes(proxy_key)){ 49 | console.log("拒绝访问, PROXY_KEY无效"); 50 | return res.status(403).send('Forbidden'); 51 | } 52 | 53 | // console.log( req ); 54 | const { moderation, moderation_level, ...restBody } = req.body; 55 | let sentence = ""; 56 | // 建立一个句子缓冲区 57 | let sentence_buffer = []; 58 | let processing = false; 59 | let processing_stop = false; 60 | 61 | async function process_buffer(res) 62 | { 63 | if( processing_stop ) 64 | { 65 | console.log("processing_stop",processing_stop); 66 | return false; 67 | } 68 | 69 | console.log("句子缓冲区" + new Date(), sentence_buffer); 70 | 71 | // 处理句子缓冲区 72 | if( processing ) 73 | { 74 | // 有正在处理的,1秒钟后重试 75 | console.log("有正在处理的,1秒钟后重试"); 76 | setTimeout( () => process_buffer(res), 1000 ); 77 | return false; 78 | } 79 | 80 | processing = true; 81 | const sentence = sentence_buffer.shift(); 82 | console.log("取出句子", sentence); 83 | if( sentence ) 84 | { 85 | if( sentence === '[DONE]' ) 86 | { 87 | console.log("[DONE]", "结束输出"); 88 | res.write("data: "+sentence+"\n\n" ); 89 | processing = false; 90 | res.end(); 91 | return true; 92 | }else 93 | { 94 | // 开始对句子进行审核 95 | let data_array = JSON.parse(sentence); 96 | console.log("解析句子数据为array",data_array); 97 | 98 | const sentence_content = data_array.choices[0]?.delta?.content; 99 | console.log("sentence_content", sentence_content); 100 | if( sentence_content ) 101 | { 102 | const params = {"Content": Buffer.from(sentence_content).toString('base64')}; 103 | const md_result = await mdClient.TextModeration(params); 104 | // console.log("审核结果", md_result); 105 | let md_check = moderation_level == 'high' ? md_result.Suggestion != 'Pass' : md_result.Suggestion == 'Block'; 106 | if( md_check ) 107 | { 108 | // 终止输出 109 | console.log("审核不通过", sentence_content, md_result); 110 | let forbidden_array = data_array; 111 | forbidden_array.choices[0].delta.content = "这个话题不适合讨论,换个话题吧。"; 112 | res.write("data: "+JSON.stringify(forbidden_array)+"\n\n" ); 113 | res.write("data: [DONE]\n\n" ); 114 | res.end(); 115 | controller.abort(); 116 | processing = false; 117 | processing_stop = true; 118 | return false; 119 | }else 120 | { 121 | console.log("审核通过", sentence_content); 122 | res.write("data: "+sentence+"\n\n" ); 123 | processing = false; 124 | console.log("processing",processing); 125 | return true; 126 | } 127 | } 128 | 129 | } 130 | }else 131 | { 132 | // console.log("句子缓冲区为空"); 133 | } 134 | 135 | processing = false; 136 | } 137 | 138 | 139 | const options = { 140 | method: req.method, 141 | timeout: process.env.TIMEOUT||30000, 142 | signal: controller.signal, 143 | headers: { 144 | 'Content-Type': 'application/json; charset=utf-8', 145 | 'Authorization': 'Bearer '+ openai_key, 146 | }, 147 | onMessage: async (data) => { 148 | // console.log(data); 149 | if( data === '[DONE]' ) 150 | { 151 | sentence_buffer.push(data); 152 | await process_buffer(res); 153 | }else 154 | { 155 | if( moderation && mdClient ) 156 | { 157 | try { 158 | let data_array = JSON.parse(data); 159 | const char = data_array.choices[0]?.delta?.content; 160 | if( char ) sentence += char; 161 | // console.log("sentence",sentence ); 162 | if( char == '。' || char == '?' || char == '!' || char == "\n" ) 163 | { 164 | // 将 sentence 送审 165 | console.log("遇到句号,将句子放入缓冲区", sentence); 166 | data_array.choices[0].delta.content = sentence; 167 | sentence = ""; 168 | sentence_buffer.push(JSON.stringify(data_array)); 169 | await process_buffer(res); 170 | } 171 | } catch (error) { 172 | // 因为开头已经处理的了 [DONE] 的情况,这里应该不会出现无法解析json的情况 173 | console.log( "error", error ); 174 | } 175 | }else 176 | { 177 | // 如果没有文本审核参数或者设置,直接输出 178 | res.write("data: "+data+"\n\n" ); 179 | } 180 | } 181 | } 182 | }; 183 | 184 | if( req.method.toLocaleLowerCase() === 'post' && req.body ) options.body = JSON.stringify(restBody); 185 | // console.log({url, options}); 186 | 187 | try { 188 | 189 | // 如果是 chat completion 和 text completion,使用 SSE 190 | if( (req.url.startsWith('/v1/completions') || req.url.startsWith('/v1/chat/completions')) && req.body.stream ) { 191 | console.log("使用 SSE"); 192 | const response = await myFetch(url, options); 193 | if( response.ok ) 194 | { 195 | // write header 196 | res.writeHead(200, { 197 | 'Content-Type': 'text/event-stream', 198 | 'Cache-Control': 'no-cache', 199 | 'Connection': 'keep-alive', 200 | }); 201 | const { createParser } = await import("eventsource-parser"); 202 | const parser = createParser((event) => { 203 | // console.log(event); 204 | if (event.type === "event") { 205 | options.onMessage(event.data); 206 | } 207 | }); 208 | if (!response.body.getReader) { 209 | const body = response.body; 210 | if (!body.on || !body.read) { 211 | throw new error('unsupported "fetch" implementation'); 212 | } 213 | body.on("readable", () => { 214 | let chunk; 215 | while (null !== (chunk = body.read())) { 216 | // console.log(chunk.toString()); 217 | parser.feed(chunk.toString()); 218 | } 219 | }); 220 | } else { 221 | for await (const chunk of streamAsyncIterable(response.body)) { 222 | const str = new TextDecoder().decode(chunk); 223 | parser.feed(str); 224 | } 225 | } 226 | }else 227 | { 228 | const body = await response.text(); 229 | res.status(response.status).send(body); 230 | } 231 | 232 | }else 233 | { 234 | console.log("使用 fetch"); 235 | const response = await myFetch(url, options); 236 | // 检查返回的内容类型 237 | const contentType = response.headers.get("Content-Type"); 238 | // 根据内容类型处理返回的数据 239 | if (contentType.includes("application/json")) { 240 | // 处理JSON数据 241 | const data = await response.json(); 242 | // 审核结果 243 | if (moderation && mdClient) { 244 | const params = {"Content": Buffer.from(data.choices[0].message.content).toString('base64')}; 245 | const md_result = await mdClient.TextModeration(params); 246 | console.log("审核结果", md_result); 247 | let md_check = moderation_level == 'high' ? md_result.Suggestion != 'Pass' : md_result.Suggestion == 'Block'; 248 | if (md_check) { 249 | // 终止输出 250 | console.log("审核不通过", data.choices[0].message.content, md_result); 251 | data.choices[0].message.content = "这个话题不适合讨论,换个话题吧。"; 252 | } else { 253 | console.log("审核通过", data.choices[0].message.content); 254 | } 255 | } 256 | // 返回JSON数据 257 | res.json(data); 258 | } else if (contentType.includes("audio")) { 259 | // 处理Audio数据 260 | const audioBlob = await response.blob(); 261 | // 需要设置正确的Content-Type 262 | res.setHeader('Content-Type', 'audio/mpeg'); 263 | // 发送音频数据给客户端 264 | const audioStream = audioBlob.stream(); 265 | audioStream.pipe(res); 266 | } else { 267 | // 处理其他类型的返回或抛出错误 268 | console.log("返回了未知类型的数据"); 269 | res.status(500).send("返回了未知类型的数据"); 270 | } 271 | } 272 | 273 | 274 | } catch (error) { 275 | console.error(error); 276 | res.status(500).json({"error":error.toString()}); 277 | } 278 | }) 279 | 280 | async function* streamAsyncIterable(stream) { 281 | const reader = stream.getReader(); 282 | try { 283 | while (true) { 284 | const { done, value } = await reader.read(); 285 | if (done) { 286 | return; 287 | } 288 | yield value; 289 | } 290 | } finally { 291 | reader.releaseLock(); 292 | } 293 | } 294 | 295 | async function myFetch(url, options) { 296 | const {timeout, ...fetchOptions} = options; 297 | const controller = new AbortController(); 298 | const timeoutId = setTimeout(() => controller.abort(), timeout||30000) 299 | const res = await fetch(url, {...fetchOptions,signal:controller.signal}); 300 | clearTimeout(timeoutId); 301 | return res; 302 | } 303 | 304 | // Error handler 305 | app.use(function(err, req, res, next) { 306 | console.error(err) 307 | res.status(500).send('Internal Serverless Error') 308 | }) 309 | 310 | const port = process.env.PORT||9000; 311 | app.listen(port, () => { 312 | console.log(`Server start on http://localhost:${port}`); 313 | }) -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=$TARGETPLATFORM node:18-alpine3.15 2 | EXPOSE 9000 3 | RUN mkdir -p /data/api 4 | COPY app.js /data/api/app.js 5 | COPY fetchsse.js /data/api/fetchsse.js 6 | COPY package.json /data/api/package.json 7 | RUN npm install --prefix /data/api 8 | CMD ["node", "/data/api/app.js"] -------------------------------------------------------------------------------- /docker/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const fetch = require('cross-fetch') 3 | const app = express() 4 | var multer = require('multer'); 5 | var forms = multer({limits: { fieldSize: 10*1024*1024 }}); 6 | app.use(forms.array()); 7 | const cors = require('cors'); 8 | app.use(cors()); 9 | 10 | const bodyParser = require('body-parser') 11 | app.use(bodyParser.json({limit : '50mb' })); 12 | app.use(bodyParser.urlencoded({ extended: true })); 13 | 14 | const tencentcloud = require("tencentcloud-sdk-nodejs"); 15 | const TmsClient = tencentcloud.tms.v20201229.Client; 16 | const clientConfig = { 17 | credential: { 18 | secretId: process.env.TENCENT_CLOUD_SID, 19 | secretKey: process.env.TENCENT_CLOUD_SKEY, 20 | }, 21 | region: process.env.TENCENT_CLOUD_AP||"ap-singapore", 22 | profile: { 23 | httpProfile: { 24 | endpoint: "tms.tencentcloudapi.com", 25 | }, 26 | }, 27 | }; 28 | const mdClient = process.env.TENCENT_CLOUD_SID && process.env.TENCENT_CLOUD_SKEY ? new TmsClient(clientConfig) : false; 29 | 30 | const controller = new AbortController(); 31 | 32 | app.all(`*`, async (req, res) => { 33 | 34 | if(req.originalUrl) req.url = req.originalUrl; 35 | let url = `https://api.openai.com${req.url}`; 36 | // 从 header 中取得 Authorization': 'Bearer 后的 token 37 | const token = req.headers.authorization?.split(' ')[1]; 38 | if( !token ) return res.status(403).send('Forbidden'); 39 | 40 | const openai_key = process.env.OPENAI_KEY||token.split(':')[0]; 41 | if( !openai_key ) return res.status(403).send('Forbidden'); 42 | if( openai_key.startsWith("fk") ) url = url.replaceAll( "api.openai.com", "openai.api2d.net" ); 43 | 44 | const proxy_key = token.split(':')[1]||""; 45 | if( process.env.PROXY_KEY && proxy_key !== process.env.PROXY_KEY ) 46 | return res.status(403).send('Forbidden'); 47 | 48 | // console.log( req ); 49 | const { moderation, moderation_level, ...restBody } = req.body; 50 | let sentence = ""; 51 | // 建立一个句子缓冲区 52 | let sentence_buffer = []; 53 | let processing = false; 54 | let processing_stop = false; 55 | 56 | async function process_buffer(res) 57 | { 58 | if( processing_stop ) 59 | { 60 | console.log("processing_stop",processing_stop); 61 | return false; 62 | } 63 | 64 | console.log("句子缓冲区" + new Date(), sentence_buffer); 65 | 66 | // 处理句子缓冲区 67 | if( processing ) 68 | { 69 | // 有正在处理的,1秒钟后重试 70 | console.log("有正在处理的,1秒钟后重试"); 71 | setTimeout( () => process_buffer(res), 1000 ); 72 | return false; 73 | } 74 | 75 | processing = true; 76 | const sentence = sentence_buffer.shift(); 77 | console.log("取出句子", sentence); 78 | if( sentence ) 79 | { 80 | if( sentence === '[DONE]' ) 81 | { 82 | console.log("[DONE]", "结束输出"); 83 | res.write("data: "+sentence+"\n\n" ); 84 | processing = false; 85 | res.end(); 86 | return true; 87 | }else 88 | { 89 | // 开始对句子进行审核 90 | let data_array = JSON.parse(sentence); 91 | console.log("解析句子数据为array",data_array); 92 | 93 | const sentence_content = data_array.choices[0]?.delta?.content; 94 | console.log("sentence_content", sentence_content); 95 | if( sentence_content ) 96 | { 97 | const params = {"Content": Buffer.from(sentence_content).toString('base64')}; 98 | const md_result = await mdClient.TextModeration(params); 99 | // console.log("审核结果", md_result); 100 | let md_check = moderation_level == 'high' ? md_result.Suggestion != 'Pass' : md_result.Suggestion == 'Block'; 101 | if( md_check ) 102 | { 103 | // 终止输出 104 | console.log("审核不通过", sentence_content, md_result); 105 | let forbidden_array = data_array; 106 | forbidden_array.choices[0].delta.content = "这个话题不适合讨论,换个话题吧。"; 107 | res.write("data: "+JSON.stringify(forbidden_array)+"\n\n" ); 108 | res.write("data: [DONE]\n\n" ); 109 | res.end(); 110 | controller.abort(); 111 | processing = false; 112 | processing_stop = true; 113 | return false; 114 | }else 115 | { 116 | console.log("审核通过", sentence_content); 117 | res.write("data: "+sentence+"\n\n" ); 118 | processing = false; 119 | console.log("processing",processing); 120 | return true; 121 | } 122 | } 123 | 124 | } 125 | }else 126 | { 127 | // console.log("句子缓冲区为空"); 128 | } 129 | 130 | processing = false; 131 | } 132 | 133 | 134 | const options = { 135 | method: req.method, 136 | timeout: process.env.TIMEOUT||30000, 137 | signal: controller.signal, 138 | headers: { 139 | 'Content-Type': 'application/json; charset=utf-8', 140 | 'Authorization': 'Bearer '+ openai_key, 141 | }, 142 | onMessage: async (data) => { 143 | // console.log(data); 144 | if( data === '[DONE]' ) 145 | { 146 | sentence_buffer.push(data); 147 | await process_buffer(res); 148 | }else 149 | { 150 | if( moderation && mdClient ) 151 | { 152 | try { 153 | let data_array = JSON.parse(data); 154 | const char = data_array.choices[0]?.delta?.content; 155 | if( char ) sentence += char; 156 | // console.log("sentence",sentence ); 157 | if( char == '。' || char == '?' || char == '!' || char == "\n" ) 158 | { 159 | // 将 sentence 送审 160 | console.log("遇到句号,将句子放入缓冲区", sentence); 161 | data_array.choices[0].delta.content = sentence; 162 | sentence = ""; 163 | sentence_buffer.push(JSON.stringify(data_array)); 164 | await process_buffer(res); 165 | } 166 | } catch (error) { 167 | // 因为开头已经处理的了 [DONE] 的情况,这里应该不会出现无法解析json的情况 168 | console.log( "error", error ); 169 | } 170 | }else 171 | { 172 | // 如果没有文本审核参数或者设置,直接输出 173 | res.write("data: "+data+"\n\n" ); 174 | } 175 | } 176 | } 177 | }; 178 | 179 | if( req.method.toLocaleLowerCase() === 'post' && req.body ) options.body = JSON.stringify(restBody); 180 | // console.log({url, options}); 181 | 182 | try { 183 | 184 | // 如果是 chat completion 和 text completion,使用 SSE 185 | if( (req.url.startsWith('/v1/completions') || req.url.startsWith('/v1/chat/completions')) && req.body.stream ) { 186 | console.log("使用 SSE"); 187 | const response = await myFetch(url, options); 188 | if( response.ok ) 189 | { 190 | // write header 191 | res.writeHead(200, { 192 | 'Content-Type': 'text/event-stream', 193 | 'Cache-Control': 'no-cache', 194 | 'Connection': 'keep-alive', 195 | }); 196 | const { createParser } = await import("eventsource-parser"); 197 | const parser = createParser((event) => { 198 | // console.log(event); 199 | if (event.type === "event") { 200 | options.onMessage(event.data); 201 | } 202 | }); 203 | if (!response.body.getReader) { 204 | const body = response.body; 205 | if (!body.on || !body.read) { 206 | throw new error('unsupported "fetch" implementation'); 207 | } 208 | body.on("readable", () => { 209 | let chunk; 210 | while (null !== (chunk = body.read())) { 211 | // console.log(chunk.toString()); 212 | parser.feed(chunk.toString()); 213 | } 214 | }); 215 | } else { 216 | for await (const chunk of streamAsyncIterable(response.body)) { 217 | const str = new TextDecoder().decode(chunk); 218 | parser.feed(str); 219 | } 220 | } 221 | }else 222 | { 223 | const body = await response.text(); 224 | res.status(response.status).send(body); 225 | } 226 | 227 | }else 228 | { 229 | console.log("使用 fetch"); 230 | const response = await myFetch(url, options); 231 | // console.log(response); 232 | const data = await response.json(); 233 | // 审核结果 234 | if( moderation && mdClient ) 235 | { 236 | const params = {"Content": Buffer.from(data.choices[0].message.content).toString('base64')}; 237 | const md_result = await mdClient.TextModeration(params); 238 | // console.log("审核结果", md_result); 239 | let md_check = moderation_level == 'high' ? md_result.Suggestion != 'Pass' : md_result.Suggestion == 'Block'; 240 | if( md_check ) 241 | { 242 | // 终止输出 243 | console.log("审核不通过", data.choices[0].message.content, md_result); 244 | data.choices[0].message.content = "这个话题不适合讨论,换个话题吧。"; 245 | }else 246 | { 247 | console.log("审核通过", data.choices[0].message.content); 248 | } 249 | } 250 | 251 | res.json(data); 252 | } 253 | 254 | 255 | } catch (error) { 256 | console.error(error); 257 | res.status(500).json({"error":error.toString()}); 258 | } 259 | }) 260 | 261 | async function* streamAsyncIterable(stream) { 262 | const reader = stream.getReader(); 263 | try { 264 | while (true) { 265 | const { done, value } = await reader.read(); 266 | if (done) { 267 | return; 268 | } 269 | yield value; 270 | } 271 | } finally { 272 | reader.releaseLock(); 273 | } 274 | } 275 | 276 | async function myFetch(url, options) { 277 | const {timeout, ...fetchOptions} = options; 278 | const controller = new AbortController(); 279 | const timeoutId = setTimeout(() => controller.abort(), timeout||30000) 280 | const res = await fetch(url, {...fetchOptions,signal:controller.signal}); 281 | clearTimeout(timeoutId); 282 | return res; 283 | } 284 | 285 | // Error handler 286 | app.use(function(err, req, res, next) { 287 | console.error(err) 288 | res.status(500).send('Internal Serverless Error') 289 | }) 290 | 291 | const port = process.env.PORT||9000; 292 | app.listen(port, () => { 293 | console.log(`Server start on http://localhost:${port}`); 294 | }) -------------------------------------------------------------------------------- /docker/fetchsse.js: -------------------------------------------------------------------------------- 1 | async function* streamAsyncIterable(stream) { 2 | const reader = stream.getReader(); 3 | try { 4 | while (true) { 5 | const { done, value } = await reader.read(); 6 | if (done) { 7 | return; 8 | } 9 | yield value; 10 | } 11 | } finally { 12 | reader.releaseLock(); 13 | } 14 | } 15 | 16 | // add timeout to fetchSSE 17 | async function fetchSSE(url, options, fetch2 = fetch) { 18 | const { createParser } = await import("eventsource-parser"); 19 | const { onMessage, timeout , ...fetchOptions } = options; 20 | const controller = new AbortController(); 21 | const timeoutId = setTimeout(() => controller.abort(), timeout||30000) 22 | 23 | const res = await fetch2(url, {...fetchOptions,signal:controller.signal}); 24 | clearTimeout(timeoutId); 25 | 26 | if (!res.ok) { 27 | let reason; 28 | try { 29 | reason = await res.text(); 30 | } catch (err) { 31 | reason = res.statusText; 32 | } 33 | const msg = `ChatGPT error ${res.status}: ${reason}`; 34 | const error = new ChatGPTError(msg, { cause: res }); 35 | error.statusCode = res.status; 36 | error.statusText = res.statusText; 37 | error.context = { url, options }; 38 | throw error; 39 | } 40 | const parser = createParser((event) => { 41 | if (event.type === "event") { 42 | onMessage(event.data); 43 | } 44 | }); 45 | if (!res.body.getReader) { 46 | const body = res.body; 47 | if (!body.on || !body.read) { 48 | throw new ChatGPTError('unsupported "fetch" implementation'); 49 | } 50 | body.on("readable", () => { 51 | let chunk; 52 | while (null !== (chunk = body.read())) { 53 | parser.feed(chunk.toString()); 54 | } 55 | }); 56 | } else { 57 | for await (const chunk of streamAsyncIterable(res.body)) { 58 | const str = new TextDecoder().decode(chunk); 59 | parser.feed(str); 60 | } 61 | } 62 | } 63 | 64 | module.exports = fetchSSE; 65 | -------------------------------------------------------------------------------- /docker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "body-parser": "^1.20.2", 4 | "cors": "^2.8.5", 5 | "cross-fetch": "^3.1.5", 6 | "eventsource-parser": "^0.1.0", 7 | "express": "^4.18.2", 8 | "multer": "^1.4.5-lts.1", 9 | "tencentcloud-sdk-nodejs": "^4.0.567" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /images/20230307122958.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307122958.png -------------------------------------------------------------------------------- /images/20230307123053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307123053.png -------------------------------------------------------------------------------- /images/20230307123511.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307123511.png -------------------------------------------------------------------------------- /images/20230307123910.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307123910.png -------------------------------------------------------------------------------- /images/20230307123957.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307123957.png -------------------------------------------------------------------------------- /images/20230307124127.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307124127.png -------------------------------------------------------------------------------- /images/202303071241272.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/202303071241272.png -------------------------------------------------------------------------------- /images/20230307124853.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307124853.png -------------------------------------------------------------------------------- /images/20230307131517.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307131517.png -------------------------------------------------------------------------------- /images/20230307203401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/images/20230307203401.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "body-parser": "^1.20.2", 4 | "cors": "^2.8.5", 5 | "cross-fetch": "^3.1.5", 6 | "eventsource-parser": "^0.1.0", 7 | "express": "^4.18.2", 8 | "multer": "^1.4.5-lts.1", 9 | "tencentcloud-sdk-nodejs": "^4.0.567" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /stream-moderation.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/stream-moderation.mov -------------------------------------------------------------------------------- /stream-moderation.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/openai-api-proxy/a3dbe8de07aede5d0f6381fca60524276d55201f/stream-moderation.mp4 -------------------------------------------------------------------------------- /yarn-error.log: -------------------------------------------------------------------------------- 1 | Arguments: 2 | /usr/local/bin/node /Users/easy/.yarn/bin/yarn.js add eventsource-parser 3 | 4 | PATH: 5 | /Users/easy/.yarn/bin:/Users/easy/.config/yarn/global/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/podman/bin:/Users/easy/.yarn/bin:/Users/easy/.config/yarn/global/node_modules/.bin:/Users/easy/.cargo/bin 6 | 7 | Yarn version: 8 | 1.22.19 9 | 10 | Node version: 11 | 18.14.0 12 | 13 | Platform: 14 | darwin x64 15 | 16 | Trace: 17 | Error: Client network socket disconnected before secure TLS connection was established 18 | at connResetException (node:internal/errors:717:14) 19 | at TLSSocket.onConnectEnd (node:_tls_wrap:1595:19) 20 | at TLSSocket.emit (node:events:525:35) 21 | at endReadableNT (node:internal/streams/readable:1359:12) 22 | at process.processTicksAndRejections (node:internal/process/task_queues:82:21) 23 | 24 | npm manifest: 25 | { 26 | "dependencies": { 27 | "body-parser": "^1.20.2", 28 | "cross-fetch": "^3.1.5", 29 | "express": "^4.18.2", 30 | "multer": "^1.4.5-lts.1" 31 | } 32 | } 33 | 34 | yarn manifest: 35 | No manifest 36 | 37 | Lockfile: 38 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 39 | # yarn lockfile v1 40 | 41 | 42 | accepts@~1.3.8: 43 | version "1.3.8" 44 | resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 45 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 46 | dependencies: 47 | mime-types "~2.1.34" 48 | negotiator "0.6.3" 49 | 50 | append-field@^1.0.0: 51 | version "1.0.0" 52 | resolved "https://registry.npmmirror.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" 53 | integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== 54 | 55 | array-flatten@1.1.1: 56 | version "1.1.1" 57 | resolved "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 58 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 59 | 60 | body-parser@1.20.1: 61 | version "1.20.1" 62 | resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" 63 | integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== 64 | dependencies: 65 | bytes "3.1.2" 66 | content-type "~1.0.4" 67 | debug "2.6.9" 68 | depd "2.0.0" 69 | destroy "1.2.0" 70 | http-errors "2.0.0" 71 | iconv-lite "0.4.24" 72 | on-finished "2.4.1" 73 | qs "6.11.0" 74 | raw-body "2.5.1" 75 | type-is "~1.6.18" 76 | unpipe "1.0.0" 77 | 78 | body-parser@^1.20.2: 79 | version "1.20.2" 80 | resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" 81 | integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== 82 | dependencies: 83 | bytes "3.1.2" 84 | content-type "~1.0.5" 85 | debug "2.6.9" 86 | depd "2.0.0" 87 | destroy "1.2.0" 88 | http-errors "2.0.0" 89 | iconv-lite "0.4.24" 90 | on-finished "2.4.1" 91 | qs "6.11.0" 92 | raw-body "2.5.2" 93 | type-is "~1.6.18" 94 | unpipe "1.0.0" 95 | 96 | buffer-from@^1.0.0: 97 | version "1.1.2" 98 | resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 99 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 100 | 101 | busboy@^1.0.0: 102 | version "1.6.0" 103 | resolved "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" 104 | integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== 105 | dependencies: 106 | streamsearch "^1.1.0" 107 | 108 | bytes@3.1.2: 109 | version "3.1.2" 110 | resolved "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 111 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 112 | 113 | call-bind@^1.0.0: 114 | version "1.0.2" 115 | resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 116 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 117 | dependencies: 118 | function-bind "^1.1.1" 119 | get-intrinsic "^1.0.2" 120 | 121 | concat-stream@^1.5.2: 122 | version "1.6.2" 123 | resolved "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 124 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 125 | dependencies: 126 | buffer-from "^1.0.0" 127 | inherits "^2.0.3" 128 | readable-stream "^2.2.2" 129 | typedarray "^0.0.6" 130 | 131 | content-disposition@0.5.4: 132 | version "0.5.4" 133 | resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 134 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 135 | dependencies: 136 | safe-buffer "5.2.1" 137 | 138 | content-type@~1.0.4, content-type@~1.0.5: 139 | version "1.0.5" 140 | resolved "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 141 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 142 | 143 | cookie-signature@1.0.6: 144 | version "1.0.6" 145 | resolved "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 146 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 147 | 148 | cookie@0.5.0: 149 | version "0.5.0" 150 | resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 151 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 152 | 153 | core-util-is@~1.0.0: 154 | version "1.0.3" 155 | resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 156 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 157 | 158 | cross-fetch@^3.1.5: 159 | version "3.1.5" 160 | resolved "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" 161 | integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== 162 | dependencies: 163 | node-fetch "2.6.7" 164 | 165 | debug@2.6.9: 166 | version "2.6.9" 167 | resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 168 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 169 | dependencies: 170 | ms "2.0.0" 171 | 172 | depd@2.0.0: 173 | version "2.0.0" 174 | resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 175 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 176 | 177 | destroy@1.2.0: 178 | version "1.2.0" 179 | resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 180 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 181 | 182 | ee-first@1.1.1: 183 | version "1.1.1" 184 | resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 185 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 186 | 187 | encodeurl@~1.0.2: 188 | version "1.0.2" 189 | resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 190 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 191 | 192 | escape-html@~1.0.3: 193 | version "1.0.3" 194 | resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 195 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 196 | 197 | etag@~1.8.1: 198 | version "1.8.1" 199 | resolved "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 200 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 201 | 202 | express@^4.18.2: 203 | version "4.18.2" 204 | resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" 205 | integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== 206 | dependencies: 207 | accepts "~1.3.8" 208 | array-flatten "1.1.1" 209 | body-parser "1.20.1" 210 | content-disposition "0.5.4" 211 | content-type "~1.0.4" 212 | cookie "0.5.0" 213 | cookie-signature "1.0.6" 214 | debug "2.6.9" 215 | depd "2.0.0" 216 | encodeurl "~1.0.2" 217 | escape-html "~1.0.3" 218 | etag "~1.8.1" 219 | finalhandler "1.2.0" 220 | fresh "0.5.2" 221 | http-errors "2.0.0" 222 | merge-descriptors "1.0.1" 223 | methods "~1.1.2" 224 | on-finished "2.4.1" 225 | parseurl "~1.3.3" 226 | path-to-regexp "0.1.7" 227 | proxy-addr "~2.0.7" 228 | qs "6.11.0" 229 | range-parser "~1.2.1" 230 | safe-buffer "5.2.1" 231 | send "0.18.0" 232 | serve-static "1.15.0" 233 | setprototypeof "1.2.0" 234 | statuses "2.0.1" 235 | type-is "~1.6.18" 236 | utils-merge "1.0.1" 237 | vary "~1.1.2" 238 | 239 | finalhandler@1.2.0: 240 | version "1.2.0" 241 | resolved "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 242 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 243 | dependencies: 244 | debug "2.6.9" 245 | encodeurl "~1.0.2" 246 | escape-html "~1.0.3" 247 | on-finished "2.4.1" 248 | parseurl "~1.3.3" 249 | statuses "2.0.1" 250 | unpipe "~1.0.0" 251 | 252 | forwarded@0.2.0: 253 | version "0.2.0" 254 | resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 255 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 256 | 257 | fresh@0.5.2: 258 | version "0.5.2" 259 | resolved "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 260 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 261 | 262 | function-bind@^1.1.1: 263 | version "1.1.1" 264 | resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 265 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 266 | 267 | get-intrinsic@^1.0.2: 268 | version "1.2.0" 269 | resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" 270 | integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== 271 | dependencies: 272 | function-bind "^1.1.1" 273 | has "^1.0.3" 274 | has-symbols "^1.0.3" 275 | 276 | has-symbols@^1.0.3: 277 | version "1.0.3" 278 | resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 279 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 280 | 281 | has@^1.0.3: 282 | version "1.0.3" 283 | resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 284 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 285 | dependencies: 286 | function-bind "^1.1.1" 287 | 288 | http-errors@2.0.0: 289 | version "2.0.0" 290 | resolved "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 291 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 292 | dependencies: 293 | depd "2.0.0" 294 | inherits "2.0.4" 295 | setprototypeof "1.2.0" 296 | statuses "2.0.1" 297 | toidentifier "1.0.1" 298 | 299 | iconv-lite@0.4.24: 300 | version "0.4.24" 301 | resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 302 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 303 | dependencies: 304 | safer-buffer ">= 2.1.2 < 3" 305 | 306 | inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: 307 | version "2.0.4" 308 | resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 309 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 310 | 311 | ipaddr.js@1.9.1: 312 | version "1.9.1" 313 | resolved "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 314 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 315 | 316 | isarray@~1.0.0: 317 | version "1.0.0" 318 | resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 319 | integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== 320 | 321 | media-typer@0.3.0: 322 | version "0.3.0" 323 | resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 324 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 325 | 326 | merge-descriptors@1.0.1: 327 | version "1.0.1" 328 | resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 329 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 330 | 331 | methods@~1.1.2: 332 | version "1.1.2" 333 | resolved "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 334 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 335 | 336 | mime-db@1.52.0: 337 | version "1.52.0" 338 | resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 339 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 340 | 341 | mime-types@~2.1.24, mime-types@~2.1.34: 342 | version "2.1.35" 343 | resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 344 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 345 | dependencies: 346 | mime-db "1.52.0" 347 | 348 | mime@1.6.0: 349 | version "1.6.0" 350 | resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 351 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 352 | 353 | minimist@^1.2.6: 354 | version "1.2.8" 355 | resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 356 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 357 | 358 | mkdirp@^0.5.4: 359 | version "0.5.6" 360 | resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 361 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 362 | dependencies: 363 | minimist "^1.2.6" 364 | 365 | ms@2.0.0: 366 | version "2.0.0" 367 | resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 368 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 369 | 370 | ms@2.1.3: 371 | version "2.1.3" 372 | resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 373 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 374 | 375 | multer@^1.4.5-lts.1: 376 | version "1.4.5-lts.1" 377 | resolved "https://registry.npmmirror.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac" 378 | integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ== 379 | dependencies: 380 | append-field "^1.0.0" 381 | busboy "^1.0.0" 382 | concat-stream "^1.5.2" 383 | mkdirp "^0.5.4" 384 | object-assign "^4.1.1" 385 | type-is "^1.6.4" 386 | xtend "^4.0.0" 387 | 388 | negotiator@0.6.3: 389 | version "0.6.3" 390 | resolved "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 391 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 392 | 393 | node-fetch@2.6.7: 394 | version "2.6.7" 395 | resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 396 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 397 | dependencies: 398 | whatwg-url "^5.0.0" 399 | 400 | object-assign@^4.1.1: 401 | version "4.1.1" 402 | resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 403 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 404 | 405 | object-inspect@^1.9.0: 406 | version "1.12.3" 407 | resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" 408 | integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== 409 | 410 | on-finished@2.4.1: 411 | version "2.4.1" 412 | resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 413 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 414 | dependencies: 415 | ee-first "1.1.1" 416 | 417 | parseurl@~1.3.3: 418 | version "1.3.3" 419 | resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 420 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 421 | 422 | path-to-regexp@0.1.7: 423 | version "0.1.7" 424 | resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 425 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 426 | 427 | process-nextick-args@~2.0.0: 428 | version "2.0.1" 429 | resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 430 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 431 | 432 | proxy-addr@~2.0.7: 433 | version "2.0.7" 434 | resolved "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 435 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 436 | dependencies: 437 | forwarded "0.2.0" 438 | ipaddr.js "1.9.1" 439 | 440 | qs@6.11.0: 441 | version "6.11.0" 442 | resolved "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 443 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 444 | dependencies: 445 | side-channel "^1.0.4" 446 | 447 | range-parser@~1.2.1: 448 | version "1.2.1" 449 | resolved "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 450 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 451 | 452 | raw-body@2.5.1: 453 | version "2.5.1" 454 | resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 455 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 456 | dependencies: 457 | bytes "3.1.2" 458 | http-errors "2.0.0" 459 | iconv-lite "0.4.24" 460 | unpipe "1.0.0" 461 | 462 | raw-body@2.5.2: 463 | version "2.5.2" 464 | resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" 465 | integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== 466 | dependencies: 467 | bytes "3.1.2" 468 | http-errors "2.0.0" 469 | iconv-lite "0.4.24" 470 | unpipe "1.0.0" 471 | 472 | readable-stream@^2.2.2: 473 | version "2.3.8" 474 | resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" 475 | integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== 476 | dependencies: 477 | core-util-is "~1.0.0" 478 | inherits "~2.0.3" 479 | isarray "~1.0.0" 480 | process-nextick-args "~2.0.0" 481 | safe-buffer "~5.1.1" 482 | string_decoder "~1.1.1" 483 | util-deprecate "~1.0.1" 484 | 485 | safe-buffer@5.2.1: 486 | version "5.2.1" 487 | resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 488 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 489 | 490 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 491 | version "5.1.2" 492 | resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 493 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 494 | 495 | "safer-buffer@>= 2.1.2 < 3": 496 | version "2.1.2" 497 | resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 498 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 499 | 500 | send@0.18.0: 501 | version "0.18.0" 502 | resolved "https://registry.npmmirror.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 503 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 504 | dependencies: 505 | debug "2.6.9" 506 | depd "2.0.0" 507 | destroy "1.2.0" 508 | encodeurl "~1.0.2" 509 | escape-html "~1.0.3" 510 | etag "~1.8.1" 511 | fresh "0.5.2" 512 | http-errors "2.0.0" 513 | mime "1.6.0" 514 | ms "2.1.3" 515 | on-finished "2.4.1" 516 | range-parser "~1.2.1" 517 | statuses "2.0.1" 518 | 519 | serve-static@1.15.0: 520 | version "1.15.0" 521 | resolved "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 522 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 523 | dependencies: 524 | encodeurl "~1.0.2" 525 | escape-html "~1.0.3" 526 | parseurl "~1.3.3" 527 | send "0.18.0" 528 | 529 | setprototypeof@1.2.0: 530 | version "1.2.0" 531 | resolved "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 532 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 533 | 534 | side-channel@^1.0.4: 535 | version "1.0.4" 536 | resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 537 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 538 | dependencies: 539 | call-bind "^1.0.0" 540 | get-intrinsic "^1.0.2" 541 | object-inspect "^1.9.0" 542 | 543 | statuses@2.0.1: 544 | version "2.0.1" 545 | resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 546 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 547 | 548 | streamsearch@^1.1.0: 549 | version "1.1.0" 550 | resolved "https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" 551 | integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== 552 | 553 | string_decoder@~1.1.1: 554 | version "1.1.1" 555 | resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 556 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 557 | dependencies: 558 | safe-buffer "~5.1.0" 559 | 560 | toidentifier@1.0.1: 561 | version "1.0.1" 562 | resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 563 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 564 | 565 | tr46@~0.0.3: 566 | version "0.0.3" 567 | resolved "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 568 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 569 | 570 | type-is@^1.6.4, type-is@~1.6.18: 571 | version "1.6.18" 572 | resolved "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 573 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 574 | dependencies: 575 | media-typer "0.3.0" 576 | mime-types "~2.1.24" 577 | 578 | typedarray@^0.0.6: 579 | version "0.0.6" 580 | resolved "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 581 | integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== 582 | 583 | unpipe@1.0.0, unpipe@~1.0.0: 584 | version "1.0.0" 585 | resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 586 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 587 | 588 | util-deprecate@~1.0.1: 589 | version "1.0.2" 590 | resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 591 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 592 | 593 | utils-merge@1.0.1: 594 | version "1.0.1" 595 | resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 596 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 597 | 598 | vary@~1.1.2: 599 | version "1.1.2" 600 | resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 601 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 602 | 603 | webidl-conversions@^3.0.0: 604 | version "3.0.1" 605 | resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 606 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 607 | 608 | whatwg-url@^5.0.0: 609 | version "5.0.0" 610 | resolved "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 611 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 612 | dependencies: 613 | tr46 "~0.0.3" 614 | webidl-conversions "^3.0.0" 615 | 616 | xtend@^4.0.0: 617 | version "4.0.2" 618 | resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 619 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 620 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.3.8: 6 | version "1.3.8" 7 | resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 8 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 9 | dependencies: 10 | mime-types "~2.1.34" 11 | negotiator "0.6.3" 12 | 13 | agent-base@6: 14 | version "6.0.2" 15 | resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 16 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 17 | dependencies: 18 | debug "4" 19 | 20 | append-field@^1.0.0: 21 | version "1.0.0" 22 | resolved "https://registry.npmmirror.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" 23 | integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== 24 | 25 | array-flatten@1.1.1: 26 | version "1.1.1" 27 | resolved "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 28 | integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== 29 | 30 | asynckit@^0.4.0: 31 | version "0.4.0" 32 | resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 33 | integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== 34 | 35 | body-parser@1.20.1: 36 | version "1.20.1" 37 | resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" 38 | integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== 39 | dependencies: 40 | bytes "3.1.2" 41 | content-type "~1.0.4" 42 | debug "2.6.9" 43 | depd "2.0.0" 44 | destroy "1.2.0" 45 | http-errors "2.0.0" 46 | iconv-lite "0.4.24" 47 | on-finished "2.4.1" 48 | qs "6.11.0" 49 | raw-body "2.5.1" 50 | type-is "~1.6.18" 51 | unpipe "1.0.0" 52 | 53 | body-parser@^1.20.2: 54 | version "1.20.2" 55 | resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" 56 | integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== 57 | dependencies: 58 | bytes "3.1.2" 59 | content-type "~1.0.5" 60 | debug "2.6.9" 61 | depd "2.0.0" 62 | destroy "1.2.0" 63 | http-errors "2.0.0" 64 | iconv-lite "0.4.24" 65 | on-finished "2.4.1" 66 | qs "6.11.0" 67 | raw-body "2.5.2" 68 | type-is "~1.6.18" 69 | unpipe "1.0.0" 70 | 71 | buffer-from@^1.0.0: 72 | version "1.1.2" 73 | resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" 74 | integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 75 | 76 | busboy@^1.0.0: 77 | version "1.6.0" 78 | resolved "https://registry.npmmirror.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" 79 | integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== 80 | dependencies: 81 | streamsearch "^1.1.0" 82 | 83 | bytes@3.1.2: 84 | version "3.1.2" 85 | resolved "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 86 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 87 | 88 | call-bind@^1.0.0: 89 | version "1.0.2" 90 | resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" 91 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 92 | dependencies: 93 | function-bind "^1.1.1" 94 | get-intrinsic "^1.0.2" 95 | 96 | combined-stream@^1.0.8: 97 | version "1.0.8" 98 | resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 99 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 100 | dependencies: 101 | delayed-stream "~1.0.0" 102 | 103 | concat-stream@^1.5.2: 104 | version "1.6.2" 105 | resolved "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" 106 | integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== 107 | dependencies: 108 | buffer-from "^1.0.0" 109 | inherits "^2.0.3" 110 | readable-stream "^2.2.2" 111 | typedarray "^0.0.6" 112 | 113 | content-disposition@0.5.4: 114 | version "0.5.4" 115 | resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 116 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 117 | dependencies: 118 | safe-buffer "5.2.1" 119 | 120 | content-type@~1.0.4, content-type@~1.0.5: 121 | version "1.0.5" 122 | resolved "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 123 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 124 | 125 | cookie-signature@1.0.6: 126 | version "1.0.6" 127 | resolved "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 128 | integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== 129 | 130 | cookie@0.5.0: 131 | version "0.5.0" 132 | resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" 133 | integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== 134 | 135 | core-util-is@~1.0.0: 136 | version "1.0.3" 137 | resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" 138 | integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== 139 | 140 | cors@^2.8.5: 141 | version "2.8.5" 142 | resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" 143 | integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== 144 | dependencies: 145 | object-assign "^4" 146 | vary "^1" 147 | 148 | cross-fetch@^3.1.5: 149 | version "3.1.5" 150 | resolved "https://registry.npmmirror.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" 151 | integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== 152 | dependencies: 153 | node-fetch "2.6.7" 154 | 155 | debug@2.6.9: 156 | version "2.6.9" 157 | resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 158 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 159 | dependencies: 160 | ms "2.0.0" 161 | 162 | debug@4: 163 | version "4.3.4" 164 | resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 165 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 166 | dependencies: 167 | ms "2.1.2" 168 | 169 | delayed-stream@~1.0.0: 170 | version "1.0.0" 171 | resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 172 | integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== 173 | 174 | depd@2.0.0: 175 | version "2.0.0" 176 | resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 177 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 178 | 179 | destroy@1.2.0: 180 | version "1.2.0" 181 | resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" 182 | integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== 183 | 184 | ee-first@1.1.1: 185 | version "1.1.1" 186 | resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 187 | integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== 188 | 189 | encodeurl@~1.0.2: 190 | version "1.0.2" 191 | resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 192 | integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== 193 | 194 | escape-html@~1.0.3: 195 | version "1.0.3" 196 | resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 197 | integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== 198 | 199 | etag@~1.8.1: 200 | version "1.8.1" 201 | resolved "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 202 | integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== 203 | 204 | eventsource-parser@^0.1.0: 205 | version "0.1.0" 206 | resolved "https://registry.npmmirror.com/eventsource-parser/-/eventsource-parser-0.1.0.tgz#4a6b84751ca8e704040e6f7f50e7d77344fa1b7c" 207 | integrity sha512-M9QjFtEIkwytUarnx113HGmgtk52LSn3jNAtnWKi3V+b9rqSfQeVdLsaD5AG/O4IrGQwmAAHBIsqbmURPTd2rA== 208 | 209 | express@^4.18.2: 210 | version "4.18.2" 211 | resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" 212 | integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== 213 | dependencies: 214 | accepts "~1.3.8" 215 | array-flatten "1.1.1" 216 | body-parser "1.20.1" 217 | content-disposition "0.5.4" 218 | content-type "~1.0.4" 219 | cookie "0.5.0" 220 | cookie-signature "1.0.6" 221 | debug "2.6.9" 222 | depd "2.0.0" 223 | encodeurl "~1.0.2" 224 | escape-html "~1.0.3" 225 | etag "~1.8.1" 226 | finalhandler "1.2.0" 227 | fresh "0.5.2" 228 | http-errors "2.0.0" 229 | merge-descriptors "1.0.1" 230 | methods "~1.1.2" 231 | on-finished "2.4.1" 232 | parseurl "~1.3.3" 233 | path-to-regexp "0.1.7" 234 | proxy-addr "~2.0.7" 235 | qs "6.11.0" 236 | range-parser "~1.2.1" 237 | safe-buffer "5.2.1" 238 | send "0.18.0" 239 | serve-static "1.15.0" 240 | setprototypeof "1.2.0" 241 | statuses "2.0.1" 242 | type-is "~1.6.18" 243 | utils-merge "1.0.1" 244 | vary "~1.1.2" 245 | 246 | finalhandler@1.2.0: 247 | version "1.2.0" 248 | resolved "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" 249 | integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== 250 | dependencies: 251 | debug "2.6.9" 252 | encodeurl "~1.0.2" 253 | escape-html "~1.0.3" 254 | on-finished "2.4.1" 255 | parseurl "~1.3.3" 256 | statuses "2.0.1" 257 | unpipe "~1.0.0" 258 | 259 | form-data@^3.0.0: 260 | version "3.0.1" 261 | resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" 262 | integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== 263 | dependencies: 264 | asynckit "^0.4.0" 265 | combined-stream "^1.0.8" 266 | mime-types "^2.1.12" 267 | 268 | forwarded@0.2.0: 269 | version "0.2.0" 270 | resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 271 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 272 | 273 | fresh@0.5.2: 274 | version "0.5.2" 275 | resolved "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 276 | integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== 277 | 278 | function-bind@^1.1.1: 279 | version "1.1.1" 280 | resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 281 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 282 | 283 | get-intrinsic@^1.0.2: 284 | version "1.2.0" 285 | resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" 286 | integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== 287 | dependencies: 288 | function-bind "^1.1.1" 289 | has "^1.0.3" 290 | has-symbols "^1.0.3" 291 | 292 | get-stream@^6.0.0: 293 | version "6.0.1" 294 | resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" 295 | integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== 296 | 297 | has-symbols@^1.0.3: 298 | version "1.0.3" 299 | resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" 300 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 301 | 302 | has@^1.0.3: 303 | version "1.0.3" 304 | resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 305 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 306 | dependencies: 307 | function-bind "^1.1.1" 308 | 309 | http-errors@2.0.0: 310 | version "2.0.0" 311 | resolved "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 312 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 313 | dependencies: 314 | depd "2.0.0" 315 | inherits "2.0.4" 316 | setprototypeof "1.2.0" 317 | statuses "2.0.1" 318 | toidentifier "1.0.1" 319 | 320 | https-proxy-agent@^5.0.0: 321 | version "5.0.1" 322 | resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" 323 | integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== 324 | dependencies: 325 | agent-base "6" 326 | debug "4" 327 | 328 | iconv-lite@0.4.24: 329 | version "0.4.24" 330 | resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 331 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 332 | dependencies: 333 | safer-buffer ">= 2.1.2 < 3" 334 | 335 | inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3: 336 | version "2.0.4" 337 | resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 338 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 339 | 340 | ipaddr.js@1.9.1: 341 | version "1.9.1" 342 | resolved "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 343 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 344 | 345 | is-stream@^2.0.0: 346 | version "2.0.1" 347 | resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" 348 | integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== 349 | 350 | isarray@~1.0.0: 351 | version "1.0.0" 352 | resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 353 | integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== 354 | 355 | media-typer@0.3.0: 356 | version "0.3.0" 357 | resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 358 | integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== 359 | 360 | merge-descriptors@1.0.1: 361 | version "1.0.1" 362 | resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 363 | integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== 364 | 365 | methods@~1.1.2: 366 | version "1.1.2" 367 | resolved "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 368 | integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== 369 | 370 | mime-db@1.52.0: 371 | version "1.52.0" 372 | resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 373 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 374 | 375 | mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: 376 | version "2.1.35" 377 | resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 378 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 379 | dependencies: 380 | mime-db "1.52.0" 381 | 382 | mime@1.6.0: 383 | version "1.6.0" 384 | resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 385 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 386 | 387 | minimist@^1.2.6: 388 | version "1.2.8" 389 | resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" 390 | integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== 391 | 392 | mkdirp@^0.5.4: 393 | version "0.5.6" 394 | resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 395 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 396 | dependencies: 397 | minimist "^1.2.6" 398 | 399 | ms@2.0.0: 400 | version "2.0.0" 401 | resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 402 | integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== 403 | 404 | ms@2.1.2: 405 | version "2.1.2" 406 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 407 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 408 | 409 | ms@2.1.3: 410 | version "2.1.3" 411 | resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 412 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 413 | 414 | multer@^1.4.5-lts.1: 415 | version "1.4.5-lts.1" 416 | resolved "https://registry.npmmirror.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac" 417 | integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ== 418 | dependencies: 419 | append-field "^1.0.0" 420 | busboy "^1.0.0" 421 | concat-stream "^1.5.2" 422 | mkdirp "^0.5.4" 423 | object-assign "^4.1.1" 424 | type-is "^1.6.4" 425 | xtend "^4.0.0" 426 | 427 | negotiator@0.6.3: 428 | version "0.6.3" 429 | resolved "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 430 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 431 | 432 | node-fetch@2.6.7: 433 | version "2.6.7" 434 | resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 435 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 436 | dependencies: 437 | whatwg-url "^5.0.0" 438 | 439 | node-fetch@^2.2.0: 440 | version "2.6.9" 441 | resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" 442 | integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== 443 | dependencies: 444 | whatwg-url "^5.0.0" 445 | 446 | object-assign@^4, object-assign@^4.1.1: 447 | version "4.1.1" 448 | resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 449 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 450 | 451 | object-inspect@^1.9.0: 452 | version "1.12.3" 453 | resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" 454 | integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== 455 | 456 | on-finished@2.4.1: 457 | version "2.4.1" 458 | resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" 459 | integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== 460 | dependencies: 461 | ee-first "1.1.1" 462 | 463 | parseurl@~1.3.3: 464 | version "1.3.3" 465 | resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 466 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 467 | 468 | path-to-regexp@0.1.7: 469 | version "0.1.7" 470 | resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 471 | integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== 472 | 473 | process-nextick-args@~2.0.0: 474 | version "2.0.1" 475 | resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 476 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 477 | 478 | proxy-addr@~2.0.7: 479 | version "2.0.7" 480 | resolved "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 481 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 482 | dependencies: 483 | forwarded "0.2.0" 484 | ipaddr.js "1.9.1" 485 | 486 | qs@6.11.0: 487 | version "6.11.0" 488 | resolved "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" 489 | integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== 490 | dependencies: 491 | side-channel "^1.0.4" 492 | 493 | range-parser@~1.2.1: 494 | version "1.2.1" 495 | resolved "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 496 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 497 | 498 | raw-body@2.5.1: 499 | version "2.5.1" 500 | resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" 501 | integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== 502 | dependencies: 503 | bytes "3.1.2" 504 | http-errors "2.0.0" 505 | iconv-lite "0.4.24" 506 | unpipe "1.0.0" 507 | 508 | raw-body@2.5.2: 509 | version "2.5.2" 510 | resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" 511 | integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== 512 | dependencies: 513 | bytes "3.1.2" 514 | http-errors "2.0.0" 515 | iconv-lite "0.4.24" 516 | unpipe "1.0.0" 517 | 518 | readable-stream@^2.2.2: 519 | version "2.3.8" 520 | resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" 521 | integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== 522 | dependencies: 523 | core-util-is "~1.0.0" 524 | inherits "~2.0.3" 525 | isarray "~1.0.0" 526 | process-nextick-args "~2.0.0" 527 | safe-buffer "~5.1.1" 528 | string_decoder "~1.1.1" 529 | util-deprecate "~1.0.1" 530 | 531 | safe-buffer@5.2.1: 532 | version "5.2.1" 533 | resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 534 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 535 | 536 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 537 | version "5.1.2" 538 | resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 539 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 540 | 541 | "safer-buffer@>= 2.1.2 < 3": 542 | version "2.1.2" 543 | resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 544 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 545 | 546 | send@0.18.0: 547 | version "0.18.0" 548 | resolved "https://registry.npmmirror.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" 549 | integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== 550 | dependencies: 551 | debug "2.6.9" 552 | depd "2.0.0" 553 | destroy "1.2.0" 554 | encodeurl "~1.0.2" 555 | escape-html "~1.0.3" 556 | etag "~1.8.1" 557 | fresh "0.5.2" 558 | http-errors "2.0.0" 559 | mime "1.6.0" 560 | ms "2.1.3" 561 | on-finished "2.4.1" 562 | range-parser "~1.2.1" 563 | statuses "2.0.1" 564 | 565 | serve-static@1.15.0: 566 | version "1.15.0" 567 | resolved "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" 568 | integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== 569 | dependencies: 570 | encodeurl "~1.0.2" 571 | escape-html "~1.0.3" 572 | parseurl "~1.3.3" 573 | send "0.18.0" 574 | 575 | setprototypeof@1.2.0: 576 | version "1.2.0" 577 | resolved "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 578 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 579 | 580 | side-channel@^1.0.4: 581 | version "1.0.4" 582 | resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" 583 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 584 | dependencies: 585 | call-bind "^1.0.0" 586 | get-intrinsic "^1.0.2" 587 | object-inspect "^1.9.0" 588 | 589 | statuses@2.0.1: 590 | version "2.0.1" 591 | resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 592 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 593 | 594 | streamsearch@^1.1.0: 595 | version "1.1.0" 596 | resolved "https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" 597 | integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== 598 | 599 | string_decoder@~1.1.1: 600 | version "1.1.1" 601 | resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 602 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 603 | dependencies: 604 | safe-buffer "~5.1.0" 605 | 606 | tencentcloud-sdk-nodejs@^4.0.567: 607 | version "4.0.567" 608 | resolved "https://registry.npmjs.org/tencentcloud-sdk-nodejs/-/tencentcloud-sdk-nodejs-4.0.567.tgz#f3fca8d9f21eeca0b4bd7ebea7231834498d45a1" 609 | integrity sha512-ly/VG/tpBlk8XFZ0GoglDPvWVDPFUk4c3WdyZcd0x0cXYw1ac88EKeMscMkNjOaomCR4q2wUQPoDPqA4UufSBg== 610 | dependencies: 611 | form-data "^3.0.0" 612 | get-stream "^6.0.0" 613 | https-proxy-agent "^5.0.0" 614 | is-stream "^2.0.0" 615 | node-fetch "^2.2.0" 616 | tslib "1.13.0" 617 | 618 | toidentifier@1.0.1: 619 | version "1.0.1" 620 | resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 621 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 622 | 623 | tr46@~0.0.3: 624 | version "0.0.3" 625 | resolved "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 626 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 627 | 628 | tslib@1.13.0: 629 | version "1.13.0" 630 | resolved "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" 631 | integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== 632 | 633 | type-is@^1.6.4, type-is@~1.6.18: 634 | version "1.6.18" 635 | resolved "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 636 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 637 | dependencies: 638 | media-typer "0.3.0" 639 | mime-types "~2.1.24" 640 | 641 | typedarray@^0.0.6: 642 | version "0.0.6" 643 | resolved "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 644 | integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== 645 | 646 | unpipe@1.0.0, unpipe@~1.0.0: 647 | version "1.0.0" 648 | resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 649 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 650 | 651 | util-deprecate@~1.0.1: 652 | version "1.0.2" 653 | resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 654 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 655 | 656 | utils-merge@1.0.1: 657 | version "1.0.1" 658 | resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 659 | integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== 660 | 661 | vary@^1, vary@~1.1.2: 662 | version "1.1.2" 663 | resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 664 | integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== 665 | 666 | webidl-conversions@^3.0.0: 667 | version "3.0.1" 668 | resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 669 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 670 | 671 | whatwg-url@^5.0.0: 672 | version "5.0.0" 673 | resolved "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 674 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 675 | dependencies: 676 | tr46 "~0.0.3" 677 | webidl-conversions "^3.0.0" 678 | 679 | xtend@^4.0.0: 680 | version "4.0.2" 681 | resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 682 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 683 | --------------------------------------------------------------------------------