将部署链路调整为 CI 构建推送镜像、服务器拉取镜像运行,并拆分/复用 Gitea workflow 与公共准备脚本;同时统一 APP_NAME 与端口变量配置,补充 Docker 与 ESLint 相关配置文件以提升可维护性。 Made-with: Cursor
This commit is contained in:
11
.dockerignore
Normal file
11
.dockerignore
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.cursor
|
||||||
|
.DS_Store
|
||||||
|
coverage
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
docs
|
||||||
|
deploy/nginx
|
||||||
116
.gitea/scripts/prepare-workspace.sh
Normal file
116
.gitea/scripts/prepare-workspace.sh
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Reusable bootstrap for Gitea workflows:
|
||||||
|
# 1) checkout target commit
|
||||||
|
# 2) ensure Node version (install from domestic mirror if missing/mismatch)
|
||||||
|
# 3) ensure Yarn is available (and optionally pin version)
|
||||||
|
# 通用准备脚本:用于 CI/Deploy 前的代码检出、Node 准备、Yarn 准备。
|
||||||
|
|
||||||
|
REPO_URL="${1:?repo url required}"
|
||||||
|
GIT_SHA="${2:?git sha required}"
|
||||||
|
# 优先使用精确版本 NODE_VERSION;未指定时按 NODE_MAJOR 自动解析最新小版本。
|
||||||
|
NODE_MAJOR="${NODE_MAJOR:-22}"
|
||||||
|
NODE_VERSION="${NODE_VERSION:-}"
|
||||||
|
YARN_VERSION="${YARN_VERSION:-stable}"
|
||||||
|
# 默认使用国内镜像,减少下载失败概率。
|
||||||
|
NODEJS_MIRROR="${NODEJS_MIRROR:-https://npmmirror.com/mirrors/node}"
|
||||||
|
NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmmirror.com}"
|
||||||
|
# 安装到用户目录,避免依赖 /opt 写权限。
|
||||||
|
NODE_INSTALL_ROOT="${NODE_INSTALL_ROOT:-$HOME/.local/node-ci}"
|
||||||
|
|
||||||
|
resolve_node_version() {
|
||||||
|
# 指定了精确版本时,直接使用。
|
||||||
|
if [ -n "${NODE_VERSION}" ]; then
|
||||||
|
echo "${NODE_VERSION#v}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 未指定精确版本时,从镜像索引中选定 NODE_MAJOR 对应的最新版本。
|
||||||
|
local resolved
|
||||||
|
resolved="$(curl -fsSL "${NODEJS_MIRROR}/index.tab" | awk -F'\t' -v major="${NODE_MAJOR}" '
|
||||||
|
NR > 1 && $1 ~ ("^v" major "\\.") { print substr($1, 2); exit }
|
||||||
|
')"
|
||||||
|
if [ -z "${resolved}" ]; then
|
||||||
|
echo "failed to resolve latest Node ${NODE_MAJOR}.x from ${NODEJS_MIRROR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "${resolved}"
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_arch() {
|
||||||
|
# 仅支持常见 Linux 架构;其他架构显式失败,避免下载错误包。
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64) echo "x64" ;;
|
||||||
|
aarch64 | arm64) echo "arm64" ;;
|
||||||
|
*)
|
||||||
|
echo "unsupported architecture: $(uname -m)"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
install_node() {
|
||||||
|
local target_version="$1"
|
||||||
|
local arch name url tarball install_dir bindir
|
||||||
|
arch="$(detect_arch)"
|
||||||
|
name="node-v${target_version}-linux-${arch}"
|
||||||
|
url="${NODEJS_MIRROR}/v${target_version}/${name}.tar.xz"
|
||||||
|
tarball="/tmp/${name}.tar.xz"
|
||||||
|
install_dir="${NODE_INSTALL_ROOT}/${name}"
|
||||||
|
bindir="${install_dir}/bin"
|
||||||
|
|
||||||
|
if [ ! -x "${bindir}/node" ]; then
|
||||||
|
# 下载并解压 Node 二进制包到本地缓存目录。
|
||||||
|
mkdir -p "${NODE_INSTALL_ROOT}"
|
||||||
|
curl -fsSL "${url}" -o "${tarball}"
|
||||||
|
tar -xJf "${tarball}" -C "${NODE_INSTALL_ROOT}"
|
||||||
|
rm -f "${tarball}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PATH="${bindir}:${PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_node() {
|
||||||
|
local target_version node_version
|
||||||
|
target_version="$(resolve_node_version)"
|
||||||
|
|
||||||
|
# 版本完全一致则直接复用,避免重复下载。
|
||||||
|
if command -v node >/dev/null 2>&1; then
|
||||||
|
node_version="$(node -v | sed 's/^v//')"
|
||||||
|
if [ "${node_version}" = "${target_version}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_node "${target_version}"
|
||||||
|
|
||||||
|
node_version="$(node -v | sed 's/^v//')"
|
||||||
|
if [ "${node_version}" != "${target_version}" ]; then
|
||||||
|
echo "failed to switch to Node ${target_version}, current=${node_version}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 首次执行时检出目标提交;已存在仓库则更新并强制切到指定 SHA。
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
git clone "${REPO_URL}" .
|
||||||
|
fi
|
||||||
|
|
||||||
|
git fetch --all --tags --prune
|
||||||
|
git checkout -f "${GIT_SHA}"
|
||||||
|
|
||||||
|
ensure_node
|
||||||
|
|
||||||
|
# Use domestic npm mirror for package-manager metadata/download.
|
||||||
|
npm config set registry "${NPM_REGISTRY}" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if ! command -v yarn >/dev/null 2>&1; then
|
||||||
|
# 通过 corepack 激活指定 Yarn 版本。
|
||||||
|
corepack enable
|
||||||
|
export COREPACK_NPM_REGISTRY="${NPM_REGISTRY}"
|
||||||
|
corepack prepare "yarn@${YARN_VERSION}" --activate
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Node: $(node -v)"
|
||||||
|
echo "Yarn: $(yarn -v)"
|
||||||
36
.gitea/workflows/ci.yml
Normal file
36
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["main"]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# workflow_call 调用示例(先保留注释,不启用):
|
||||||
|
# ci:
|
||||||
|
# uses: ./.gitea/workflows/reusable-ci.yml
|
||||||
|
# with:
|
||||||
|
# node_major: "22"
|
||||||
|
# yarn_version: "stable"
|
||||||
|
# run_lint: true
|
||||||
|
# run_tsc: true
|
||||||
|
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NODE_MAJOR: "22"
|
||||||
|
YARN_VERSION: "stable"
|
||||||
|
steps:
|
||||||
|
- name: Prepare workspace (checkout + node/yarn)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
chmod +x .gitea/scripts/prepare-workspace.sh
|
||||||
|
./.gitea/scripts/prepare-workspace.sh \
|
||||||
|
"${{ github.server_url }}/${{ github.repository }}.git" \
|
||||||
|
"${{ github.sha }}"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
- name: Lint
|
||||||
|
run: yarn lint
|
||||||
|
- name: TypeScript check
|
||||||
|
run: yarn tsc --noEmit
|
||||||
80
.gitea/workflows/deploy.yml
Normal file
80
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Deploy Production
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ["v*"]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NODE_MAJOR: "22"
|
||||||
|
YARN_VERSION: "stable"
|
||||||
|
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
|
||||||
|
DEPLOY_PORT: ${{ vars.DEPLOY_PORT }}
|
||||||
|
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
||||||
|
DEPLOY_PATH: ${{ vars.DEPLOY_PATH }}
|
||||||
|
IMAGE_REPO: ${{ vars.IMAGE_REPO }}
|
||||||
|
REGISTRY: ${{ vars.REGISTRY }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare workspace (checkout + node/yarn)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
chmod +x .gitea/scripts/prepare-workspace.sh
|
||||||
|
./.gitea/scripts/prepare-workspace.sh \
|
||||||
|
"${{ github.server_url }}/${{ github.repository }}.git" \
|
||||||
|
"${{ github.sha }}"
|
||||||
|
|
||||||
|
- name: Setup SSH
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||||
|
chmod 600 ~/.ssh/id_rsa
|
||||||
|
ssh-keyscan -p "${DEPLOY_PORT:-22}" "${DEPLOY_HOST}" >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: Prepare image tag
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then
|
||||||
|
IMAGE_TAG="${GITHUB_REF_NAME}"
|
||||||
|
else
|
||||||
|
IMAGE_TAG="${GITHUB_SHA:0:12}"
|
||||||
|
fi
|
||||||
|
echo "IMAGE_TAG=${IMAGE_TAG}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -z "${REGISTRY}" ] || [ -z "${IMAGE_REPO}" ]; then
|
||||||
|
echo "REGISTRY and IMAGE_REPO vars are required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${REGISTRY}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
|
||||||
|
docker build -f deploy/docker/Dockerfile -t "${IMAGE_REPO}:${IMAGE_TAG}" .
|
||||||
|
docker push "${IMAGE_REPO}:${IMAGE_TAG}"
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
ssh -p "${DEPLOY_PORT:-22}" "${DEPLOY_USER}@${DEPLOY_HOST}" <<EOF
|
||||||
|
set -euo pipefail
|
||||||
|
cd "${DEPLOY_PATH}"
|
||||||
|
|
||||||
|
mkdir -p deploy/docker
|
||||||
|
cat > deploy/docker/.env <<EOT
|
||||||
|
${{ vars.DEPLOY_DOCKER_ENV }}
|
||||||
|
IMAGE_REPO=${IMAGE_REPO}
|
||||||
|
IMAGE_TAG=${IMAGE_TAG}
|
||||||
|
EOT
|
||||||
|
|
||||||
|
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "${REGISTRY}" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env pull app
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d app
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml ps
|
||||||
|
curl -fsS "http://127.0.0.1:\${HOST_BIND_PORT:-3000}/api/docs" >/dev/null
|
||||||
|
EOF
|
||||||
51
.gitea/workflows/reusable-ci.yml
Normal file
51
.gitea/workflows/reusable-ci.yml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Reusable CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
node_major:
|
||||||
|
description: "Node 主版本(例如 22)"
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: "22"
|
||||||
|
yarn_version:
|
||||||
|
description: "Yarn 版本(例如 stable 或 1.22.22)"
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: "stable"
|
||||||
|
run_lint:
|
||||||
|
description: "是否执行 yarn lint"
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
run_tsc:
|
||||||
|
description: "是否执行 yarn tsc --noEmit"
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NODE_MAJOR: ${{ inputs.node_major }}
|
||||||
|
YARN_VERSION: ${{ inputs.yarn_version }}
|
||||||
|
steps:
|
||||||
|
- name: Prepare workspace (checkout + node/yarn)
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
chmod +x .gitea/scripts/prepare-workspace.sh
|
||||||
|
./.gitea/scripts/prepare-workspace.sh \
|
||||||
|
"${{ github.server_url }}/${{ github.repository }}.git" \
|
||||||
|
"${{ github.sha }}"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
if: ${{ inputs.run_lint }}
|
||||||
|
run: yarn lint
|
||||||
|
|
||||||
|
- name: TypeScript check
|
||||||
|
if: ${{ inputs.run_tsc }}
|
||||||
|
run: yarn tsc --noEmit
|
||||||
42
deploy/docker/.env.example
Normal file
42
deploy/docker/.env.example
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# App
|
||||||
|
NODE_ENV=production
|
||||||
|
PORT=3000
|
||||||
|
HOST_BIND_PORT=3000
|
||||||
|
APP_NAME=chat-one-service
|
||||||
|
IMAGE_REPO=registry.example.com/team/chat-one-service
|
||||||
|
IMAGE_TAG=v0.0.1
|
||||||
|
|
||||||
|
# JWT
|
||||||
|
JWT_ACCESS_SECRET=replace_with_random_string_min_32_chars
|
||||||
|
JWT_REFRESH_SECRET=replace_with_random_string_min_32_chars
|
||||||
|
JWT_ACCESS_EXPIRES_IN=2h
|
||||||
|
JWT_REFRESH_EXPIRES_IN=30d
|
||||||
|
|
||||||
|
# AI Providers
|
||||||
|
QWEN_API_KEY=
|
||||||
|
QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
||||||
|
DEEPSEEK_API_KEY=
|
||||||
|
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
|
||||||
|
VOLC_API_KEY=
|
||||||
|
VOLC_BASE_URL=https://ark.cn-beijing.volces.com/api/v3
|
||||||
|
|
||||||
|
# SMS
|
||||||
|
SPUG_PUSH_SMS_TEMPLATE_ID=
|
||||||
|
SPUG_PUSH_BASE_URL=https://push.spug.cc
|
||||||
|
SMS_CODE_TTL_SECONDS=300
|
||||||
|
SMS_MOCK=false
|
||||||
|
|
||||||
|
# Redis (remote)
|
||||||
|
REDIS_HOST=your-remote-redis-host
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PASSWORD=your-redis-password
|
||||||
|
REDIS_DB=1
|
||||||
|
REDIS_KEY_PREFIX_CLIENT=chatone:client:prod
|
||||||
|
REDIS_KEY_PREFIX_ADMIN=chatone:admin:prod
|
||||||
|
|
||||||
|
# PostgreSQL (remote)
|
||||||
|
DATABASE_URL=postgresql://user:password@your-remote-postgres-host:5432/chat_one?schema=public
|
||||||
|
|
||||||
|
# AI Route
|
||||||
|
AI_ROUTE_RETRY_TIMES=1
|
||||||
|
AI_ROUTE_TIMEOUT_MS=45000
|
||||||
30
deploy/docker/Dockerfile
Normal file
30
deploy/docker/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FROM node:22-alpine AS base
|
||||||
|
WORKDIR /app
|
||||||
|
RUN apk add --no-cache libc6-compat openssl
|
||||||
|
RUN npm i -g pm2
|
||||||
|
|
||||||
|
FROM base AS deps
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
FROM deps AS build
|
||||||
|
COPY tsconfig.json ./
|
||||||
|
COPY prisma ./prisma
|
||||||
|
COPY src ./src
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
FROM base AS runner
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY --from=build /app/dist ./dist
|
||||||
|
COPY --from=build /app/prisma ./prisma
|
||||||
|
COPY package.json yarn.lock ./
|
||||||
|
COPY deploy/docker/app.entrypoint.sh ./app.entrypoint.sh
|
||||||
|
COPY deploy/docker/ecosystem.config.cjs ./ecosystem.config.cjs
|
||||||
|
|
||||||
|
RUN chmod +x ./app.entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["./app.entrypoint.sh"]
|
||||||
8
deploy/docker/app.entrypoint.sh
Normal file
8
deploy/docker/app.entrypoint.sh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
echo "[entrypoint] running prisma migrate deploy..."
|
||||||
|
npx prisma migrate deploy
|
||||||
|
|
||||||
|
echo "[entrypoint] starting service with pm2-runtime..."
|
||||||
|
pm2-runtime start ecosystem.config.cjs --env production
|
||||||
9
deploy/docker/docker-compose.yml
Normal file
9
deploy/docker/docker-compose.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: ${IMAGE_REPO}:${IMAGE_TAG}
|
||||||
|
container_name: ${APP_NAME}-app
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file:
|
||||||
|
- ./.env
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:${HOST_BIND_PORT}:${PORT}"
|
||||||
18
deploy/docker/ecosystem.config.cjs
Normal file
18
deploy/docker/ecosystem.config.cjs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: process.env.APP_NAME,
|
||||||
|
script: 'dist/main.js',
|
||||||
|
cwd: '/app',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
autorestart: true,
|
||||||
|
watch: false,
|
||||||
|
max_memory_restart: '1G',
|
||||||
|
env_production: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name api.example.com;
|
|
||||||
|
|
||||||
client_max_body_size 20m;
|
|
||||||
|
|
||||||
location / {
|
|
||||||
proxy_pass http://127.0.0.1:3000;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
|
|
||||||
# SSE support
|
|
||||||
proxy_buffering off;
|
|
||||||
proxy_cache off;
|
|
||||||
proxy_read_timeout 3600;
|
|
||||||
proxy_send_timeout 3600;
|
|
||||||
chunked_transfer_encoding off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
167
docs/deploy-docker-compose.md
Normal file
167
docs/deploy-docker-compose.md
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# ChatOne Service Docker 部署(Compose)
|
||||||
|
|
||||||
|
本文提供单机 Docker Compose 部署方案,包含 `app`(数据库与 Redis 使用远程实例)。
|
||||||
|
域名、HTTPS、反向代理统一在宿主机 Nginx 处理。
|
||||||
|
|
||||||
|
## 1. 文件位置
|
||||||
|
|
||||||
|
- `deploy/docker/Dockerfile`
|
||||||
|
- `deploy/docker/app.entrypoint.sh`
|
||||||
|
- `deploy/docker/ecosystem.config.cjs`
|
||||||
|
- `deploy/docker/docker-compose.yml`
|
||||||
|
- `deploy/docker/.env.example`
|
||||||
|
|
||||||
|
## 2. 初始化
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd deploy/docker
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
修改 `.env` 中所有密钥与密码,至少包括:
|
||||||
|
|
||||||
|
- `JWT_ACCESS_SECRET`
|
||||||
|
- `JWT_REFRESH_SECRET`
|
||||||
|
- `QWEN_API_KEY`(如使用)
|
||||||
|
- `DATABASE_URL`
|
||||||
|
- `REDIS_PASSWORD`
|
||||||
|
- `IMAGE_REPO`
|
||||||
|
- `IMAGE_TAG`
|
||||||
|
|
||||||
|
请将 `DATABASE_URL`、`REDIS_HOST`、`REDIS_PASSWORD` 替换为远程实例配置。
|
||||||
|
镜像发布模式说明:
|
||||||
|
|
||||||
|
- CI 负责构建并推送 `${IMAGE_REPO}:${IMAGE_TAG}`
|
||||||
|
- 目标服务器仅执行 `docker compose pull + up`
|
||||||
|
|
||||||
|
端口统一约定:
|
||||||
|
|
||||||
|
- `PORT`:容器内应用监听端口
|
||||||
|
- `HOST_BIND_PORT`:宿主机绑定端口(供宿主机 Nginx 反代)
|
||||||
|
|
||||||
|
## 3. 启动
|
||||||
|
|
||||||
|
在项目根目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
查看状态:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml ps
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml logs -f app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 验证
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -i http://127.0.0.1:${HOST_BIND_PORT}/api/docs
|
||||||
|
```
|
||||||
|
|
||||||
|
SSE 冒烟:
|
||||||
|
|
||||||
|
- `POST /api/client/v1/chat/completions/stream`
|
||||||
|
|
||||||
|
## 5. 发布升级
|
||||||
|
|
||||||
|
拉取新代码后执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d --build app
|
||||||
|
```
|
||||||
|
|
||||||
|
数据库迁移会在 `app` 容器启动时自动执行(`npx prisma migrate deploy`)。
|
||||||
|
应用进程由容器内 `pm2-runtime` 管理。
|
||||||
|
|
||||||
|
## 6. 回滚
|
||||||
|
|
||||||
|
推荐在发布前打镜像标签,例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -f deploy/docker/Dockerfile -t chat-one-service:20260426 .
|
||||||
|
```
|
||||||
|
|
||||||
|
回滚时将 compose 中 `app.image` 改为旧标签,然后:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f deploy/docker/docker-compose.yml --env-file deploy/docker/.env up -d app
|
||||||
|
```
|
||||||
|
|
||||||
|
## 7. 生产建议
|
||||||
|
|
||||||
|
- 不要把 `.env` 提交到仓库。
|
||||||
|
- `app` 仅监听本机 `127.0.0.1:${HOST_BIND_PORT}`,由宿主机 Nginx 反向代理。
|
||||||
|
- PostgreSQL/Redis 建议使用托管或远程实例,并通过白名单限制访问来源。
|
||||||
|
- HTTPS 由宿主机 Nginx 统一终止,保留 SSE 反代配置(`proxy_buffering off`、长超时)。
|
||||||
|
- 定时备份 Postgres:
|
||||||
|
- `pg_dump` 每日一次,保留 7-14 天并异地存储。
|
||||||
|
|
||||||
|
## 8. 宿主机 Nginx 配置示例
|
||||||
|
|
||||||
|
将域名流量转发到本机 `127.0.0.1:${HOST_BIND_PORT}`(容器 app 端口),并确保 SSE 可用。
|
||||||
|
|
||||||
|
### 8.1 HTTP 示例
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name api.your-domain.com;
|
||||||
|
|
||||||
|
client_max_body_size 20m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:${HOST_BIND_PORT};
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# SSE support
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_cache off;
|
||||||
|
proxy_read_timeout 3600;
|
||||||
|
proxy_send_timeout 3600;
|
||||||
|
chunked_transfer_encoding off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.2 HTTPS 示例(推荐)
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name api.your-domain.com;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/api.your-domain.com/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/api.your-domain.com/privkey.pem;
|
||||||
|
|
||||||
|
client_max_body_size 20m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:${HOST_BIND_PORT};
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_cache off;
|
||||||
|
proxy_read_timeout 3600;
|
||||||
|
proxy_send_timeout 3600;
|
||||||
|
chunked_transfer_encoding off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
应用配置后执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nginx -t && sudo systemctl reload nginx
|
||||||
|
```
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
# ChatOne Service 单机部署指南(Ubuntu + PM2 + Nginx)
|
|
||||||
|
|
||||||
本文给出 `chat-one-service` 在单机 Linux 环境的可执行部署流程,覆盖:
|
|
||||||
- 服务器基线检查
|
|
||||||
- 生产环境变量合同
|
|
||||||
- 发布与回滚流程
|
|
||||||
- Nginx 反向代理(含 SSE)
|
|
||||||
- 监控、备份与巡检
|
|
||||||
|
|
||||||
## 1. 适用范围
|
|
||||||
|
|
||||||
- OS:Ubuntu 22.04 LTS
|
|
||||||
- Runtime:Node.js 22.x
|
|
||||||
- 进程管理:PM2
|
|
||||||
- 反向代理:Nginx
|
|
||||||
- 依赖:PostgreSQL、Redis(可为外部托管)
|
|
||||||
|
|
||||||
## 2. 服务器基线检查(部署前)
|
|
||||||
|
|
||||||
### 2.1 主机与网络
|
|
||||||
|
|
||||||
- [ ] 已准备公网域名(示例:`api.example.com`)
|
|
||||||
- [ ] `22/80/443` 已开放
|
|
||||||
- [ ] 应用端口(默认 `3000`)仅允许本机访问
|
|
||||||
- [ ] 时区与 NTP 已校准(`timedatectl status`)
|
|
||||||
|
|
||||||
### 2.2 账号与权限
|
|
||||||
|
|
||||||
- [ ] 创建专用用户:`chatone`
|
|
||||||
- [ ] 禁止 root 直登,仅 SSH Key 登录
|
|
||||||
- [ ] `chatone` 拥有 `/srv/chat-one-service` 读写权限
|
|
||||||
|
|
||||||
### 2.3 依赖连通性
|
|
||||||
|
|
||||||
- [ ] PostgreSQL 可连接(`DATABASE_URL` 可用)
|
|
||||||
- [ ] Redis 可连接(`REDIS_HOST/PORT` 可用)
|
|
||||||
- [ ] 第三方 AI API Key 已可用(如 `QWEN_API_KEY`)
|
|
||||||
|
|
||||||
## 3. 目录约定
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/srv/chat-one-service/
|
|
||||||
releases/
|
|
||||||
20260423_120000/
|
|
||||||
current -> /srv/chat-one-service/releases/20260423_120000
|
|
||||||
shared/
|
|
||||||
.env
|
|
||||||
logs/
|
|
||||||
```
|
|
||||||
|
|
||||||
初始化目录:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /srv/chat-one-service/{releases,shared/logs}
|
|
||||||
sudo chown -R chatone:chatone /srv/chat-one-service
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4. 运行时安装
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Node.js 22(nvm 方式,推荐)
|
|
||||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
||||||
source ~/.nvm/nvm.sh
|
|
||||||
nvm install 22
|
|
||||||
nvm use 22
|
|
||||||
|
|
||||||
# Yarn + PM2
|
|
||||||
npm i -g yarn pm2
|
|
||||||
|
|
||||||
# Nginx + certbot
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y nginx certbot python3-certbot-nginx postgresql-client redis-tools
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5. 生产环境变量合同(shared/.env)
|
|
||||||
|
|
||||||
在 `/srv/chat-one-service/shared/.env` 写入:
|
|
||||||
|
|
||||||
```dotenv
|
|
||||||
# app
|
|
||||||
NODE_ENV=production
|
|
||||||
PORT=3000
|
|
||||||
APP_NAME=chat-one-service
|
|
||||||
|
|
||||||
# jwt(至少 32 位随机串)
|
|
||||||
JWT_ACCESS_SECRET=replace-with-long-random-string
|
|
||||||
JWT_REFRESH_SECRET=replace-with-long-random-string
|
|
||||||
JWT_ACCESS_EXPIRES_IN=2h
|
|
||||||
JWT_REFRESH_EXPIRES_IN=30d
|
|
||||||
|
|
||||||
# database
|
|
||||||
DATABASE_URL=postgresql://user:password@host:5432/chat_one?schema=public
|
|
||||||
|
|
||||||
# redis
|
|
||||||
REDIS_HOST=127.0.0.1
|
|
||||||
REDIS_PORT=6379
|
|
||||||
REDIS_PASSWORD=
|
|
||||||
REDIS_DB=0
|
|
||||||
REDIS_KEY_PREFIX_CLIENT=chatone:client
|
|
||||||
REDIS_KEY_PREFIX_ADMIN=chatone:admin
|
|
||||||
|
|
||||||
# ai
|
|
||||||
QWEN_API_KEY=
|
|
||||||
QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
|
|
||||||
DEEPSEEK_API_KEY=
|
|
||||||
VOLC_API_KEY=
|
|
||||||
|
|
||||||
# ai route
|
|
||||||
AI_ROUTE_RETRY_TIMES=1
|
|
||||||
AI_ROUTE_TIMEOUT_MS=45000
|
|
||||||
```
|
|
||||||
|
|
||||||
安全要求:
|
|
||||||
- `.env` 仅服务器本地保存,不入仓库。
|
|
||||||
- 定期轮换密钥,变更后执行 `pm2 reload chat-one-service --update-env`。
|
|
||||||
|
|
||||||
## 6. 首次部署流程
|
|
||||||
|
|
||||||
以下命令以 `chatone` 用户执行:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
set -e
|
|
||||||
APP_ROOT=/srv/chat-one-service
|
|
||||||
RELEASE="$APP_ROOT/releases/$(date +%Y%m%d_%H%M%S)"
|
|
||||||
|
|
||||||
mkdir -p "$RELEASE"
|
|
||||||
git clone <your-repo-url> "$RELEASE"
|
|
||||||
cd "$RELEASE"
|
|
||||||
|
|
||||||
yarn install --frozen-lockfile
|
|
||||||
yarn build
|
|
||||||
npx prisma migrate deploy
|
|
||||||
|
|
||||||
ln -sfn "$RELEASE" "$APP_ROOT/current"
|
|
||||||
```
|
|
||||||
|
|
||||||
启动:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /srv/chat-one-service/current
|
|
||||||
pm2 start ecosystem.config.js --env production
|
|
||||||
pm2 save
|
|
||||||
pm2 startup
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7. 日常发布流程(零停机)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
set -e
|
|
||||||
APP_ROOT=/srv/chat-one-service
|
|
||||||
RELEASE="$APP_ROOT/releases/$(date +%Y%m%d_%H%M%S)"
|
|
||||||
|
|
||||||
mkdir -p "$RELEASE"
|
|
||||||
git clone <your-repo-url> "$RELEASE"
|
|
||||||
cd "$RELEASE"
|
|
||||||
|
|
||||||
yarn install --frozen-lockfile
|
|
||||||
yarn build
|
|
||||||
npx prisma migrate deploy
|
|
||||||
|
|
||||||
ln -sfn "$RELEASE" "$APP_ROOT/current"
|
|
||||||
pm2 reload chat-one-service --update-env
|
|
||||||
```
|
|
||||||
|
|
||||||
发布后验证:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -fsS http://127.0.0.1:3000/api/docs >/dev/null
|
|
||||||
curl -fsS https://api.example.com/api/docs >/dev/null
|
|
||||||
```
|
|
||||||
|
|
||||||
如需 SSE 冒烟测试,调用:
|
|
||||||
- `POST /api/client/v1/chat/completions/stream`
|
|
||||||
|
|
||||||
## 8. Nginx 配置(含 SSE)
|
|
||||||
|
|
||||||
参考文件:`deploy/nginx/chat-one-service.conf`
|
|
||||||
|
|
||||||
生效步骤:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo cp deploy/nginx/chat-one-service.conf /etc/nginx/sites-available/chat-one-service.conf
|
|
||||||
sudo ln -sfn /etc/nginx/sites-available/chat-one-service.conf /etc/nginx/sites-enabled/chat-one-service.conf
|
|
||||||
sudo nginx -t
|
|
||||||
sudo systemctl reload nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
申请 HTTPS:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo certbot --nginx -d api.example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## 9. 回滚策略
|
|
||||||
|
|
||||||
### 9.1 代码回滚(快速)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
APP_ROOT=/srv/chat-one-service
|
|
||||||
ls -1dt "$APP_ROOT"/releases/* | sed -n '1,2p' # 找到上一个版本
|
|
||||||
ln -sfn <previous-release-path> "$APP_ROOT/current"
|
|
||||||
pm2 reload chat-one-service --update-env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9.2 数据回滚(高风险)
|
|
||||||
|
|
||||||
- 仅在迁移引发严重问题时执行。
|
|
||||||
- 使用最近一次全量备份恢复(建议维护停机窗口)。
|
|
||||||
|
|
||||||
## 10. 备份与监控最小集
|
|
||||||
|
|
||||||
### 10.1 PostgreSQL 备份
|
|
||||||
|
|
||||||
每日定时(cron):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pg_dump "$DATABASE_URL" | gzip > /data/backup/chat_one_$(date +%F).sql.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
建议:
|
|
||||||
- 保留 7-14 天
|
|
||||||
- 同步到对象存储(异地)
|
|
||||||
|
|
||||||
### 10.2 应用观测
|
|
||||||
|
|
||||||
- PM2:重启次数、内存、CPU
|
|
||||||
- Nginx:`4xx/5xx` 比率、延迟
|
|
||||||
- Redis:连接数与内存
|
|
||||||
- 日志:按天滚动,至少保留 7 天
|
|
||||||
|
|
||||||
## 11. 常用排障命令
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pm2 ls
|
|
||||||
pm2 logs chat-one-service --lines 200
|
|
||||||
pm2 describe chat-one-service
|
|
||||||
|
|
||||||
sudo systemctl status nginx
|
|
||||||
sudo tail -n 200 /var/log/nginx/error.log
|
|
||||||
|
|
||||||
curl -i http://127.0.0.1:3000/api/docs
|
|
||||||
```
|
|
||||||
|
|
||||||
## 12. 安全加固建议
|
|
||||||
|
|
||||||
- 安全组白名单限制 SSH 来源
|
|
||||||
- 开启 UFW,仅放行 `22/80/443`
|
|
||||||
- 禁止将 `.env`、备份明文文件提交到 Git
|
|
||||||
- 配置 fail2ban(可选)
|
|
||||||
32
eslint.config.mjs
Normal file
32
eslint.config.mjs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import js from "@eslint/js";
|
||||||
|
import { defineConfig } from "eslint/config";
|
||||||
|
import globals from "globals";
|
||||||
|
import tseslint from "typescript-eslint";
|
||||||
|
|
||||||
|
export default defineConfig(
|
||||||
|
{
|
||||||
|
ignores: ["dist/**", "node_modules/**"],
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
js.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
{
|
||||||
|
files: ["src/**/*.ts"],
|
||||||
|
languageOptions: {
|
||||||
|
parserOptions: {
|
||||||
|
projectService: true,
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
"no-console": "off",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -44,13 +44,16 @@
|
|||||||
"undici": "^8.1.0"
|
"undici": "^8.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^10.0.1",
|
||||||
"@types/node": "^25.6.0",
|
"@types/node": "^25.6.0",
|
||||||
"eslint": "^10.2.0",
|
"eslint": "^10.2.0",
|
||||||
|
"globals": "^17.5.0",
|
||||||
"pino-pretty": "^13.1.3",
|
"pino-pretty": "^13.1.3",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.8.3",
|
||||||
"prisma": "^7.7.0",
|
"prisma": "^7.7.0",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tsx": "^4.21.0",
|
"tsx": "^4.21.0",
|
||||||
"typescript": "^6.0.2"
|
"typescript": "^6.0.2",
|
||||||
|
"typescript-eslint": "^8.59.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
150
yarn.lock
150
yarn.lock
@@ -159,7 +159,7 @@
|
|||||||
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz#8fe30b3088b89b4873c3a6cc87597ae3920c0a8b"
|
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz#8fe30b3088b89b4873c3a6cc87597ae3920c0a8b"
|
||||||
integrity sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==
|
integrity sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==
|
||||||
|
|
||||||
"@eslint-community/eslint-utils@^4.8.0":
|
"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1":
|
||||||
version "4.9.1"
|
version "4.9.1"
|
||||||
resolved "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595"
|
resolved "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595"
|
||||||
integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==
|
integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==
|
||||||
@@ -194,6 +194,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/json-schema" "^7.0.15"
|
"@types/json-schema" "^7.0.15"
|
||||||
|
|
||||||
|
"@eslint/js@^10.0.1":
|
||||||
|
version "10.0.1"
|
||||||
|
resolved "https://registry.npmmirror.com/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583"
|
||||||
|
integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==
|
||||||
|
|
||||||
"@eslint/object-schema@^3.0.5":
|
"@eslint/object-schema@^3.0.5":
|
||||||
version "3.0.5"
|
version "3.0.5"
|
||||||
resolved "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091"
|
resolved "https://registry.npmmirror.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091"
|
||||||
@@ -748,6 +753,102 @@
|
|||||||
resolved "https://registry.npmmirror.com/@types/validator/-/validator-13.15.10.tgz#742b77ec34d58554b94a76a14cef30d59e3c16b9"
|
resolved "https://registry.npmmirror.com/@types/validator/-/validator-13.15.10.tgz#742b77ec34d58554b94a76a14cef30d59e3c16b9"
|
||||||
integrity sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==
|
integrity sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==
|
||||||
|
|
||||||
|
"@typescript-eslint/eslint-plugin@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz#fcbe76b693ce2412410cf4d48aefd617d345f2d9"
|
||||||
|
integrity sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==
|
||||||
|
dependencies:
|
||||||
|
"@eslint-community/regexpp" "^4.12.2"
|
||||||
|
"@typescript-eslint/scope-manager" "8.59.0"
|
||||||
|
"@typescript-eslint/type-utils" "8.59.0"
|
||||||
|
"@typescript-eslint/utils" "8.59.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "8.59.0"
|
||||||
|
ignore "^7.0.5"
|
||||||
|
natural-compare "^1.4.0"
|
||||||
|
ts-api-utils "^2.5.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/parser@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.59.0.tgz#57a138280b3ceaf07904fbd62c433d5cc1ee1573"
|
||||||
|
integrity sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/scope-manager" "8.59.0"
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "8.59.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "8.59.0"
|
||||||
|
debug "^4.4.3"
|
||||||
|
|
||||||
|
"@typescript-eslint/project-service@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.59.0.tgz#914bf62069d870faa0389ffd725774a200f511bf"
|
||||||
|
integrity sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/tsconfig-utils" "^8.59.0"
|
||||||
|
"@typescript-eslint/types" "^8.59.0"
|
||||||
|
debug "^4.4.3"
|
||||||
|
|
||||||
|
"@typescript-eslint/scope-manager@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz#f71be268bd31da1c160815c689e4dde7c9bc9e8e"
|
||||||
|
integrity sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "8.59.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/tsconfig-utils@8.59.0", "@typescript-eslint/tsconfig-utils@^8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz#1276077f5ad77e384446ea28a2474e8f8be1af41"
|
||||||
|
integrity sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==
|
||||||
|
|
||||||
|
"@typescript-eslint/type-utils@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz#2834ea3b179cedfc9244dcd4f74105a27751a439"
|
||||||
|
integrity sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "8.59.0"
|
||||||
|
"@typescript-eslint/utils" "8.59.0"
|
||||||
|
debug "^4.4.3"
|
||||||
|
ts-api-utils "^2.5.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/types@8.59.0", "@typescript-eslint/types@^8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.59.0.tgz#cfcc643c6e879016479775850d86d84c14492738"
|
||||||
|
integrity sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==
|
||||||
|
|
||||||
|
"@typescript-eslint/typescript-estree@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz#feba58a70ab6ea7ac53a2f3ae900db28ce3454c2"
|
||||||
|
integrity sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/project-service" "8.59.0"
|
||||||
|
"@typescript-eslint/tsconfig-utils" "8.59.0"
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
"@typescript-eslint/visitor-keys" "8.59.0"
|
||||||
|
debug "^4.4.3"
|
||||||
|
minimatch "^10.2.2"
|
||||||
|
semver "^7.7.3"
|
||||||
|
tinyglobby "^0.2.15"
|
||||||
|
ts-api-utils "^2.5.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/utils@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.59.0.tgz#f50df9bd6967881ef64fba62230111153179ead5"
|
||||||
|
integrity sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==
|
||||||
|
dependencies:
|
||||||
|
"@eslint-community/eslint-utils" "^4.9.1"
|
||||||
|
"@typescript-eslint/scope-manager" "8.59.0"
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "8.59.0"
|
||||||
|
|
||||||
|
"@typescript-eslint/visitor-keys@8.59.0":
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz#2e80de30e7e944ed4bd47d751e37dcb04db03795"
|
||||||
|
integrity sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/types" "8.59.0"
|
||||||
|
eslint-visitor-keys "^5.0.0"
|
||||||
|
|
||||||
abstract-logging@^2.0.1:
|
abstract-logging@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
|
resolved "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
|
||||||
@@ -1125,7 +1226,7 @@ eslint-visitor-keys@^3.4.3:
|
|||||||
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||||
|
|
||||||
eslint-visitor-keys@^5.0.1:
|
eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be"
|
resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be"
|
||||||
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
|
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
|
||||||
@@ -1298,6 +1399,11 @@ fastq@^1.17.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
reusify "^1.0.4"
|
reusify "^1.0.4"
|
||||||
|
|
||||||
|
fdir@^6.5.0:
|
||||||
|
version "6.5.0"
|
||||||
|
resolved "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
||||||
|
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||||
|
|
||||||
file-entry-cache@^8.0.0:
|
file-entry-cache@^8.0.0:
|
||||||
version "8.0.0"
|
version "8.0.0"
|
||||||
resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
|
resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
|
||||||
@@ -1410,6 +1516,11 @@ glob@^13.0.0:
|
|||||||
minipass "^7.1.3"
|
minipass "^7.1.3"
|
||||||
path-scurry "^2.0.2"
|
path-scurry "^2.0.2"
|
||||||
|
|
||||||
|
globals@^17.5.0:
|
||||||
|
version "17.5.0"
|
||||||
|
resolved "https://registry.npmmirror.com/globals/-/globals-17.5.0.tgz#a82c641d898f8dfbe0e81f66fdff7d0de43f88c6"
|
||||||
|
integrity sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==
|
||||||
|
|
||||||
graceful-fs@^4.2.4:
|
graceful-fs@^4.2.4:
|
||||||
version "4.2.11"
|
version "4.2.11"
|
||||||
resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||||
@@ -1473,6 +1584,11 @@ ignore@^5.2.0:
|
|||||||
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
resolved "https://registry.npmmirror.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||||
|
|
||||||
|
ignore@^7.0.5:
|
||||||
|
version "7.0.5"
|
||||||
|
resolved "https://registry.npmmirror.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9"
|
||||||
|
integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==
|
||||||
|
|
||||||
imurmurhash@^0.1.4:
|
imurmurhash@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
@@ -1955,6 +2071,11 @@ pgpass@1.0.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
split2 "^4.1.0"
|
split2 "^4.1.0"
|
||||||
|
|
||||||
|
picomatch@^4.0.4:
|
||||||
|
version "4.0.4"
|
||||||
|
resolved "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||||
|
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||||
|
|
||||||
pino-abstract-transport@^3.0.0:
|
pino-abstract-transport@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23"
|
resolved "https://registry.npmmirror.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23"
|
||||||
@@ -2222,7 +2343,7 @@ secure-json-parse@^4.0.0:
|
|||||||
resolved "https://registry.npmmirror.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c"
|
resolved "https://registry.npmmirror.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c"
|
||||||
integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==
|
integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==
|
||||||
|
|
||||||
semver@^7.5.4, semver@^7.6.0:
|
semver@^7.5.4, semver@^7.6.0, semver@^7.7.3:
|
||||||
version "7.7.4"
|
version "7.7.4"
|
||||||
resolved "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
|
resolved "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
|
||||||
integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
|
integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
|
||||||
@@ -2327,6 +2448,14 @@ tinyexec@^1.0.2:
|
|||||||
resolved "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.1.1.tgz#e1ff45dfa60d1dedb91b734956b78f6c2a3e821b"
|
resolved "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.1.1.tgz#e1ff45dfa60d1dedb91b734956b78f6c2a3e821b"
|
||||||
integrity sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==
|
integrity sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==
|
||||||
|
|
||||||
|
tinyglobby@^0.2.15:
|
||||||
|
version "0.2.16"
|
||||||
|
resolved "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6"
|
||||||
|
integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==
|
||||||
|
dependencies:
|
||||||
|
fdir "^6.5.0"
|
||||||
|
picomatch "^4.0.4"
|
||||||
|
|
||||||
toad-cache@^3.7.0:
|
toad-cache@^3.7.0:
|
||||||
version "3.7.0"
|
version "3.7.0"
|
||||||
resolved "https://registry.npmmirror.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
|
resolved "https://registry.npmmirror.com/toad-cache/-/toad-cache-3.7.0.tgz#b9b63304ea7c45ec34d91f1d2fa513517025c441"
|
||||||
@@ -2346,6 +2475,11 @@ token-types@^6.1.1:
|
|||||||
"@tokenizer/token" "^0.3.0"
|
"@tokenizer/token" "^0.3.0"
|
||||||
ieee754 "^1.2.1"
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
|
ts-api-utils@^2.5.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1"
|
||||||
|
integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==
|
||||||
|
|
||||||
ts-node@^10.9.2:
|
ts-node@^10.9.2:
|
||||||
version "10.9.2"
|
version "10.9.2"
|
||||||
resolved "https://registry.npmmirror.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
|
resolved "https://registry.npmmirror.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
|
||||||
@@ -2387,6 +2521,16 @@ type-check@^0.4.0, type-check@~0.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
prelude-ls "^1.2.1"
|
prelude-ls "^1.2.1"
|
||||||
|
|
||||||
|
typescript-eslint@^8.59.0:
|
||||||
|
version "8.59.0"
|
||||||
|
resolved "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.59.0.tgz#d1cc7c63559ce7116aeb66d35ec9dbe0063379fd"
|
||||||
|
integrity sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==
|
||||||
|
dependencies:
|
||||||
|
"@typescript-eslint/eslint-plugin" "8.59.0"
|
||||||
|
"@typescript-eslint/parser" "8.59.0"
|
||||||
|
"@typescript-eslint/typescript-estree" "8.59.0"
|
||||||
|
"@typescript-eslint/utils" "8.59.0"
|
||||||
|
|
||||||
typescript@^6.0.2:
|
typescript@^6.0.2:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.npmmirror.com/typescript/-/typescript-6.0.2.tgz#0b1bfb15f68c64b97032f3d78abbf98bdbba501f"
|
resolved "https://registry.npmmirror.com/typescript/-/typescript-6.0.2.tgz#0b1bfb15f68c64b97032f3d78abbf98bdbba501f"
|
||||||
|
|||||||
Reference in New Issue
Block a user