Compare commits
5 Commits
fix/route-
...
fix/ci-dep
| Author | SHA1 | Date | |
|---|---|---|---|
| c6e1d94510 | |||
| 8c437cd082 | |||
| 4c95de2e56 | |||
| 9d74bd2d51 | |||
| f4072ce93a |
44
.gitea/workflows/dependency-check.yml
Normal file
44
.gitea/workflows/dependency-check.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Dependency Check
|
||||
|
||||
# 依赖安全检查:生产依赖 moderate+ 或全局 critical 漏洞即失败;
|
||||
# npm outdated 作为信息输出,不阻断。
|
||||
# 注意:npmmirror 未实现 audit 接口,audit 必须显式指定官方 registry。
|
||||
|
||||
env:
|
||||
NPM_CONFIG_REGISTRY: https://registry.npmmirror.com
|
||||
NPM_CONFIG_AUDIT: "false"
|
||||
NPM_CONFIG_FUND: "false"
|
||||
NPM_CONFIG_REPLACE_REGISTRY_HOST: always
|
||||
CI: "true"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '30 2 * * 1' # 每周一 02:30 复查已发布的新漏洞
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
container: node:22.22.0-bookworm
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: https://gitee.com/mirrors_actions/checkout@v4
|
||||
with:
|
||||
github-server-url: https://git.gongxue100.com
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Audit production dependencies (moderate+)
|
||||
run: npm audit --registry=https://registry.npmjs.org --omit=dev --audit-level=moderate
|
||||
|
||||
- name: Audit all dependencies (critical only)
|
||||
run: npm audit --registry=https://registry.npmjs.org --audit-level=critical
|
||||
|
||||
- name: Outdated report (informational)
|
||||
run: npm outdated --registry=https://registry.npmjs.org || true
|
||||
@@ -75,7 +75,10 @@ jobs:
|
||||
run: |
|
||||
cd ${{ vars.REMOTE_DIR || '/opt/gongxue' }}
|
||||
sleep 3
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/api/dashboard/stats || true)"
|
||||
# 从 .env 读 PORT(默认 3000),避免硬编码端口与后端不一致
|
||||
PORT="$(grep '^PORT=' .env 2>/dev/null | cut -d= -f2- | tr -d '"' || true)"
|
||||
PORT="${PORT:-3000}"
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:${PORT}/api/dashboard/stats" || true)"
|
||||
echo "后端 HTTP 状态: ${code}(401=正常,接口需登录)"
|
||||
if [ "${code}" != "401" ] && [ "${code}" != "200" ]; then
|
||||
echo "健康检查失败:后端未按预期响应" >&2
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.1.1",
|
||||
"@ant-design/x": "^2.8.0",
|
||||
"@ant-design/x": "^2.9.0",
|
||||
"@ant-design/x-card": "^2.9.0",
|
||||
"@ant-design/x-markdown": "^2.8.0",
|
||||
"@ant-design/x-markdown": "^2.9.0",
|
||||
"@ant-design/x-sdk": "^2.8.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
@@ -26,10 +26,11 @@
|
||||
"antd": "^6.3.6",
|
||||
"axios": "^1.15.1",
|
||||
"dayjs": "^1.11.20",
|
||||
"dompurify": "^3.4.13",
|
||||
"echarts": "^6.0.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"mermaid": "^11.16.0",
|
||||
"mermaid": "^11.16.1",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-router": "^8.3.0",
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
import { config } from 'dotenv';
|
||||
import { join } from 'path';
|
||||
import { basename, join, resolve } from 'path';
|
||||
|
||||
// TypeORM CLI runs from apps/server/
|
||||
const root = process.cwd();
|
||||
// TypeORM CLI 默认在 apps/server/ 下运行,但生产环境的 .env 通常放在仓库根目录。
|
||||
// 这里先加载仓库根目录的 .env(默认),再加载当前目录(apps/server/.env)作为补充/覆盖,
|
||||
// 这样无论 .env 放哪一份,迁移 CLI 都能读到数据库配置。
|
||||
const root = resolve(process.cwd());
|
||||
const repoRoot =
|
||||
basename(root) === 'server' && basename(join(root, '..')) === 'apps'
|
||||
? resolve(root, '../..')
|
||||
: root;
|
||||
|
||||
// 先根目录,后当前目录(dotenv 默认不覆盖已存在变量,所以根目录优先级更高)
|
||||
config({ path: join(repoRoot, '.env') });
|
||||
config({ path: join(root, '.env') });
|
||||
|
||||
export default new DataSource({
|
||||
|
||||
@@ -6,7 +6,9 @@ export function toMinutes(time: string): number {
|
||||
}
|
||||
|
||||
export function getCourseClock(date: Date): { date: string; minutes: number } {
|
||||
const d = dayjs(date);
|
||||
// Asia/Shanghai 无夏令时,固定 UTC+8(与 attendance-settlement 保持一致),
|
||||
// 避免依赖服务器进程时区导致「课程是否已开始」判断漂移。
|
||||
const d = dayjs(date).utcOffset(8);
|
||||
return {
|
||||
date: d.format('YYYY-MM-DD'),
|
||||
minutes: d.hour() * 60 + d.minute(),
|
||||
|
||||
108
deploy.sh
108
deploy.sh
@@ -1,12 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# 恭学教育 — PM2 部署脚本
|
||||
# 用法: ./deploy.sh [ssh_host]
|
||||
# 用法:
|
||||
# ./deploy.sh # 本地直跑(默认,适合 runner/代码就在生产服务器上,不需要 SSH)
|
||||
# ./deploy.sh local # 同上
|
||||
# ./deploy.sh <ssh_host> # 远程部署(构建后 rsync 到远端,需要 SSH 免密/key)
|
||||
# 前提: 服务器 MySQL 已在运行,PM2 已安装
|
||||
set -euo pipefail
|
||||
|
||||
SSH_HOST="${1:-tencent}"
|
||||
MODE="${1:-local}"
|
||||
|
||||
# 校验 SSH_HOST:非空、不以 - 开头(防被 ssh/rsync 当作选项)、仅允许安全字符(防命令注入)
|
||||
# 调用锁:mkdir 原子创建,已存在即代表已有部署在跑,直接退出
|
||||
LOCK_DIR="/tmp/gongxue-deploy.lock"
|
||||
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
|
||||
echo "检测到 $LOCK_DIR,已有部署在运行。若确认没有其他部署,请手动删除该锁目录。" >&2
|
||||
exit 1
|
||||
fi
|
||||
release_deploy_lock() {
|
||||
rmdir "$LOCK_DIR" 2>/dev/null || true
|
||||
}
|
||||
trap release_deploy_lock EXIT
|
||||
|
||||
echo "=== 1/4 本地构建后端 ==="
|
||||
npm run build -w @gongxue/server
|
||||
|
||||
echo "=== 2/4 本地构建前端 ==="
|
||||
npm run build -w @gongxue/admin
|
||||
|
||||
# ── 健康检查(本地/远程共用逻辑,通过 pm2 jlist 按 name 判断 online 且无 unstable_restarts)──
|
||||
# online ≠ healthy:若后续后端提供健康端点,应优先 curl 探测。
|
||||
run_health_check() {
|
||||
set -euo pipefail
|
||||
local healthy=0
|
||||
local i
|
||||
for i in $(seq 1 15); do
|
||||
if pm2 jlist 2>/dev/null | node -e '
|
||||
let data = "";
|
||||
process.stdin.on("data", (c) => (data += c));
|
||||
process.stdin.on("end", () => {
|
||||
const apps = JSON.parse(data || "[]");
|
||||
const app = apps.find((a) => a && a.name === "gongxue-backend");
|
||||
const env = (app || {}).pm2_env || {};
|
||||
if (env.status === "online" && Number(env.unstable_restarts || 0) === 0) {
|
||||
process.exit(0);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
'; then
|
||||
healthy=1
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
if [ "${healthy}" -ne 1 ]; then
|
||||
echo "错误:后端进程未就绪(gongxue-backend 非 online 或存在不稳定重启)" >&2
|
||||
pm2 status >&2
|
||||
return 1
|
||||
fi
|
||||
echo "健康检查通过:gongxue-backend 在线"
|
||||
}
|
||||
|
||||
if [ "${MODE}" = "local" ]; then
|
||||
echo "=== 3/4 安装依赖 → 迁移 → PM2 重载(本机) ==="
|
||||
npm ci
|
||||
echo '执行数据库迁移...'
|
||||
npm run migration:run -w @gongxue/server
|
||||
echo 'PM2 重载...'
|
||||
pm2 startOrReload ecosystem.config.cjs --update-env
|
||||
pm2 save
|
||||
pm2 status
|
||||
|
||||
echo "=== 4/4 健康检查 ==="
|
||||
run_health_check
|
||||
echo ""
|
||||
echo "部署完成!后端: http://127.0.0.1:$(grep '^PORT=' .env 2>/dev/null | cut -d= -f2- | tr -d '"' || echo 3000)/api"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── 远程模式(保留,用于部署到其他主机)──
|
||||
SSH_HOST="${MODE}"
|
||||
# 校验 SSH_HOST:非空、不以 - 开头、仅允许安全字符(防注入)
|
||||
if [[ -z "${SSH_HOST}" ]]; then
|
||||
echo "错误:SSH_HOST 不能为空" >&2
|
||||
exit 1
|
||||
@@ -21,23 +93,6 @@ if [[ ! "${SSH_HOST}" =~ ^[A-Za-z0-9._:@%+=,-]+$ ]]; then
|
||||
fi
|
||||
REMOTE_DIR="/opt/gongxue"
|
||||
|
||||
# 调用锁:mkdir 原子创建,已存在即代表已有部署在跑,直接退出
|
||||
LOCK_DIR="/tmp/gongxue-deploy.lock"
|
||||
if ! mkdir "$LOCK_DIR" 2>/dev/null; then
|
||||
echo "检测到 $LOCK_DIR,已有部署在运行。若确认没有其他部署,请手动删除该锁目录。" >&2
|
||||
exit 1
|
||||
fi
|
||||
release_deploy_lock() {
|
||||
rmdir "$LOCK_DIR" 2>/dev/null || true
|
||||
}
|
||||
trap release_deploy_lock EXIT
|
||||
|
||||
echo "=== 1/5 本地构建后端 ==="
|
||||
npm run build -w @gongxue/server
|
||||
|
||||
echo "=== 2/5 本地构建前端 ==="
|
||||
npm run build -w @gongxue/admin
|
||||
|
||||
echo "=== 3/5 同步到 ${SSH_HOST} ==="
|
||||
# --delete 保留,但必须排除服务器端独有文件(.env、数据、上传目录),防止被清掉
|
||||
rsync -avz --delete \
|
||||
@@ -66,18 +121,11 @@ ssh -o BatchMode=yes -o ConnectTimeout=10 "${SSH_HOST}" "
|
||||
echo 'PM2 重载...'
|
||||
pm2 startOrReload ecosystem.config.cjs --update-env
|
||||
pm2 save
|
||||
echo '=== PM2 状态 ==='
|
||||
pm2 status
|
||||
"
|
||||
|
||||
echo "=== 5/5 健康检查 ==="
|
||||
# 后端未提供 /api/health 等专用健康端点,改用 pm2 jlist(JSON)按 name 查找 gongxue-backend:
|
||||
# 判断 status === 'online' 且 unstable_restarts === 0。
|
||||
# 说明:
|
||||
# - restart_time 是累计重启次数(正常滚动/长期运行也会累计),不适合做健康阈值,改用 unstable_restarts。
|
||||
# - online ≠ healthy:online 只代表 PM2 认为进程存活;若后续后端提供健康端点,应优先 curl 探测。
|
||||
# 带重试以覆盖 PM2 reload 的 listen_timeout(8s)窗口;应用不在线则 exit 1,部署失败。
|
||||
if ! ssh -o BatchMode=yes -o ConnectTimeout=10 "${SSH_HOST}" bash -s <<'REMOTE_HEALTH'
|
||||
ssh -o BatchMode=yes -o ConnectTimeout=10 "${SSH_HOST}" bash -s <<'REMOTE_HEALTH'
|
||||
set -euo pipefail
|
||||
HEALTHY=0
|
||||
for _i in $(seq 1 15); do
|
||||
@@ -106,10 +154,6 @@ if [ "${HEALTHY}" -ne 1 ]; then
|
||||
fi
|
||||
echo "健康检查通过:gongxue-backend 在线"
|
||||
REMOTE_HEALTH
|
||||
then
|
||||
echo "错误:健康检查失败,部署中止" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "部署完成!"
|
||||
|
||||
214
package-lock.json
generated
214
package-lock.json
generated
@@ -21,9 +21,9 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.1.1",
|
||||
"@ant-design/x": "^2.8.0",
|
||||
"@ant-design/x": "^2.9.0",
|
||||
"@ant-design/x-card": "^2.9.0",
|
||||
"@ant-design/x-markdown": "^2.8.0",
|
||||
"@ant-design/x-markdown": "^2.9.0",
|
||||
"@ant-design/x-sdk": "^2.8.0",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
@@ -33,10 +33,11 @@
|
||||
"antd": "^6.3.6",
|
||||
"axios": "^1.15.1",
|
||||
"dayjs": "^1.11.20",
|
||||
"dompurify": "^3.4.13",
|
||||
"echarts": "^6.0.0",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"mermaid": "^11.16.0",
|
||||
"mermaid": "^11.16.1",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-router": "^8.3.0",
|
||||
@@ -65,6 +66,103 @@
|
||||
"vitest": "^4.1.10"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/@ant-design/x": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmmirror.com/@ant-design/x/-/x-2.9.0.tgz",
|
||||
"integrity": "sha512-m3N2nprrPG/D0n93B/fBFhjpvSaJAb2IDF6w0rX0ycYXSGxtgrJQvqSI33Jhx6gxUHj495zdIzqA1NMFld9iQA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^8.0.0",
|
||||
"@ant-design/cssinjs": "^2.0.1",
|
||||
"@ant-design/cssinjs-utils": "^2.0.2",
|
||||
"@ant-design/fast-color": "^3.0.0",
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@babel/runtime": "^7.25.6",
|
||||
"@rc-component/motion": "^1.1.6",
|
||||
"@rc-component/resize-observer": "^1.0.1",
|
||||
"@rc-component/util": "^1.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"mermaid": "^11.12.1",
|
||||
"react-syntax-highlighter": "^16.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ant-design"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^6.1.1",
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/@ant-design/x-markdown": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmmirror.com/@ant-design/x-markdown/-/x-markdown-2.9.0.tgz",
|
||||
"integrity": "sha512-IwYUky9Fi3y86wouFQ3rjx/DyKFUm/eAidiU/leVD0u6hAfN4INDWltWuZqe1FRRwOE7DJdSxweDyD6+/B6oQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.1",
|
||||
"dompurify": "^3.2.6",
|
||||
"html-react-parser": "^5.2.13",
|
||||
"katex": "^0.16.22",
|
||||
"marked": "^15.0.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/dompurify": {
|
||||
"version": "3.4.13",
|
||||
"resolved": "https://registry.npmmirror.com/dompurify/-/dompurify-3.4.13.tgz",
|
||||
"integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/mermaid": {
|
||||
"version": "11.16.1",
|
||||
"resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.16.1.tgz",
|
||||
"integrity": "sha512-TQsq6u22fAn3rek5VOubrhKPo1g5hwC3FXUN9hiyupTckcYiGuuKGkNQrKYwGJkXUxZdojwRG46gsSCFZMDp4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.1.2",
|
||||
"@iconify/utils": "^3.0.2",
|
||||
"@mermaid-js/parser": "^1.2.0",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@upsetjs/venn.js": "^2.0.0",
|
||||
"cytoscape": "^3.33.3",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.2.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"dagre-d3-es": "7.0.14",
|
||||
"dayjs": "^1.11.20",
|
||||
"dompurify": "^3.3.3",
|
||||
"es-toolkit": "^1.45.1",
|
||||
"katex": "^0.16.45",
|
||||
"khroma": "^2.1.0",
|
||||
"marked": "^16.3.0",
|
||||
"roughjs": "^4.6.6",
|
||||
"stylis": "^4.3.6",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/mermaid/node_modules/marked": {
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmmirror.com/marked/-/marked-16.4.2.tgz",
|
||||
"integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"apps/admin/node_modules/react-router": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/react-router/-/react-router-8.3.0.tgz",
|
||||
@@ -553,36 +651,6 @@
|
||||
"react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ant-design/x": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/x/-/x-2.8.0.tgz",
|
||||
"integrity": "sha512-z0ncy8i3sy8fnFS1iETTQfP2Os1kzOl5OPdljT5ZFSCDsZp+VYFt9jHHMacBnkEftKNzkmG1BLSwvBTS1aWxiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^8.0.0",
|
||||
"@ant-design/cssinjs": "^2.0.1",
|
||||
"@ant-design/cssinjs-utils": "^2.0.2",
|
||||
"@ant-design/fast-color": "^3.0.0",
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@babel/runtime": "^7.25.6",
|
||||
"@rc-component/motion": "^1.1.6",
|
||||
"@rc-component/resize-observer": "^1.0.1",
|
||||
"@rc-component/util": "^1.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"mermaid": "^11.12.1",
|
||||
"react-syntax-highlighter": "^16.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ant-design"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^6.1.1",
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ant-design/x-card": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmmirror.com/@ant-design/x-card/-/x-card-2.9.0.tgz",
|
||||
@@ -599,23 +667,6 @@
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ant-design/x-markdown": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/x-markdown/-/x-markdown-2.8.0.tgz",
|
||||
"integrity": "sha512-QRS0s81ykVt8RLqf9nGHJmP/y8hNQgQZdu7+7x+EMS5VuPBeQw74IpIUNchVLQy/P60VoNpkw+YTalyJtyLPPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.1",
|
||||
"dompurify": "^3.2.6",
|
||||
"html-react-parser": "^5.2.13",
|
||||
"katex": "^0.16.22",
|
||||
"marked": "^15.0.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ant-design/x-sdk": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@ant-design/x-sdk/-/x-sdk-2.8.0.tgz",
|
||||
@@ -10085,15 +10136,6 @@
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.4.12",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz",
|
||||
"integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||
@@ -14394,60 +14436,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mermaid": {
|
||||
"version": "11.16.0",
|
||||
"resolved": "https://registry.npmmirror.com/mermaid/-/mermaid-11.16.0.tgz",
|
||||
"integrity": "sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.1.2",
|
||||
"@iconify/utils": "^3.0.2",
|
||||
"@mermaid-js/parser": "^1.2.0",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@upsetjs/venn.js": "^2.0.0",
|
||||
"cytoscape": "^3.33.3",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.2.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
"dagre-d3-es": "7.0.14",
|
||||
"dayjs": "^1.11.20",
|
||||
"dompurify": "^3.3.3",
|
||||
"es-toolkit": "^1.45.1",
|
||||
"katex": "^0.16.45",
|
||||
"khroma": "^2.1.0",
|
||||
"marked": "^16.3.0",
|
||||
"roughjs": "^4.6.6",
|
||||
"stylis": "^4.3.6",
|
||||
"ts-dedent": "^2.2.0",
|
||||
"uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid/node_modules/marked": {
|
||||
"version": "16.4.2",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz",
|
||||
"integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/mermaid/node_modules/uuid": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
|
||||
"integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "dist-node/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.54.0",
|
||||
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
},
|
||||
"minimatch@10.2.5": {
|
||||
"brace-expansion": "^5.0.9"
|
||||
}
|
||||
},
|
||||
"dompurify": "^3.4.13"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user