├── src
├── typings.d.ts
├── interface
│ ├── errorCodes.ts
│ └── common.ts
├── index.ts
├── app.ts
├── routers.ts
├── controllers
│ └── storage.ts
└── class
│ └── storage.ts
├── .dockerignore
├── .gitignore
├── Dockerfile
├── package.json
├── LICENSE
├── tsconfig.json
├── .github
└── workflows
│ └── docker-publish.yml
├── README.md
└── pnpm-lock.yaml
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.json" {
2 | const value: any;
3 | export default value;
4 | }
5 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .git
3 | .gitignore
4 | *.md
5 | dist
6 | storage
7 | .vscode
8 | .github
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
23 | # 发布的二进制文件
24 | /releases
25 | /database
26 | /config
27 | /storage
--------------------------------------------------------------------------------
/src/interface/errorCodes.ts:
--------------------------------------------------------------------------------
1 | const ERROR = {
2 | PermissionDenied: {
3 | code: 10001,
4 | msg: "Permission Denied"
5 | },
6 |
7 | MaxResourceLimit: {
8 | code: 10002,
9 | msg: "Maximum resource limit"
10 | },
11 |
12 | InvalidRequest: {
13 | code: 10003,
14 | msg: "Invalid request"
15 | },
16 |
17 | InvalidResourceId: {
18 | code: 10004,
19 | msg: "Invalid request id"
20 | },
21 |
22 | InvalidResourceName: {
23 | code: 10005,
24 | msg: "Invalid request name"
25 | },
26 |
27 | InvalidResourcePath: {
28 | code: 10006,
29 | msg: "Invalid resource path"
30 | },
31 |
32 | InvalidResourceData: {
33 | code: 10007,
34 | msg: "Invalid resource data"
35 | }
36 | };
37 |
38 | export default ERROR;
39 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # ⚙️ 基础构建镜像:含 pnpm + 源码
2 | FROM node:22-alpine AS base
3 | ENV PNPM_HOME="/pnpm"
4 | ENV PATH="$PNPM_HOME:$PATH"
5 | RUN corepack enable pnpm
6 | WORKDIR /app
7 | COPY package.json pnpm-lock.yaml ./
8 |
9 | # 📦 安装 prod 依赖
10 | FROM base AS prod-deps
11 | RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
12 | pnpm install --prod --frozen-lockfile
13 |
14 | # 🛠️ 构建阶段
15 | FROM base AS build
16 | RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
17 | pnpm install --frozen-lockfile
18 | COPY . .
19 | RUN pnpm run build
20 |
21 | # 🚀 最终运行镜像
22 | FROM node:22-alpine
23 | WORKDIR /app
24 | COPY --from=prod-deps /app/node_modules ./node_modules
25 | COPY --from=build /app/dist ./dist
26 | COPY --from=build /app/package.json ./package.json
27 | VOLUME ["/app/storage", "/app/config"]
28 | EXPOSE 8088
29 | CMD [ "node", "./dist/index.js" ]
30 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "open-web-simple-storage",
3 | "version": "1.0.0",
4 | "description": "Open Web Simple Storage",
5 | "main": "index.js",
6 | "author": "culturist",
7 | "license": "MIT",
8 | "scripts": {
9 | "test": "tsc && node ./dist/index.js",
10 | "watch": "tsc -w",
11 | "build": "tsc",
12 | "dev": "tsc && node ./dist/index.js",
13 | "start": "node ./dist/index.js",
14 | "init": "pnpm install && tsc && node ./dist/index.js",
15 | "clean": "rm -rf ./node_modules",
16 | "install:prod": "pnpm install --production"
17 | },
18 | "dependencies": {
19 | "body-parser": "^2.2.0",
20 | "crypto-js": "^4.2.0",
21 | "extend": "^3.0.2",
22 | "request-ip": "^3.3.0",
23 | "restify": "^11.1.0"
24 | },
25 | "devDependencies": {
26 | "@types/crypto-js": "^4.2.2",
27 | "@types/extend": "^3.0.4",
28 | "@types/node": "^22.14.0",
29 | "@types/request-ip": "^0.0.41",
30 | "@types/restify": "^8.5.12",
31 | "ts-node": "^10.9.2",
32 | "typescript": "^5.8.3"
33 | }
34 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 栽培者
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.
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // tsconfig 所在的根目录, 则是一个project
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "@/*": [
7 | "src/*"
8 | ]
9 | },
10 | "module": "commonjs", // 模块系统
11 | "target": "es2015", // 生成目标, 一般选择ES6,因为不是客户端环境,没必要还编译成 ES5
12 | "outDir": "dist",
13 | // 一组严苛的编译选项
14 | "noImplicitAny": false,
15 | "strictNullChecks": true,
16 | "strict": true,
17 | "alwaysStrict": true,
18 | "sourceMap": false,
19 | "noImplicitReturns": true,
20 | "noImplicitThis": true,
21 | "pretty": true,
22 | "listFiles": true, // 包含了哪些库,这个必要的时候还是很有用的
23 | "listEmittedFiles": true,
24 | "lib": [ // 要那些 lib,按需选择即可
25 | "es2016"
26 | ],
27 | // "noUnusedLocals": true,
28 | // "noUnusedParameters": true,
29 | // "noFallthroughCasesInSwitch": true,
30 | // 指定库的搜索路径,这个比较有用,一般会指定 @types,还可以按需添加
31 | "typeRoots": [
32 | "./node_modules/@types"
33 | ]
34 | // 库搜索路径下, 仅使用哪些库, 一般没啥用
35 | // "types": [
36 | // ]
37 | },
38 | // file include会算出一个交集, 指明哪些是项目的 ts 文件
39 | "include": [
40 | "./**/*"
41 | ],
42 | // 排除项目下面不符合要求的文件,这个按需设定即可,可以放心排除乱七八糟的文件
43 | "exclude": [
44 | "node_modules",
45 | "**/*.spec.ts",
46 | "*.js"
47 | ]
48 | }
--------------------------------------------------------------------------------
/.github/workflows/docker-publish.yml:
--------------------------------------------------------------------------------
1 | name: Build and Push Docker image
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | workflow_dispatch:
8 | inputs:
9 | tag:
10 | description: 'Docker image tag (e.g. v1.0.0)'
11 | required: false
12 | default: 'latest'
13 |
14 | jobs:
15 | build-and-push:
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - name: Checkout code
20 | uses: actions/checkout@v3
21 |
22 | - name: Set Docker image tag
23 | id: vars
24 | run: |
25 | # 如果是手动输入 tag 就用它,否则默认用 latest
26 | echo "tag=${{ github.event.inputs.tag || 'latest' }}" >> $GITHUB_OUTPUT
27 |
28 | - name: Log in to Docker Hub
29 | uses: docker/login-action@v2
30 | with:
31 | username: ${{ secrets.DOCKER_USERNAME }}
32 | password: ${{ secrets.DOCKER_PASSWORD }}
33 |
34 | - name: Set up Docker Buildx
35 | uses: docker/setup-buildx-action@v3
36 |
37 | - name: Build and push Docker image
38 | uses: docker/build-push-action@v5
39 | with:
40 | context: .
41 | push: true
42 | tags: ronggang/owss:${{ steps.vars.outputs.tag }}
43 |
--------------------------------------------------------------------------------
/src/interface/common.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 服务器部署类型
3 | */
4 | export enum EDeployType {
5 | Private = "Private",
6 | Public = "Public"
7 | }
8 |
9 | /**
10 | * 用户验证类型
11 | */
12 | export enum EAuthType {
13 | OAuth2 = "OAuth2",
14 | None = "None"
15 | }
16 |
17 | export interface IAppConfig {
18 | server: {
19 | version?: string;
20 | name: string;
21 | port: number;
22 | // 启用访问白名单
23 | enableAccessWhitelist?: boolean;
24 | // 访问白名单
25 | accessWhitelist?: string[];
26 | // 部署类型,设置为私有时,默认仅在内网可申请创建资源
27 | deployType?: EDeployType | string;
28 | };
29 |
30 | isFirstTime?: boolean;
31 | storage: IStorageServiceConfig;
32 | }
33 |
34 | export interface IResourceOptions {
35 | authType?: EAuthType;
36 | resourceCount?: number;
37 | }
38 |
39 | export interface IStorageServiceConfig {
40 | dataPath: string;
41 | configPath: string;
42 | rootPath: string;
43 | maxResource?: number;
44 | tmpPath?: string;
45 | sharePath?: string;
46 | resourceBlacklist?: string[];
47 | autoCleanOldResource?: boolean;
48 | }
49 |
50 | export enum EResourceOrderBy {
51 | time = "time",
52 | name = "name",
53 | size = "size"
54 | }
55 |
56 | export enum EResourceOrderMode {
57 | desc = "desc",
58 | asc = "asc"
59 | }
60 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as PATH from "path";
2 | import * as FS from "fs";
3 | import { IAppConfig, EDeployType } from "./interface/common";
4 | import App from "./app";
5 |
6 | function main() {
7 | // 由环境变量指定部署类型
8 | const deployType = process.env.DEPLOY_TYPE;
9 | const confPath = PATH.join(__dirname, "../config");
10 | const conf = PATH.join(confPath, "config.json");
11 | const packageFile = FS.readFileSync(
12 | PATH.join(__dirname, "../package.json"),
13 | "utf-8"
14 | );
15 |
16 | if (!FS.existsSync(conf)) {
17 | if (!FS.existsSync(confPath)) {
18 | FS.mkdirSync(confPath, {
19 | recursive: true
20 | });
21 | }
22 |
23 | let defaultConf: IAppConfig = {
24 | server: {
25 | port: 8088,
26 | name: "OWSS",
27 | version: "0.0.1",
28 | enableAccessWhitelist: false,
29 | deployType: deployType || EDeployType.Private
30 | },
31 | storage: {
32 | rootPath: "storage",
33 | configPath: "conf",
34 | dataPath: "data",
35 | autoCleanOldResource: false,
36 | maxResource: 100
37 | }
38 | };
39 | FS.writeFileSync(conf, JSON.stringify(defaultConf));
40 | defaultConf.isFirstTime = true;
41 | new App(defaultConf);
42 | return;
43 | }
44 |
45 | try {
46 | let appConf: IAppConfig = JSON.parse(FS.readFileSync(conf, "utf-8"));
47 | if (deployType) {
48 | appConf.server.deployType = deployType;
49 | }
50 | appConf.server.version = JSON.parse(packageFile).version;
51 | new App(appConf);
52 | } catch (error) {
53 | console.log(error);
54 | }
55 | }
56 |
57 | main();
58 |
--------------------------------------------------------------------------------
/src/app.ts:
--------------------------------------------------------------------------------
1 | // 导入基础库
2 | import * as restify from "restify";
3 | import { IAppConfig } from "./interface/common";
4 | import * as PATH from "path";
5 | import * as FS from "fs";
6 | import { Routers } from "./routers";
7 | import * as extend from "extend";
8 | import * as requestIP from "request-ip";
9 |
10 | /**
11 | * 默认APP
12 | */
13 | class App {
14 | public routers: Routers = new Routers(this);
15 | public config: IAppConfig = {
16 | server: {
17 | port: 8088,
18 | name: "OWSS"
19 | },
20 | storage: {
21 | rootPath: "storage",
22 | configPath: "conf",
23 | dataPath: "data"
24 | }
25 | };
26 | public rootPath: string = "";
27 |
28 | constructor(config?: IAppConfig) {
29 | this.rootPath = PATH.join(__dirname, "../");
30 | this.config.storage.tmpPath = PATH.join(
31 | this.rootPath,
32 | this.config.storage.rootPath,
33 | "tmp"
34 | );
35 |
36 | if (!FS.existsSync(this.config.storage.tmpPath)) {
37 | FS.mkdirSync(this.config.storage.tmpPath, { recursive: true });
38 | }
39 |
40 | this.config.storage.sharePath = PATH.join(
41 | this.rootPath,
42 | this.config.storage.rootPath,
43 | "share"
44 | );
45 |
46 | if (!FS.existsSync(this.config.storage.sharePath)) {
47 | FS.mkdirSync(this.config.storage.sharePath, { recursive: true });
48 | }
49 |
50 | this.config = extend(true, this.config, config);
51 | this.routers.start();
52 | }
53 |
54 | /**
55 | * 验证ip白名单
56 | * @param req
57 | */
58 | public isWhitelist(req: restify.Request, whitelist?: string[]): boolean {
59 | let ip = requestIP.getClientIp(req);
60 |
61 | if (!this.config.server.enableAccessWhitelist && !whitelist) {
62 | return true;
63 | }
64 |
65 | if (!ip) {
66 | return false;
67 | }
68 |
69 | if (!whitelist) {
70 | const config = this.config.server;
71 | whitelist = config.accessWhitelist;
72 | }
73 |
74 | let result = false;
75 | if (whitelist && whitelist.length > 0) {
76 | whitelist.some(item => {
77 | let rule = item.replace(/\*/g, "\\d+");
78 | rule = rule.replace(/\./g, "\\.");
79 | let match = new RegExp(`^(${rule})$`, "");
80 | if (match.test(ip)) {
81 | result = true;
82 | return true;
83 | }
84 | return false;
85 | });
86 | }
87 | return result;
88 | }
89 | }
90 |
91 | export default App;
92 |
--------------------------------------------------------------------------------
/src/routers.ts:
--------------------------------------------------------------------------------
1 | // 导入基础库
2 | import * as restify from "restify";
3 | import { StorageController } from "./controllers/storage";
4 | import App from "./app";
5 | import ERROR from "./interface/errorCodes";
6 |
7 | export class Routers {
8 | public server: restify.Server;
9 | constructor(public app: App) {
10 | this.server = {} as any;
11 | }
12 |
13 | /**
14 | * 挂载路由
15 | */
16 | private mountRoutes(): void {
17 | this.server.get(
18 | "/storage",
19 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
20 | res.send(200, "Welcome to use OWSS.");
21 | next();
22 | }
23 | );
24 |
25 | let storage = new StorageController(this.app);
26 |
27 | // 创建
28 | this.server.get(
29 | "/storage/create",
30 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
31 | storage.create(req, res, next);
32 | }
33 | );
34 |
35 | // 获取列表
36 | this.server.get(
37 | "/storage/:resourceId/list",
38 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
39 | storage.list(req, res, next);
40 | }
41 | );
42 |
43 | this.server.post(
44 | "/storage/:resourceId/add",
45 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
46 | storage.add(req, res, next);
47 | }
48 | );
49 |
50 | this.server.get(
51 | "/storage/:resourceId/get/:path",
52 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
53 | storage.get(req, res, next);
54 | }
55 | );
56 |
57 | this.server.post(
58 | "/storage/:resourceId/delete/:path",
59 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
60 | storage.delete(req, res, next);
61 | }
62 | );
63 |
64 | this.server.get(
65 | "/share/:id",
66 | (req: restify.Request, res: restify.Response, next: restify.Next) => {
67 | storage.getShare(req, res, next);
68 | }
69 | );
70 | }
71 |
72 | /**
73 | * 初始化插件
74 | */
75 | private initPlugins(server: restify.Server) {
76 | // 使用数据解析器
77 | server.use(
78 | restify.plugins.bodyParser({
79 | uploadDir: this.app.config.storage.tmpPath
80 | }),
81 | restify.plugins.queryParser()
82 | );
83 |
84 | // 设置允许跨域头信息
85 | server.use((req, res, next) => {
86 | res.header("Access-Control-Allow-Origin", "*");
87 | res.header("Access-Control-Allow-Headers", "X-Requested-With");
88 | next();
89 | });
90 |
91 | // 验证白名单
92 | server.use((req, res, next) => {
93 | if (req.socket.remoteAddress && this.app.isWhitelist(req)) {
94 | next();
95 | } else {
96 | res.send(401, ERROR.PermissionDenied);
97 | }
98 | });
99 | }
100 |
101 | /**
102 | * 启动服务
103 | */
104 | public start() {
105 | let server = restify.createServer({
106 | name: this.app.config.server.name
107 | });
108 |
109 | this.initPlugins(server);
110 |
111 | this.server = server;
112 | this.mountRoutes();
113 |
114 | const port = this.app.config.server.port;
115 |
116 | server.listen(port, () => {
117 | const storageConfg = this.app.config.storage;
118 | console.log(
119 | "\n%s 服务已启动 \n当前版本:%s \n本地端口:%s \n部署类型:%s \n自动清理:%s \n服务地址:%s \n%s \n使用说明:%s",
120 | this.server.name,
121 | this.app.config.server.version,
122 | port,
123 | this.app.config.server.deployType,
124 | storageConfg.autoCleanOldResource
125 | ? `已启用,每个授权码最多可存储 ${storageConfg.maxResource} 个资源`
126 | : "未启用",
127 | `http://127.0.0.1:${port}/storage`,
128 | "-----------------------------------------",
129 | "https://github.com/ronggang/OWSS"
130 | );
131 | });
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | OWSS
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ---
11 | Open Web Simple Storage(OWSS),一个基于 `nodejs` 简单的 Web 存储微服务,可用于私人配置文件集中存储。
12 |
13 | ## 如何使用
14 | - 部署服务器程序;
15 | - 向已部署的服务器申请一个资源ID(授权码);
16 | - 开始使用
17 | - 创建文件;
18 | - 下载文件;
19 | - 删除文件;
20 |
21 | ## 服务器部署
22 | ### 方式一:Docker 部署
23 | - 安装 [Docker](https://docker.com)
24 | - 拉取镜像
25 | ``` shell
26 | docker pull ronggang/owss
27 | ```
28 | - 部署示例
29 | ``` shell
30 | # Linux
31 | docker run -d -v /OWSS/storage:/app/storage -v /OWSS/config:/app/config -p 8088:8088 ronggang/owss
32 |
33 | # Windows
34 | docker run -d -v "D:/OWSS/storage":/app/storage -v "D:/OWSS/config":/app/config -p 8088:8088 ronggang/owss
35 | ```
36 | - 数据目录
37 | - `/app/storage` : 数据存储目录;
38 | - `/app/config` : 服务运行配置目录;
39 |
40 | - 如果您需要部署到 `群晖 NAS` 里,请参考 [Synology 部署说明](https://github.com/ronggang/OWSS/wiki/Install-Synology);
41 |
42 |
43 | ### 方式二:从源码部署
44 | - 安装环境依赖:
45 | - [nodejs](https://nodejs.org) ;
46 | - [pnpm](https://pnpm.io/zh/) ;
47 | - 下载最新的发布版本,[点我前往下载](https://github.com/ronggang/OWSS/releases) ;
48 | - 解压到你想要保存的目录(如:`/OWSS/` );
49 | - 如果您已安装 [git](https://git-scm.com) ,也可直接 `clone` 本项目:
50 | ```
51 | git clone https://github.com/ronggang/OWSS.git
52 | ```
53 | - 运行程序;
54 | ```
55 | pnpm init
56 | ```
57 |
58 | ## 首次运行说明
59 | - 首次运行时,会自动创建一个 `./config/config.json` 文件,同时生成一个授权码,请留意 `stdout` 输出内容;
60 | - 程序默认运行在 `8088` 端口下,可通过 `./config/config.json` 进行参数调整;调整后,重新运行程序即可;
61 |
62 | ## config 文件说明
63 | ``` jsonc
64 | {
65 | // 服务器配置
66 | "server": {
67 | // 服务运行的端口号
68 | "port": 8118,
69 | // 是否启用访问白名单
70 | "enableAccessWhitelist": false,
71 | // 访问白名单列表
72 | "accessWhitelist": [
73 | "127.0.0.1",
74 | "localhost",
75 | "::1"
76 | ],
77 | // 部署类型(Private, Public)
78 | // 设置为私有时,默认仅在本机可申请创建资源,其他接口(如上传、下载)可正常使用
79 | "deployType": "Private"
80 | },
81 | // 存储配置
82 | "storage": {
83 | // 最大资源数量
84 | "maxResource": 10,
85 | // 是否启用自动清理,如果启用该参数,每个授权码最多允许存储 `maxResource` 个文件,超过时会自动删除最老的文件
86 | "autoCleanOldResource": false
87 | }
88 | }
89 | ```
90 | 示例:
91 | ``` json
92 | {
93 | "server": {
94 | "port": 8118,
95 | "deployType": "Private"
96 | }
97 | }
98 | ```
99 |
100 | ## 客户端使用
101 | - 请求根路径默认为: `http(s)://ip_or_host:port/storage` ,该地址为服务地址,例:
102 | - `http://192.168.10.10:8088/storage`
103 |
104 | - 为行文方便,服务地址以下简称:`service_url/`
105 |
106 |
107 | ### GET `service_url/create`
108 | - 申请一个资源ID(`resourceId`),该资源ID用于后续所有操作;
109 | - 如果服务器部署配置为 `Private` ,那么默认情况下,仅允许 `本机` 访问创建资源;
110 |
111 | ### GET `service_url/:resourceId/list`
112 | - 列出当前资源下的符合条件的文件;
113 | - 可用查询参数:
114 | - `search`: 要过滤的关键字,默认为所有;
115 | - `orderBy`: 排序方式,可用:`time`(默认), `name`, `size` ;
116 | - `orderMode`: 排序模式,可用:`desc`(默认), `asc` ;
117 |
118 | ### POST `service_url/:resourceId/add`
119 | - 添加一个文件,需提供以下字段:
120 | - `name`: 文件名称;
121 | - `data`: 文件内容字段;
122 | - `share`: 是否共享文件,默认为 `false`
123 | - 当启用共享文件时,创建成功后会同时返回一个 `shareId` ,可根据这个 `shareId` 来访问资源,而不必暴露 `resourceId`
124 | - 访问方法:`http(s)://ip_or_host:port/share/shareId` ,如:
125 | - `http://192.168.10.10:8088/share/abc1234567890`
126 |
127 | ### GET `service_url/:resourceId/get/:path`
128 | - 获取(下载)一个文件
129 |
130 | ### POST `service_url/:resourceId/delete/:path`
131 | - 删除一个文件
132 |
133 | ### GET `service_url/share/:id`
134 | - 获取(下载)一个已共享的文件
--------------------------------------------------------------------------------
/src/controllers/storage.ts:
--------------------------------------------------------------------------------
1 | import * as restify from "restify";
2 | import App from "../app";
3 | import { Storage } from "../class/storage";
4 | import { EDeployType } from "../interface/common";
5 | import ERROR from "../interface/errorCodes";
6 |
7 | export class StorageController {
8 | public service: Storage;
9 | constructor(public app: App) {
10 | this.service = new Storage(app);
11 | if (app.config.isFirstTime) {
12 | this.service.create().then(result => {
13 | console.log(
14 | `\n疑似首次部署,已为您自动生成一个授权码: ${result} ,请妥善保管。`
15 | );
16 | });
17 | }
18 | }
19 |
20 | /**
21 | * 获取指定的资源
22 | * @param req
23 | * @param res
24 | * @param next
25 | */
26 | public get(req: restify.Request, res: restify.Response, next: restify.Next) {
27 | this.service
28 | .get(req.params.resourceId, req.params.path)
29 | .then(result => {
30 | res.send(200, result, {
31 | "Content-Type": "application/octet-stream",
32 | "Content-Disposition":
33 | "attachment; filename=" + (req.params.name || req.params.path)
34 | });
35 | })
36 | .catch(err => {
37 | res.json({
38 | error: err
39 | });
40 | }).finally(()=>{
41 | next();
42 | });
43 | }
44 |
45 | /**
46 | * 获取共享资源
47 | * @param req
48 | * @param res
49 | * @param next
50 | */
51 | public getShare(req: restify.Request, res: restify.Response, next: restify.Next) {
52 | this.service
53 | .getShare(req.params.id)
54 | .then(result => {
55 | res.send(200, result, {
56 | "Content-Type": "application/octet-stream",
57 | "Content-Disposition":
58 | "attachment; filename=" + (req.params.name || req.params.id)
59 | });
60 | })
61 | .catch(err => {
62 | res.json({
63 | error: err
64 | });
65 | }).finally(()=>{
66 | next();
67 | });
68 | }
69 |
70 | /**
71 | * 获取资源列表
72 | * @param req
73 | * @param res
74 | * @param next
75 | */
76 | public list(req: restify.Request, res: restify.Response, next: restify.Next) {
77 | this.service
78 | .list(
79 | req.params.resourceId,
80 | req.query.search,
81 | req.query.page,
82 | req.query.pageSize,
83 | req.query.orderBy,
84 | req.query.orderMode
85 | )
86 | .then(result => {
87 | res.json({
88 | data: result
89 | });
90 | })
91 | .catch(err => {
92 | res.json({
93 | error: err
94 | });
95 | }).finally(()=>{
96 | next();
97 | });
98 | }
99 |
100 | /**
101 | * 创建资源
102 | * @param req
103 | * @param res
104 | * @param next
105 | */
106 | public create(
107 | req: restify.Request,
108 | res: restify.Response,
109 | next: restify.Next
110 | ) {
111 | console.log("create", req.socket.remoteAddress);
112 | if (this.app.config.server.deployType === EDeployType.Private) {
113 | const whiteList = ["::1", "127.0.0.1", "localhost"];
114 |
115 | // 如果有定义白名单,不管是否已启用,都允许创建资源
116 | if (
117 | this.app.config.server.accessWhitelist &&
118 | this.app.config.server.accessWhitelist.length > 0
119 | ) {
120 | whiteList.push(...this.app.config.server.accessWhitelist);
121 | }
122 | if (!this.app.isWhitelist(req, whiteList)) {
123 | res.send(401, ERROR.PermissionDenied);
124 | return next();
125 | }
126 | }
127 |
128 | this.service
129 | .create()
130 | .then(result => {
131 | // 输出一下已创建的资源ID
132 | console.log("new id: %s", result);
133 | res.json({
134 | data: result
135 | });
136 | })
137 | .catch(err => {
138 | res.json({
139 | error: err
140 | });
141 | }).finally(()=>{
142 | next();
143 | });
144 | }
145 |
146 | /**
147 | * 增加资源
148 | * @param req
149 | * @param res
150 | * @param next
151 | */
152 | public add(req: restify.Request, res: restify.Response, next: restify.Next) {
153 | if (req.files && req.files.data) {
154 | this.service
155 | .add(req.params.resourceId, req.params.name, req.files.data.path, req.params.share)
156 | .then(result => {
157 | res.json({
158 | data: result
159 | });
160 | })
161 | .catch(err => {
162 | res.json({
163 | error: err
164 | });
165 | }).finally(()=>{
166 | next();
167 | });
168 | } else if (req.params.type == "dir") {
169 | this.service
170 | .addFolder(req.params.resourceId, req.params.name)
171 | .then(result => {
172 | res.json({
173 | data: result
174 | });
175 | })
176 | .catch(err => {
177 | res.json({
178 | error: err
179 | });
180 | }).finally(()=>{
181 | next();
182 | });
183 | } else {
184 | res.send(400, ERROR.InvalidRequest);
185 | next();
186 | }
187 | }
188 |
189 | /**
190 | * 删除指定的文件或目录
191 | * @param req
192 | * @param res
193 | * @param next
194 | */
195 | public delete(
196 | req: restify.Request,
197 | res: restify.Response,
198 | next: restify.Next
199 | ) {
200 | this.service
201 | .delete(req.params.resourceId, req.params.path)
202 | .then(result => {
203 | res.json({
204 | data: result
205 | });
206 | })
207 | .catch(err => {
208 | res.json({
209 | error: err
210 | });
211 | }).finally(()=>{
212 | next();
213 | });
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/src/class/storage.ts:
--------------------------------------------------------------------------------
1 | import * as PATH from "path";
2 | import * as FS from "fs";
3 | import * as CryptoJS from "crypto-js";
4 | import App from "../app";
5 | import {
6 | IStorageServiceConfig,
7 | IResourceOptions,
8 | EResourceOrderBy,
9 | EResourceOrderMode
10 | } from "../interface/common";
11 | import ERROR from "../interface/errorCodes";
12 |
13 | export class Storage {
14 | private rootPath: string = "";
15 | public config: IStorageServiceConfig = {
16 | dataPath: "data",
17 | configPath: "conf",
18 | rootPath: "storage",
19 | maxResource: 100,
20 | autoCleanOldResource: false
21 | };
22 |
23 | constructor(app: App) {
24 | this.config = Object.assign(this.config, app.config.storage);
25 | this.rootPath = PATH.resolve(app.rootPath, this.config.rootPath);
26 | }
27 |
28 | /**
29 | * 创建一个资源目录
30 | */
31 | public create(options?: IResourceOptions): Promise {
32 | return new Promise((resolve?: any, reject?: any) => {
33 | const id = this.getNewId();
34 | this.createConfig(id, options);
35 |
36 | resolve(id);
37 | });
38 | }
39 |
40 | /**
41 | * 创建资源配置信息
42 | * @param resourceId
43 | * @param options
44 | */
45 | private createConfig(resourceId: string, options?: IResourceOptions) {
46 | const configFile = this.getConfigFile(resourceId);
47 | const configPath = PATH.parse(configFile).dir;
48 | const dataPath = this.getDataDirectory(resourceId);
49 | FS.mkdirSync(configPath, { recursive: true });
50 | FS.mkdirSync(dataPath, { recursive: true });
51 | FS.writeFileSync(
52 | configFile,
53 | JSON.stringify(
54 | Object.assign({ authType: "none", resourceCount: 0 }, options)
55 | )
56 | );
57 | }
58 |
59 | private getConfigFile(resourceId: string): string {
60 | return PATH.join(
61 | this.rootPath,
62 | this.config.configPath,
63 | resourceId.substr(0, 1),
64 | `${resourceId}.json`
65 | );
66 | }
67 |
68 | private getConfig(resourceId: string): IResourceOptions {
69 | const path = this.getConfigFile(resourceId);
70 |
71 | const result = FS.readFileSync(path, "utf-8");
72 | return JSON.parse(result);
73 | }
74 |
75 | /**
76 | * 获取当前资源目录
77 | * @param resourceId
78 | */
79 | private getDataDirectory(resourceId: string): string {
80 | return PATH.join(
81 | this.rootPath,
82 | this.config.dataPath,
83 | resourceId.substr(0, 1),
84 | resourceId
85 | );
86 | }
87 |
88 | public get(resourceId: string, path: string): Promise {
89 | return new Promise((resolve?: any, reject?: any) => {
90 | if (!this.checkResourceId(resourceId)) {
91 | reject(ERROR.InvalidResourceId);
92 | return;
93 | }
94 |
95 | const currentDirectory = this.getDataDirectory(resourceId);
96 | const fullPath = PATH.join(currentDirectory, path);
97 |
98 | if (FS.existsSync(fullPath)) {
99 | FS.readFile(fullPath, (err, data) => {
100 | resolve(data);
101 | });
102 | } else {
103 | reject(ERROR.InvalidResourceName);
104 | }
105 | });
106 | }
107 |
108 | public getShare(shareId: string): Promise {
109 | return new Promise((resolve?: any, reject?: any) => {
110 | if (!this.config.sharePath) {
111 | reject(null);
112 | return;
113 | }
114 |
115 | const sharePath = PATH.join(this.config.sharePath, shareId);
116 |
117 | if (FS.existsSync(sharePath)) {
118 | const filePath = FS.readFileSync(sharePath);
119 | FS.readFile(filePath, (err, data) => {
120 | resolve(data);
121 | });
122 | } else {
123 | reject(ERROR.InvalidResourceId);
124 | }
125 | });
126 | }
127 |
128 | /**
129 | * 获取指定路径下的资源列表
130 | * @param path 路径
131 | * @param search 搜索关键字
132 | * @param page 页码
133 | * @param pageSize 需要显示的数量
134 | * @param orderBy 排序字段
135 | * @param orderMode 排序模式(asc, desc)
136 | */
137 | private getResourceList(
138 | path: string,
139 | search: string = "",
140 | page: number = 1,
141 | pageSize: number = 10,
142 | orderBy: EResourceOrderBy = EResourceOrderBy.time,
143 | orderMode: EResourceOrderMode = EResourceOrderMode.desc
144 | ) {
145 | const startIndex = (page - 1) * pageSize;
146 | return FS.readdirSync(path)
147 | .filter(name => {
148 | return name.indexOf(search) !== -1;
149 | })
150 | .map(name => {
151 | const stat = FS.statSync(PATH.join(path, name));
152 |
153 | return {
154 | name,
155 | time: stat.mtime.getTime(),
156 | type: stat.isDirectory() ? "directory" : "file",
157 | size: stat.size
158 | };
159 | })
160 | .sort((a, b) => {
161 | let v1, v2;
162 | switch (orderBy) {
163 | case EResourceOrderBy.name:
164 | v1 = a.name;
165 | v2 = b.name;
166 | break;
167 |
168 | case EResourceOrderBy.size:
169 | v1 = a.size;
170 | v2 = b.size;
171 | break;
172 |
173 | default:
174 | v1 = a.time;
175 | v2 = b.time;
176 | break;
177 | }
178 |
179 | if (orderMode === EResourceOrderMode.desc) {
180 | return v1.toString().localeCompare(v2) == 1 ? -1 : 1;
181 | } else {
182 | return v1.toString().localeCompare(v2);
183 | }
184 | })
185 | .slice(startIndex, pageSize === -1 ? undefined : startIndex + pageSize);
186 | }
187 |
188 | public list(
189 | resourceId: string,
190 | search: string = "",
191 | page: number = 1,
192 | pageSize: number = 10,
193 | orderBy: EResourceOrderBy = EResourceOrderBy.time,
194 | orderMode: EResourceOrderMode = EResourceOrderMode.desc
195 | ): Promise {
196 | return new Promise((resolve?: any, reject?: any) => {
197 | if (!this.checkResourceId(resourceId)) {
198 | reject(ERROR.InvalidResourceId);
199 | return;
200 | }
201 | const currentDirectory = this.getDataDirectory(resourceId);
202 | const result = this.getResourceList(
203 | currentDirectory,
204 | search,
205 | page,
206 | pageSize,
207 | orderBy,
208 | orderMode
209 | );
210 |
211 | resolve(result);
212 | });
213 | }
214 |
215 | /**
216 | * 删除指定的文件或目录
217 | */
218 | public delete(resourceId: string, path: string): Promise {
219 | return new Promise((resolve?: any, reject?: any) => {
220 | if (!this.checkResourceId(resourceId)) {
221 | reject(ERROR.InvalidResourceId);
222 | return;
223 | }
224 |
225 | if (!path) {
226 | reject(ERROR.InvalidResourcePath);
227 | return;
228 | }
229 |
230 | const currentDirectory = this.getDataDirectory(resourceId);
231 | const fullPath = PATH.join(currentDirectory, path);
232 | const stat = FS.statSync(fullPath);
233 |
234 | if (stat.isDirectory()) {
235 | FS.rmdir(fullPath, error => {
236 | if (!error) {
237 | this.resourceCountDecrement(resourceId);
238 | resolve(true);
239 | } else {
240 | reject(error);
241 | }
242 | });
243 | } else {
244 | FS.unlink(fullPath, error => {
245 | if (!error) {
246 | this.resourceCountDecrement(resourceId);
247 | resolve(true);
248 | } else {
249 | reject(error);
250 | }
251 | });
252 | }
253 | });
254 | }
255 |
256 | /**
257 | * 添加文件
258 | * @param resourceId
259 | * @param name
260 | * @param data
261 | */
262 | public add(resourceId: string, name: string, data: any, share: boolean=false): Promise {
263 | return new Promise((resolve?: any, reject?: any) => {
264 | if (!this.checkResourceId(resourceId)) {
265 | reject(ERROR.InvalidResourceId);
266 | return;
267 | }
268 |
269 | if (!name) {
270 | reject(ERROR.InvalidResourceName);
271 | return;
272 | }
273 |
274 | if (!data) {
275 | reject(ERROR.InvalidResourceData);
276 | return;
277 | }
278 |
279 | const config = this.getConfig(resourceId);
280 | if (config.resourceCount === undefined) {
281 | this.resetResourceCount(resourceId);
282 | }
283 |
284 | this.cleanOldResource(resourceId);
285 |
286 | // 替换非法文件名称
287 | name = name.replace(/(<|>|\/|\||\\|\:|\"|\*|\?)/g, "_");
288 |
289 | const currentDirectory = this.getDataDirectory(resourceId);
290 | const path = PATH.join(currentDirectory, name);
291 |
292 | try {
293 | if (PATH.isAbsolute(data)) {
294 | FS.renameSync(data, path)
295 | } else {
296 | FS.writeFileSync(path, data);
297 | }
298 |
299 | this.resourceCountIncrement(resourceId);
300 |
301 | // 是否共享
302 | if (share && this.config.sharePath) {
303 | const shareId = this.getNewId();
304 | const sharePath = PATH.join(this.config.sharePath, shareId);
305 | FS.writeFileSync(sharePath, path);
306 | resolve({
307 | shareId
308 | })
309 | return;
310 | }
311 |
312 | resolve(true);
313 | } catch (error) {
314 | reject(error)
315 | }
316 | });
317 | }
318 |
319 | public addFolder(resourceId: string, path: string): Promise {
320 | return new Promise((resolve?: any, reject?: any) => {
321 | if (!this.checkResourceId(resourceId)) {
322 | reject(ERROR.InvalidResourceId);
323 | return;
324 | }
325 |
326 | if (!path) {
327 | reject(ERROR.InvalidResourcePath);
328 | return;
329 | }
330 |
331 | const currentDirectory = this.getDataDirectory(resourceId);
332 | const fullPath = PATH.join(currentDirectory, path);
333 |
334 | FS.mkdirSync(fullPath, { recursive: true });
335 |
336 | resolve(true);
337 | });
338 | }
339 |
340 | public checkResourceId(resourceId: string): boolean {
341 | if (/^[a-z0-9]{32}$/.test(resourceId)) {
342 | return FS.existsSync(this.getDataDirectory(resourceId));
343 | }
344 | return false;
345 | }
346 |
347 | private getNewId() {
348 | const chars =
349 | "abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKMNOPQRSTUVWXYZ";
350 | const maxLength = chars.length;
351 | const result: string[] = [];
352 | for (let i = 0; i < 32; i++) {
353 | result.push(chars.charAt(Math.floor(Math.random() * maxLength)));
354 | }
355 |
356 | return CryptoJS.MD5(
357 | new Date().getTime().toString() + result.join("")
358 | ).toString();
359 | }
360 |
361 | /**
362 | * 重置指定资源的文件数量(不包含子目录)
363 | * @param resourceId
364 | */
365 | public resetResourceCount(resourceId: string) {
366 | const config = this.getConfig(resourceId);
367 | if (config.resourceCount === undefined) {
368 | config.resourceCount = 0;
369 | }
370 |
371 | const configFile = this.getConfigFile(resourceId);
372 |
373 | const currentDirectory = this.getDataDirectory(resourceId);
374 |
375 | config.resourceCount = FS.readdirSync(currentDirectory, {
376 | withFileTypes: true
377 | }).filter(item => {
378 | return item.isFile();
379 | }).length;
380 |
381 | FS.writeFileSync(configFile, JSON.stringify(config));
382 | }
383 |
384 | public resourceCountIncrement(resourceId: string): number {
385 | const config = this.getConfig(resourceId);
386 | if (config.resourceCount === undefined) {
387 | config.resourceCount = 0;
388 | }
389 |
390 | const configFile = this.getConfigFile(resourceId);
391 |
392 | config.resourceCount++;
393 |
394 | FS.writeFileSync(configFile, JSON.stringify(config));
395 |
396 | return config.resourceCount;
397 | }
398 |
399 | public resourceCountDecrement(resourceId: string, count: number = 1): number {
400 | const config = this.getConfig(resourceId);
401 | if (config.resourceCount === undefined) {
402 | config.resourceCount = 0;
403 | }
404 |
405 | const configFile = this.getConfigFile(resourceId);
406 |
407 | config.resourceCount = config.resourceCount - count;
408 | if (config.resourceCount < 0) {
409 | config.resourceCount = 0;
410 | }
411 |
412 | FS.writeFileSync(configFile, JSON.stringify(config));
413 |
414 | return config.resourceCount;
415 | }
416 |
417 | /**
418 | * 清理老文件
419 | * @param resourceId
420 | */
421 | private cleanOldResource(resourceId: string) {
422 | if (!this.config.maxResource || !this.config.autoCleanOldResource) {
423 | return;
424 | }
425 |
426 | const config = this.getConfig(resourceId);
427 |
428 | if (!config.resourceCount) {
429 | return;
430 | }
431 |
432 | // 如果超出最大数量,则删除最老的文件
433 | if (config.resourceCount >= this.config.maxResource) {
434 | const cleanCount = config.resourceCount - this.config.maxResource + 1;
435 | const currentDirectory = this.getDataDirectory(resourceId);
436 | const list = this.getResourceList(
437 | currentDirectory,
438 | "",
439 | 1,
440 | cleanCount,
441 | EResourceOrderBy.time,
442 | EResourceOrderMode.asc
443 | );
444 |
445 | if (list.length > 0) {
446 | list.forEach(item => {
447 | const fullPath = PATH.join(currentDirectory, item.name);
448 | FS.unlinkSync(fullPath);
449 | });
450 |
451 | this.resourceCountDecrement(resourceId, cleanCount);
452 | }
453 | }
454 | }
455 | }
456 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | body-parser:
12 | specifier: ^2.2.0
13 | version: 2.2.0
14 | crypto-js:
15 | specifier: ^4.2.0
16 | version: 4.2.0
17 | extend:
18 | specifier: ^3.0.2
19 | version: 3.0.2
20 | request-ip:
21 | specifier: ^3.3.0
22 | version: 3.3.0
23 | restify:
24 | specifier: ^11.1.0
25 | version: 11.1.0
26 | devDependencies:
27 | '@types/crypto-js':
28 | specifier: ^4.2.2
29 | version: 4.2.2
30 | '@types/extend':
31 | specifier: ^3.0.4
32 | version: 3.0.4
33 | '@types/node':
34 | specifier: ^22.14.0
35 | version: 22.14.0
36 | '@types/request-ip':
37 | specifier: ^0.0.41
38 | version: 0.0.41
39 | '@types/restify':
40 | specifier: ^8.5.12
41 | version: 8.5.12
42 | ts-node:
43 | specifier: ^10.9.2
44 | version: 10.9.2(@types/node@22.14.0)(typescript@5.8.3)
45 | typescript:
46 | specifier: ^5.8.3
47 | version: 5.8.3
48 |
49 | packages:
50 |
51 | '@cspotcode/source-map-support@0.8.1':
52 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
53 | engines: {node: '>=12'}
54 |
55 | '@jridgewell/resolve-uri@3.1.2':
56 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
57 | engines: {node: '>=6.0.0'}
58 |
59 | '@jridgewell/sourcemap-codec@1.5.0':
60 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
61 |
62 | '@jridgewell/trace-mapping@0.3.9':
63 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
64 |
65 | '@netflix/nerror@1.1.3':
66 | resolution: {integrity: sha512-b+MGNyP9/LXkapreJzNUzcvuzZslj/RGgdVVJ16P2wSlYatfLycPObImqVJSmNAdyeShvNeM/pl3sVZsObFueg==}
67 |
68 | '@tsconfig/node10@1.0.11':
69 | resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
70 |
71 | '@tsconfig/node12@1.0.11':
72 | resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
73 |
74 | '@tsconfig/node14@1.0.3':
75 | resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
76 |
77 | '@tsconfig/node16@1.0.4':
78 | resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
79 |
80 | '@types/bunyan@1.8.11':
81 | resolution: {integrity: sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==}
82 |
83 | '@types/crypto-js@4.2.2':
84 | resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
85 |
86 | '@types/extend@3.0.4':
87 | resolution: {integrity: sha512-ArMouDUTJEz1SQRpFsT2rIw7DeqICFv5aaVzLSIYMYQSLcwcGOfT3VyglQs/p7K3F7fT4zxr0NWxYZIdifD6dA==}
88 |
89 | '@types/formidable@1.2.8':
90 | resolution: {integrity: sha512-6psvrUy5VDYb+yaPJReF1WrRsz+FBwyJutK9Twz1Efa27tm07bARNIkK2B8ZPWq80dXqpKfrxTO96xrtPp+AuA==}
91 |
92 | '@types/node@22.14.0':
93 | resolution: {integrity: sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==}
94 |
95 | '@types/request-ip@0.0.41':
96 | resolution: {integrity: sha512-Qzz0PM2nSZej4lsLzzNfADIORZhhxO7PED0fXpg4FjXiHuJ/lMyUg+YFF5q8x9HPZH3Gl6N+NOM8QZjItNgGKg==}
97 |
98 | '@types/restify@8.5.12':
99 | resolution: {integrity: sha512-tW9y4O/B0gNIhin/88PzLTPgolkzOOrFK0IfgdiiYjGgjXI+PDTwp7QThhQy0p0l5FuNy59NW2PXU3Qx3r5cOQ==}
100 |
101 | '@types/spdy@3.4.9':
102 | resolution: {integrity: sha512-ZYGzQrZX6j4GEy9x9+e4bjWOPOiZqFPm/3GnZ9xS0SMJqs+FbNiF6hBzr8EjSF2Z6TFY/PzUWOswUiRcZxW3FQ==}
103 |
104 | abort-controller@3.0.0:
105 | resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
106 | engines: {node: '>=6.5'}
107 |
108 | acorn-walk@8.3.4:
109 | resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
110 | engines: {node: '>=0.4.0'}
111 |
112 | acorn@8.14.1:
113 | resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
114 | engines: {node: '>=0.4.0'}
115 | hasBin: true
116 |
117 | arg@4.1.3:
118 | resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
119 |
120 | asn1@0.2.6:
121 | resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
122 |
123 | assert-plus@1.0.0:
124 | resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
125 | engines: {node: '>=0.8'}
126 |
127 | atomic-sleep@1.0.0:
128 | resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==}
129 | engines: {node: '>=8.0.0'}
130 |
131 | base64-js@1.5.1:
132 | resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
133 |
134 | bcrypt-pbkdf@1.0.2:
135 | resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
136 |
137 | body-parser@2.2.0:
138 | resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
139 | engines: {node: '>=18'}
140 |
141 | buffer@6.0.3:
142 | resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
143 |
144 | bytes@3.1.2:
145 | resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
146 | engines: {node: '>= 0.8'}
147 |
148 | call-bind-apply-helpers@1.0.2:
149 | resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
150 | engines: {node: '>= 0.4'}
151 |
152 | call-bound@1.0.4:
153 | resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
154 | engines: {node: '>= 0.4'}
155 |
156 | content-type@1.0.5:
157 | resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
158 | engines: {node: '>= 0.6'}
159 |
160 | core-util-is@1.0.2:
161 | resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
162 |
163 | core-util-is@1.0.3:
164 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
165 |
166 | create-require@1.1.1:
167 | resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
168 |
169 | crypto-js@4.2.0:
170 | resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
171 |
172 | csv-generate@4.4.2:
173 | resolution: {integrity: sha512-W6nVsf+rz0J3yo9FOjeer7tmzBJKaTTxf7K0uw6GZgRocZYPVpuSWWa5/aoWWrjQZj4/oNIKTYapOM7hiNjVMA==}
174 |
175 | csv-parse@5.6.0:
176 | resolution: {integrity: sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==}
177 |
178 | csv-stringify@6.5.2:
179 | resolution: {integrity: sha512-RFPahj0sXcmUyjrObAK+DOWtMvMIFV328n4qZJhgX3x2RqkQgOTU2mCUmiFR0CzM6AzChlRSUErjiJeEt8BaQA==}
180 |
181 | csv@6.3.11:
182 | resolution: {integrity: sha512-a8bhT76Q546jOElHcTrkzWY7Py925mfLO/jqquseH61ThOebYwOjLbWHBqdRB4K1VpU36sTyIei6Jwj7QdEZ7g==}
183 | engines: {node: '>= 0.1.90'}
184 |
185 | dashdash@1.14.1:
186 | resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
187 | engines: {node: '>=0.10'}
188 |
189 | debug@2.6.9:
190 | resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
191 | peerDependencies:
192 | supports-color: '*'
193 | peerDependenciesMeta:
194 | supports-color:
195 | optional: true
196 |
197 | debug@4.4.0:
198 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
199 | engines: {node: '>=6.0'}
200 | peerDependencies:
201 | supports-color: '*'
202 | peerDependenciesMeta:
203 | supports-color:
204 | optional: true
205 |
206 | depd@2.0.0:
207 | resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
208 | engines: {node: '>= 0.8'}
209 |
210 | destroy@1.2.0:
211 | resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
212 | engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
213 |
214 | detect-node@2.1.0:
215 | resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
216 |
217 | diff@4.0.2:
218 | resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
219 | engines: {node: '>=0.3.1'}
220 |
221 | dtrace-provider@0.8.8:
222 | resolution: {integrity: sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==}
223 | engines: {node: '>=0.10'}
224 |
225 | dunder-proto@1.0.1:
226 | resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
227 | engines: {node: '>= 0.4'}
228 |
229 | ecc-jsbn@0.1.2:
230 | resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
231 |
232 | ee-first@1.1.1:
233 | resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
234 |
235 | encodeurl@1.0.2:
236 | resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
237 | engines: {node: '>= 0.8'}
238 |
239 | es-define-property@1.0.1:
240 | resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
241 | engines: {node: '>= 0.4'}
242 |
243 | es-errors@1.3.0:
244 | resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
245 | engines: {node: '>= 0.4'}
246 |
247 | es-object-atoms@1.1.1:
248 | resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
249 | engines: {node: '>= 0.4'}
250 |
251 | escape-html@1.0.3:
252 | resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
253 |
254 | escape-regexp-component@1.0.2:
255 | resolution: {integrity: sha512-B0yxafj1D1ZTNEHkFoQxz4iboZSfaZHhaNhIug7GcUCL4ZUrVSJZTmWUAkPOFaYDfi3RNT9XM082TuGE6jpmiQ==}
256 |
257 | etag@1.8.1:
258 | resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
259 | engines: {node: '>= 0.6'}
260 |
261 | event-target-shim@5.0.1:
262 | resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
263 | engines: {node: '>=6'}
264 |
265 | events@3.3.0:
266 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
267 | engines: {node: '>=0.8.x'}
268 |
269 | ewma@2.0.1:
270 | resolution: {integrity: sha512-MYYK17A76cuuyvkR7MnqLW4iFYPEi5Isl2qb8rXiWpLiwFS9dxW/rncuNnjjgSENuVqZQkIuR4+DChVL4g1lnw==}
271 |
272 | extend@3.0.2:
273 | resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
274 |
275 | extsprintf@1.3.0:
276 | resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
277 | engines: {'0': node >=0.6.0}
278 |
279 | extsprintf@1.4.1:
280 | resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==}
281 | engines: {'0': node >=0.6.0}
282 |
283 | fast-decode-uri-component@1.0.1:
284 | resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
285 |
286 | fast-deep-equal@3.1.3:
287 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
288 |
289 | fast-querystring@1.1.2:
290 | resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
291 |
292 | fast-redact@3.5.0:
293 | resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
294 | engines: {node: '>=6'}
295 |
296 | find-my-way@7.7.0:
297 | resolution: {integrity: sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==}
298 | engines: {node: '>=14'}
299 |
300 | formidable@1.2.6:
301 | resolution: {integrity: sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==}
302 | deprecated: 'Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau'
303 |
304 | fresh@0.5.2:
305 | resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
306 | engines: {node: '>= 0.6'}
307 |
308 | function-bind@1.1.2:
309 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
310 |
311 | get-intrinsic@1.3.0:
312 | resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
313 | engines: {node: '>= 0.4'}
314 |
315 | get-proto@1.0.1:
316 | resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
317 | engines: {node: '>= 0.4'}
318 |
319 | getpass@0.1.7:
320 | resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
321 |
322 | gopd@1.2.0:
323 | resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
324 | engines: {node: '>= 0.4'}
325 |
326 | handle-thing@2.0.1:
327 | resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==}
328 |
329 | has-symbols@1.1.0:
330 | resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
331 | engines: {node: '>= 0.4'}
332 |
333 | hasown@2.0.2:
334 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
335 | engines: {node: '>= 0.4'}
336 |
337 | hpack.js@2.1.6:
338 | resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==}
339 |
340 | http-deceiver@1.2.7:
341 | resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==}
342 |
343 | http-errors@2.0.0:
344 | resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
345 | engines: {node: '>= 0.8'}
346 |
347 | http-signature@1.4.0:
348 | resolution: {integrity: sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==}
349 | engines: {node: '>=0.10'}
350 |
351 | iconv-lite@0.6.3:
352 | resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
353 | engines: {node: '>=0.10.0'}
354 |
355 | ieee754@1.2.1:
356 | resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
357 |
358 | inherits@2.0.4:
359 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
360 |
361 | isarray@1.0.0:
362 | resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
363 |
364 | jsbn@0.1.1:
365 | resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
366 |
367 | json-schema@0.4.0:
368 | resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
369 |
370 | jsprim@2.0.2:
371 | resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==}
372 | engines: {'0': node >=0.6.0}
373 |
374 | lodash@4.17.21:
375 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
376 |
377 | lru-cache@7.18.3:
378 | resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
379 | engines: {node: '>=12'}
380 |
381 | make-error@1.3.6:
382 | resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
383 |
384 | math-intrinsics@1.1.0:
385 | resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
386 | engines: {node: '>= 0.4'}
387 |
388 | media-typer@1.1.0:
389 | resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
390 | engines: {node: '>= 0.8'}
391 |
392 | mime-db@1.54.0:
393 | resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
394 | engines: {node: '>= 0.6'}
395 |
396 | mime-types@3.0.1:
397 | resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
398 | engines: {node: '>= 0.6'}
399 |
400 | mime@1.6.0:
401 | resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
402 | engines: {node: '>=4'}
403 | hasBin: true
404 |
405 | mime@3.0.0:
406 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==}
407 | engines: {node: '>=10.0.0'}
408 | hasBin: true
409 |
410 | minimalistic-assert@1.0.1:
411 | resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
412 |
413 | ms@2.0.0:
414 | resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
415 |
416 | ms@2.1.3:
417 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
418 |
419 | nan@2.22.2:
420 | resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==}
421 |
422 | negotiator@0.6.4:
423 | resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
424 | engines: {node: '>= 0.6'}
425 |
426 | object-inspect@1.13.4:
427 | resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
428 | engines: {node: '>= 0.4'}
429 |
430 | obuf@1.1.2:
431 | resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
432 |
433 | on-exit-leak-free@2.1.2:
434 | resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
435 | engines: {node: '>=14.0.0'}
436 |
437 | on-finished@2.4.1:
438 | resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
439 | engines: {node: '>= 0.8'}
440 |
441 | once@1.4.0:
442 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
443 |
444 | pidusage@3.0.2:
445 | resolution: {integrity: sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==}
446 | engines: {node: '>=10'}
447 |
448 | pino-abstract-transport@1.2.0:
449 | resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==}
450 |
451 | pino-std-serializers@6.2.2:
452 | resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
453 |
454 | pino@8.21.0:
455 | resolution: {integrity: sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==}
456 | hasBin: true
457 |
458 | process-nextick-args@2.0.1:
459 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
460 |
461 | process-warning@3.0.0:
462 | resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==}
463 |
464 | process@0.11.10:
465 | resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
466 | engines: {node: '>= 0.6.0'}
467 |
468 | qs@6.14.0:
469 | resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
470 | engines: {node: '>=0.6'}
471 |
472 | quick-format-unescaped@4.0.4:
473 | resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
474 |
475 | range-parser@1.2.1:
476 | resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
477 | engines: {node: '>= 0.6'}
478 |
479 | raw-body@3.0.0:
480 | resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==}
481 | engines: {node: '>= 0.8'}
482 |
483 | readable-stream@2.3.8:
484 | resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
485 |
486 | readable-stream@3.6.2:
487 | resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
488 | engines: {node: '>= 6'}
489 |
490 | readable-stream@4.7.0:
491 | resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==}
492 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
493 |
494 | real-require@0.2.0:
495 | resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
496 | engines: {node: '>= 12.13.0'}
497 |
498 | request-ip@3.3.0:
499 | resolution: {integrity: sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==}
500 |
501 | restify-errors@8.0.2:
502 | resolution: {integrity: sha512-UsXUVQo7M26xoQzeUcZQ0+H8L2t9DGzrXcAgR3WB/1vnbl+UdI4tZ1PqYsN+sS5WnqHKZ0Xy9w0CKf83bbrwYA==}
503 |
504 | restify@11.1.0:
505 | resolution: {integrity: sha512-ng7uBlj4wpIpshhAjNNSd6JG5Eg32+zgync2gG8OlF4e2xzIflZo54GJ/qLs765OtQaVU+uJPcNOL5Atm2F/dg==}
506 | engines: {node: '>=10.0.0'}
507 | hasBin: true
508 |
509 | ret@0.2.2:
510 | resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==}
511 | engines: {node: '>=4'}
512 |
513 | safe-buffer@5.1.2:
514 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
515 |
516 | safe-buffer@5.2.1:
517 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
518 |
519 | safe-json-stringify@1.2.0:
520 | resolution: {integrity: sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==}
521 |
522 | safe-regex2@2.0.0:
523 | resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==}
524 |
525 | safe-stable-stringify@2.5.0:
526 | resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
527 | engines: {node: '>=10'}
528 |
529 | safer-buffer@2.1.2:
530 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
531 |
532 | select-hose@2.0.0:
533 | resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==}
534 |
535 | semver@7.7.1:
536 | resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
537 | engines: {node: '>=10'}
538 | hasBin: true
539 |
540 | send@0.18.0:
541 | resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
542 | engines: {node: '>= 0.8.0'}
543 |
544 | setprototypeof@1.2.0:
545 | resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
546 |
547 | side-channel-list@1.0.0:
548 | resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
549 | engines: {node: '>= 0.4'}
550 |
551 | side-channel-map@1.0.1:
552 | resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
553 | engines: {node: '>= 0.4'}
554 |
555 | side-channel-weakmap@1.0.2:
556 | resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
557 | engines: {node: '>= 0.4'}
558 |
559 | side-channel@1.1.0:
560 | resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
561 | engines: {node: '>= 0.4'}
562 |
563 | sonic-boom@3.8.1:
564 | resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==}
565 |
566 | spdy-transport@3.0.0:
567 | resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==}
568 |
569 | spdy@4.0.2:
570 | resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==}
571 | engines: {node: '>=6.0.0'}
572 |
573 | split2@4.2.0:
574 | resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
575 | engines: {node: '>= 10.x'}
576 |
577 | sshpk@1.18.0:
578 | resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
579 | engines: {node: '>=0.10.0'}
580 | hasBin: true
581 |
582 | statuses@2.0.1:
583 | resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
584 | engines: {node: '>= 0.8'}
585 |
586 | stream-transform@3.3.3:
587 | resolution: {integrity: sha512-dALXrXe+uq4aO5oStdHKlfCM/b3NBdouigvxVPxCdrMRAU6oHh3KNss20VbTPQNQmjAHzZGKGe66vgwegFEIog==}
588 |
589 | string_decoder@1.1.1:
590 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
591 |
592 | string_decoder@1.3.0:
593 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
594 |
595 | thread-stream@2.7.0:
596 | resolution: {integrity: sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==}
597 |
598 | toidentifier@1.0.1:
599 | resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
600 | engines: {node: '>=0.6'}
601 |
602 | ts-node@10.9.2:
603 | resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
604 | hasBin: true
605 | peerDependencies:
606 | '@swc/core': '>=1.2.50'
607 | '@swc/wasm': '>=1.2.50'
608 | '@types/node': '*'
609 | typescript: '>=2.7'
610 | peerDependenciesMeta:
611 | '@swc/core':
612 | optional: true
613 | '@swc/wasm':
614 | optional: true
615 |
616 | tweetnacl@0.14.5:
617 | resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
618 |
619 | type-is@2.0.1:
620 | resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
621 | engines: {node: '>= 0.6'}
622 |
623 | typescript@5.8.3:
624 | resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
625 | engines: {node: '>=14.17'}
626 | hasBin: true
627 |
628 | undici-types@6.21.0:
629 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
630 |
631 | unpipe@1.0.0:
632 | resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
633 | engines: {node: '>= 0.8'}
634 |
635 | util-deprecate@1.0.2:
636 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
637 |
638 | uuid@9.0.1:
639 | resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
640 | hasBin: true
641 |
642 | v8-compile-cache-lib@3.0.1:
643 | resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
644 |
645 | vasync@2.2.1:
646 | resolution: {integrity: sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==}
647 | engines: {'0': node >=0.6.0}
648 |
649 | verror@1.10.0:
650 | resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
651 | engines: {'0': node >=0.6.0}
652 |
653 | wbuf@1.7.3:
654 | resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==}
655 |
656 | wrappy@1.0.2:
657 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
658 |
659 | yn@3.1.1:
660 | resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
661 | engines: {node: '>=6'}
662 |
663 | snapshots:
664 |
665 | '@cspotcode/source-map-support@0.8.1':
666 | dependencies:
667 | '@jridgewell/trace-mapping': 0.3.9
668 |
669 | '@jridgewell/resolve-uri@3.1.2': {}
670 |
671 | '@jridgewell/sourcemap-codec@1.5.0': {}
672 |
673 | '@jridgewell/trace-mapping@0.3.9':
674 | dependencies:
675 | '@jridgewell/resolve-uri': 3.1.2
676 | '@jridgewell/sourcemap-codec': 1.5.0
677 |
678 | '@netflix/nerror@1.1.3':
679 | dependencies:
680 | assert-plus: 1.0.0
681 | extsprintf: 1.4.1
682 | lodash: 4.17.21
683 |
684 | '@tsconfig/node10@1.0.11': {}
685 |
686 | '@tsconfig/node12@1.0.11': {}
687 |
688 | '@tsconfig/node14@1.0.3': {}
689 |
690 | '@tsconfig/node16@1.0.4': {}
691 |
692 | '@types/bunyan@1.8.11':
693 | dependencies:
694 | '@types/node': 22.14.0
695 |
696 | '@types/crypto-js@4.2.2': {}
697 |
698 | '@types/extend@3.0.4': {}
699 |
700 | '@types/formidable@1.2.8':
701 | dependencies:
702 | '@types/node': 22.14.0
703 |
704 | '@types/node@22.14.0':
705 | dependencies:
706 | undici-types: 6.21.0
707 |
708 | '@types/request-ip@0.0.41':
709 | dependencies:
710 | '@types/node': 22.14.0
711 |
712 | '@types/restify@8.5.12':
713 | dependencies:
714 | '@types/bunyan': 1.8.11
715 | '@types/formidable': 1.2.8
716 | '@types/node': 22.14.0
717 | '@types/spdy': 3.4.9
718 |
719 | '@types/spdy@3.4.9':
720 | dependencies:
721 | '@types/node': 22.14.0
722 |
723 | abort-controller@3.0.0:
724 | dependencies:
725 | event-target-shim: 5.0.1
726 |
727 | acorn-walk@8.3.4:
728 | dependencies:
729 | acorn: 8.14.1
730 |
731 | acorn@8.14.1: {}
732 |
733 | arg@4.1.3: {}
734 |
735 | asn1@0.2.6:
736 | dependencies:
737 | safer-buffer: 2.1.2
738 |
739 | assert-plus@1.0.0: {}
740 |
741 | atomic-sleep@1.0.0: {}
742 |
743 | base64-js@1.5.1: {}
744 |
745 | bcrypt-pbkdf@1.0.2:
746 | dependencies:
747 | tweetnacl: 0.14.5
748 |
749 | body-parser@2.2.0:
750 | dependencies:
751 | bytes: 3.1.2
752 | content-type: 1.0.5
753 | debug: 4.4.0
754 | http-errors: 2.0.0
755 | iconv-lite: 0.6.3
756 | on-finished: 2.4.1
757 | qs: 6.14.0
758 | raw-body: 3.0.0
759 | type-is: 2.0.1
760 | transitivePeerDependencies:
761 | - supports-color
762 |
763 | buffer@6.0.3:
764 | dependencies:
765 | base64-js: 1.5.1
766 | ieee754: 1.2.1
767 |
768 | bytes@3.1.2: {}
769 |
770 | call-bind-apply-helpers@1.0.2:
771 | dependencies:
772 | es-errors: 1.3.0
773 | function-bind: 1.1.2
774 |
775 | call-bound@1.0.4:
776 | dependencies:
777 | call-bind-apply-helpers: 1.0.2
778 | get-intrinsic: 1.3.0
779 |
780 | content-type@1.0.5: {}
781 |
782 | core-util-is@1.0.2: {}
783 |
784 | core-util-is@1.0.3: {}
785 |
786 | create-require@1.1.1: {}
787 |
788 | crypto-js@4.2.0: {}
789 |
790 | csv-generate@4.4.2: {}
791 |
792 | csv-parse@5.6.0: {}
793 |
794 | csv-stringify@6.5.2: {}
795 |
796 | csv@6.3.11:
797 | dependencies:
798 | csv-generate: 4.4.2
799 | csv-parse: 5.6.0
800 | csv-stringify: 6.5.2
801 | stream-transform: 3.3.3
802 |
803 | dashdash@1.14.1:
804 | dependencies:
805 | assert-plus: 1.0.0
806 |
807 | debug@2.6.9:
808 | dependencies:
809 | ms: 2.0.0
810 |
811 | debug@4.4.0:
812 | dependencies:
813 | ms: 2.1.3
814 |
815 | depd@2.0.0: {}
816 |
817 | destroy@1.2.0: {}
818 |
819 | detect-node@2.1.0: {}
820 |
821 | diff@4.0.2: {}
822 |
823 | dtrace-provider@0.8.8:
824 | dependencies:
825 | nan: 2.22.2
826 | optional: true
827 |
828 | dunder-proto@1.0.1:
829 | dependencies:
830 | call-bind-apply-helpers: 1.0.2
831 | es-errors: 1.3.0
832 | gopd: 1.2.0
833 |
834 | ecc-jsbn@0.1.2:
835 | dependencies:
836 | jsbn: 0.1.1
837 | safer-buffer: 2.1.2
838 |
839 | ee-first@1.1.1: {}
840 |
841 | encodeurl@1.0.2: {}
842 |
843 | es-define-property@1.0.1: {}
844 |
845 | es-errors@1.3.0: {}
846 |
847 | es-object-atoms@1.1.1:
848 | dependencies:
849 | es-errors: 1.3.0
850 |
851 | escape-html@1.0.3: {}
852 |
853 | escape-regexp-component@1.0.2: {}
854 |
855 | etag@1.8.1: {}
856 |
857 | event-target-shim@5.0.1: {}
858 |
859 | events@3.3.0: {}
860 |
861 | ewma@2.0.1:
862 | dependencies:
863 | assert-plus: 1.0.0
864 |
865 | extend@3.0.2: {}
866 |
867 | extsprintf@1.3.0: {}
868 |
869 | extsprintf@1.4.1: {}
870 |
871 | fast-decode-uri-component@1.0.1: {}
872 |
873 | fast-deep-equal@3.1.3: {}
874 |
875 | fast-querystring@1.1.2:
876 | dependencies:
877 | fast-decode-uri-component: 1.0.1
878 |
879 | fast-redact@3.5.0: {}
880 |
881 | find-my-way@7.7.0:
882 | dependencies:
883 | fast-deep-equal: 3.1.3
884 | fast-querystring: 1.1.2
885 | safe-regex2: 2.0.0
886 |
887 | formidable@1.2.6: {}
888 |
889 | fresh@0.5.2: {}
890 |
891 | function-bind@1.1.2: {}
892 |
893 | get-intrinsic@1.3.0:
894 | dependencies:
895 | call-bind-apply-helpers: 1.0.2
896 | es-define-property: 1.0.1
897 | es-errors: 1.3.0
898 | es-object-atoms: 1.1.1
899 | function-bind: 1.1.2
900 | get-proto: 1.0.1
901 | gopd: 1.2.0
902 | has-symbols: 1.1.0
903 | hasown: 2.0.2
904 | math-intrinsics: 1.1.0
905 |
906 | get-proto@1.0.1:
907 | dependencies:
908 | dunder-proto: 1.0.1
909 | es-object-atoms: 1.1.1
910 |
911 | getpass@0.1.7:
912 | dependencies:
913 | assert-plus: 1.0.0
914 |
915 | gopd@1.2.0: {}
916 |
917 | handle-thing@2.0.1: {}
918 |
919 | has-symbols@1.1.0: {}
920 |
921 | hasown@2.0.2:
922 | dependencies:
923 | function-bind: 1.1.2
924 |
925 | hpack.js@2.1.6:
926 | dependencies:
927 | inherits: 2.0.4
928 | obuf: 1.1.2
929 | readable-stream: 2.3.8
930 | wbuf: 1.7.3
931 |
932 | http-deceiver@1.2.7: {}
933 |
934 | http-errors@2.0.0:
935 | dependencies:
936 | depd: 2.0.0
937 | inherits: 2.0.4
938 | setprototypeof: 1.2.0
939 | statuses: 2.0.1
940 | toidentifier: 1.0.1
941 |
942 | http-signature@1.4.0:
943 | dependencies:
944 | assert-plus: 1.0.0
945 | jsprim: 2.0.2
946 | sshpk: 1.18.0
947 |
948 | iconv-lite@0.6.3:
949 | dependencies:
950 | safer-buffer: 2.1.2
951 |
952 | ieee754@1.2.1: {}
953 |
954 | inherits@2.0.4: {}
955 |
956 | isarray@1.0.0: {}
957 |
958 | jsbn@0.1.1: {}
959 |
960 | json-schema@0.4.0: {}
961 |
962 | jsprim@2.0.2:
963 | dependencies:
964 | assert-plus: 1.0.0
965 | extsprintf: 1.3.0
966 | json-schema: 0.4.0
967 | verror: 1.10.0
968 |
969 | lodash@4.17.21: {}
970 |
971 | lru-cache@7.18.3: {}
972 |
973 | make-error@1.3.6: {}
974 |
975 | math-intrinsics@1.1.0: {}
976 |
977 | media-typer@1.1.0: {}
978 |
979 | mime-db@1.54.0: {}
980 |
981 | mime-types@3.0.1:
982 | dependencies:
983 | mime-db: 1.54.0
984 |
985 | mime@1.6.0: {}
986 |
987 | mime@3.0.0: {}
988 |
989 | minimalistic-assert@1.0.1: {}
990 |
991 | ms@2.0.0: {}
992 |
993 | ms@2.1.3: {}
994 |
995 | nan@2.22.2:
996 | optional: true
997 |
998 | negotiator@0.6.4: {}
999 |
1000 | object-inspect@1.13.4: {}
1001 |
1002 | obuf@1.1.2: {}
1003 |
1004 | on-exit-leak-free@2.1.2: {}
1005 |
1006 | on-finished@2.4.1:
1007 | dependencies:
1008 | ee-first: 1.1.1
1009 |
1010 | once@1.4.0:
1011 | dependencies:
1012 | wrappy: 1.0.2
1013 |
1014 | pidusage@3.0.2:
1015 | dependencies:
1016 | safe-buffer: 5.2.1
1017 |
1018 | pino-abstract-transport@1.2.0:
1019 | dependencies:
1020 | readable-stream: 4.7.0
1021 | split2: 4.2.0
1022 |
1023 | pino-std-serializers@6.2.2: {}
1024 |
1025 | pino@8.21.0:
1026 | dependencies:
1027 | atomic-sleep: 1.0.0
1028 | fast-redact: 3.5.0
1029 | on-exit-leak-free: 2.1.2
1030 | pino-abstract-transport: 1.2.0
1031 | pino-std-serializers: 6.2.2
1032 | process-warning: 3.0.0
1033 | quick-format-unescaped: 4.0.4
1034 | real-require: 0.2.0
1035 | safe-stable-stringify: 2.5.0
1036 | sonic-boom: 3.8.1
1037 | thread-stream: 2.7.0
1038 |
1039 | process-nextick-args@2.0.1: {}
1040 |
1041 | process-warning@3.0.0: {}
1042 |
1043 | process@0.11.10: {}
1044 |
1045 | qs@6.14.0:
1046 | dependencies:
1047 | side-channel: 1.1.0
1048 |
1049 | quick-format-unescaped@4.0.4: {}
1050 |
1051 | range-parser@1.2.1: {}
1052 |
1053 | raw-body@3.0.0:
1054 | dependencies:
1055 | bytes: 3.1.2
1056 | http-errors: 2.0.0
1057 | iconv-lite: 0.6.3
1058 | unpipe: 1.0.0
1059 |
1060 | readable-stream@2.3.8:
1061 | dependencies:
1062 | core-util-is: 1.0.3
1063 | inherits: 2.0.4
1064 | isarray: 1.0.0
1065 | process-nextick-args: 2.0.1
1066 | safe-buffer: 5.1.2
1067 | string_decoder: 1.1.1
1068 | util-deprecate: 1.0.2
1069 |
1070 | readable-stream@3.6.2:
1071 | dependencies:
1072 | inherits: 2.0.4
1073 | string_decoder: 1.3.0
1074 | util-deprecate: 1.0.2
1075 |
1076 | readable-stream@4.7.0:
1077 | dependencies:
1078 | abort-controller: 3.0.0
1079 | buffer: 6.0.3
1080 | events: 3.3.0
1081 | process: 0.11.10
1082 | string_decoder: 1.3.0
1083 |
1084 | real-require@0.2.0: {}
1085 |
1086 | request-ip@3.3.0: {}
1087 |
1088 | restify-errors@8.0.2:
1089 | dependencies:
1090 | '@netflix/nerror': 1.1.3
1091 | assert-plus: 1.0.0
1092 | lodash: 4.17.21
1093 | optionalDependencies:
1094 | safe-json-stringify: 1.2.0
1095 |
1096 | restify@11.1.0:
1097 | dependencies:
1098 | assert-plus: 1.0.0
1099 | csv: 6.3.11
1100 | escape-regexp-component: 1.0.2
1101 | ewma: 2.0.1
1102 | find-my-way: 7.7.0
1103 | formidable: 1.2.6
1104 | http-signature: 1.4.0
1105 | lodash: 4.17.21
1106 | lru-cache: 7.18.3
1107 | mime: 3.0.0
1108 | negotiator: 0.6.4
1109 | once: 1.4.0
1110 | pidusage: 3.0.2
1111 | pino: 8.21.0
1112 | qs: 6.14.0
1113 | restify-errors: 8.0.2
1114 | semver: 7.7.1
1115 | send: 0.18.0
1116 | spdy: 4.0.2
1117 | uuid: 9.0.1
1118 | vasync: 2.2.1
1119 | optionalDependencies:
1120 | dtrace-provider: 0.8.8
1121 | transitivePeerDependencies:
1122 | - supports-color
1123 |
1124 | ret@0.2.2: {}
1125 |
1126 | safe-buffer@5.1.2: {}
1127 |
1128 | safe-buffer@5.2.1: {}
1129 |
1130 | safe-json-stringify@1.2.0:
1131 | optional: true
1132 |
1133 | safe-regex2@2.0.0:
1134 | dependencies:
1135 | ret: 0.2.2
1136 |
1137 | safe-stable-stringify@2.5.0: {}
1138 |
1139 | safer-buffer@2.1.2: {}
1140 |
1141 | select-hose@2.0.0: {}
1142 |
1143 | semver@7.7.1: {}
1144 |
1145 | send@0.18.0:
1146 | dependencies:
1147 | debug: 2.6.9
1148 | depd: 2.0.0
1149 | destroy: 1.2.0
1150 | encodeurl: 1.0.2
1151 | escape-html: 1.0.3
1152 | etag: 1.8.1
1153 | fresh: 0.5.2
1154 | http-errors: 2.0.0
1155 | mime: 1.6.0
1156 | ms: 2.1.3
1157 | on-finished: 2.4.1
1158 | range-parser: 1.2.1
1159 | statuses: 2.0.1
1160 | transitivePeerDependencies:
1161 | - supports-color
1162 |
1163 | setprototypeof@1.2.0: {}
1164 |
1165 | side-channel-list@1.0.0:
1166 | dependencies:
1167 | es-errors: 1.3.0
1168 | object-inspect: 1.13.4
1169 |
1170 | side-channel-map@1.0.1:
1171 | dependencies:
1172 | call-bound: 1.0.4
1173 | es-errors: 1.3.0
1174 | get-intrinsic: 1.3.0
1175 | object-inspect: 1.13.4
1176 |
1177 | side-channel-weakmap@1.0.2:
1178 | dependencies:
1179 | call-bound: 1.0.4
1180 | es-errors: 1.3.0
1181 | get-intrinsic: 1.3.0
1182 | object-inspect: 1.13.4
1183 | side-channel-map: 1.0.1
1184 |
1185 | side-channel@1.1.0:
1186 | dependencies:
1187 | es-errors: 1.3.0
1188 | object-inspect: 1.13.4
1189 | side-channel-list: 1.0.0
1190 | side-channel-map: 1.0.1
1191 | side-channel-weakmap: 1.0.2
1192 |
1193 | sonic-boom@3.8.1:
1194 | dependencies:
1195 | atomic-sleep: 1.0.0
1196 |
1197 | spdy-transport@3.0.0:
1198 | dependencies:
1199 | debug: 4.4.0
1200 | detect-node: 2.1.0
1201 | hpack.js: 2.1.6
1202 | obuf: 1.1.2
1203 | readable-stream: 3.6.2
1204 | wbuf: 1.7.3
1205 | transitivePeerDependencies:
1206 | - supports-color
1207 |
1208 | spdy@4.0.2:
1209 | dependencies:
1210 | debug: 4.4.0
1211 | handle-thing: 2.0.1
1212 | http-deceiver: 1.2.7
1213 | select-hose: 2.0.0
1214 | spdy-transport: 3.0.0
1215 | transitivePeerDependencies:
1216 | - supports-color
1217 |
1218 | split2@4.2.0: {}
1219 |
1220 | sshpk@1.18.0:
1221 | dependencies:
1222 | asn1: 0.2.6
1223 | assert-plus: 1.0.0
1224 | bcrypt-pbkdf: 1.0.2
1225 | dashdash: 1.14.1
1226 | ecc-jsbn: 0.1.2
1227 | getpass: 0.1.7
1228 | jsbn: 0.1.1
1229 | safer-buffer: 2.1.2
1230 | tweetnacl: 0.14.5
1231 |
1232 | statuses@2.0.1: {}
1233 |
1234 | stream-transform@3.3.3: {}
1235 |
1236 | string_decoder@1.1.1:
1237 | dependencies:
1238 | safe-buffer: 5.1.2
1239 |
1240 | string_decoder@1.3.0:
1241 | dependencies:
1242 | safe-buffer: 5.2.1
1243 |
1244 | thread-stream@2.7.0:
1245 | dependencies:
1246 | real-require: 0.2.0
1247 |
1248 | toidentifier@1.0.1: {}
1249 |
1250 | ts-node@10.9.2(@types/node@22.14.0)(typescript@5.8.3):
1251 | dependencies:
1252 | '@cspotcode/source-map-support': 0.8.1
1253 | '@tsconfig/node10': 1.0.11
1254 | '@tsconfig/node12': 1.0.11
1255 | '@tsconfig/node14': 1.0.3
1256 | '@tsconfig/node16': 1.0.4
1257 | '@types/node': 22.14.0
1258 | acorn: 8.14.1
1259 | acorn-walk: 8.3.4
1260 | arg: 4.1.3
1261 | create-require: 1.1.1
1262 | diff: 4.0.2
1263 | make-error: 1.3.6
1264 | typescript: 5.8.3
1265 | v8-compile-cache-lib: 3.0.1
1266 | yn: 3.1.1
1267 |
1268 | tweetnacl@0.14.5: {}
1269 |
1270 | type-is@2.0.1:
1271 | dependencies:
1272 | content-type: 1.0.5
1273 | media-typer: 1.1.0
1274 | mime-types: 3.0.1
1275 |
1276 | typescript@5.8.3: {}
1277 |
1278 | undici-types@6.21.0: {}
1279 |
1280 | unpipe@1.0.0: {}
1281 |
1282 | util-deprecate@1.0.2: {}
1283 |
1284 | uuid@9.0.1: {}
1285 |
1286 | v8-compile-cache-lib@3.0.1: {}
1287 |
1288 | vasync@2.2.1:
1289 | dependencies:
1290 | verror: 1.10.0
1291 |
1292 | verror@1.10.0:
1293 | dependencies:
1294 | assert-plus: 1.0.0
1295 | core-util-is: 1.0.2
1296 | extsprintf: 1.4.1
1297 |
1298 | wbuf@1.7.3:
1299 | dependencies:
1300 | minimalistic-assert: 1.0.1
1301 |
1302 | wrappy@1.0.2: {}
1303 |
1304 | yn@3.1.1: {}
1305 |
--------------------------------------------------------------------------------