{ "name": "api", "version": "0.0.1", "private": true, "scripts": { "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json", "prisma": "prisma", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate dev", "prisma:deploy": "prisma migrate deploy", "prisma:seed": "ts-node prisma/seed.ts", "postinstall": "prisma generate", "verify": "bash scripts/verify-env.sh", "deploy": "bash scripts/deploy.sh --production", "deploy:dev": "bash scripts/deploy.sh --development", "deploy:quick": "bash scripts/deploy.sh --production --skip-build", "deploy:check": "bash scripts/deploy.sh --production --init-check", "migrate": "bash scripts/deploy.sh --production --skip-build --skip-seed", "seed": "bash scripts/deploy.sh --production --skip-build --skip-migrate", "health": "bash scripts/healthcheck.sh", "health:init": "bash -c 'read -p \"管理员 Token: \" token; ADMIN_TOKEN=$$token bash scripts/healthcheck.sh'", "init:status": "bash -c 'read -p \"管理员 Token: \" token; curl -s -H \"Authorization: Bearer $$token\" http://localhost:3001/init/status | python3 -m json.tool 2>/dev/null || curl -s -H \"Authorization: Bearer $$token\" http://localhost:3001/init/status'", "init:run": "bash -c 'read -p \"管理员 Token: \" token; curl -s -X POST -H \"Authorization: Bearer $$token\" http://localhost:3001/init/run | python3 -m json.tool 2>/dev/null || curl -s -X POST -H \"Authorization: Bearer $$token\" http://localhost:3001/init/run'", "init:generate-keys": "bash -c 'openssl genrsa -out oauth2-private.pem 2048 && openssl rsa -pubout -in oauth2-private.pem -out oauth2-public.pem && echo \"✅ 密钥已生成:\" && echo \" 私钥: oauth2-private.pem\" && echo \" 公钥: oauth2-public.pem\" && echo \"\" && echo \"请将 PEM 内容复制到 .env 文件:\" && echo \"OAUTH2_TOKEN_SIGNING_PRIVATE_KEY=\\\"$$(cat oauth2-private.pem)\\\"\" && echo \"OAUTH2_TOKEN_SIGNING_PUBLIC_KEY=\\\"$$(cat oauth2-public.pem)\\\"\"'", "logs": "docker-compose logs -f", "logs:api": "docker-compose logs -f api", "logs:db": "docker-compose logs -f postgres", "logs:redis": "docker-compose logs -f redis", "backup": "bash scripts/backup.sh manual_$(date +%Y%m%d_%H%M%S)", "restore": "bash -c 'if [ -z \"$(BACKUP_FILE)\" ]; then echo \"❌ 请指定备份文件: pnpm run restore --BACKUP_FILE=backups/xxx.sql.gz\"; exit 1; fi; bash scripts/restore.sh \"$(BACKUP_FILE)\"'", "status": "docker-compose ps", "stats": "docker stats --no-stream", "shell": "docker-compose exec api sh", "shell:db": "docker-compose exec postgres psql -U blog linkshare", "shell:redis": "docker-compose exec redis redis-cli", "start:all": "docker-compose up -d", "stop": "docker-compose down", "restart": "docker-compose restart", "recreate": "docker-compose down -v && docker-compose up -d", "clean": "docker-compose down -v && docker system prune -f", "clean:all": "docker-compose down -v && docker rmi binglogyblog-api -f 2>/dev/null || true && docker system prune -af --volumes", "secrets": "bash -c 'echo \"SESSION_COOKIE_SECRET=$(openssl rand -base64 32)\" && echo \"OAUTH2_CLIENT_SECRET=$(openssl rand -hex 32)\" && echo \"\" && echo \"请将上述值添加到 .env 文件\"'", "cert": "bash -c 'mkdir -p ssl && openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ssl/selfsigned.key -out ssl/selfsigned.crt -subj \"/C=US/ST=State/L=City/O=Org/CN=localhost\" && echo \"✅ 证书已生成: ssl/selfsigned.crt / ssl/selfsigned.key\"'", "docs": "bash -c 'echo \"📚 文档:\" && echo \" README: ./README.md\" && echo \" 开发规范: ./AGENTS.md\" && echo \" 数据库 Schema: ./prisma/schema.prisma\" && echo \" 环境变量: ./.env.example\" && echo \" 脚本集: ./scripts/\" && echo \" API 文档: http://localhost:3001/api-docs (开发环境)\"'" }, "dependencies": { "@nestjs/bullmq": "^11.0.4", "@nestjs/common": "^11.0.1", "@nestjs/config": "^4.0.3", "@nestjs/core": "^11.0.1", "@nestjs/platform-express": "^11.0.1", "@nestjs/swagger": "^11.2.6", "@nestjs/throttler": "^6.5.0", "bcrypt": "^5.1.1", "class-validator": "^0.14.1", "class-transformer": "^0.5.1", "express-session": "^1.17.3", "jsonwebtoken": "^9.0.2", "nodemailer": "^6.9.16", "prisma": "^6.1.0", "@prisma/client": "^6.1.0", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.1", "helmet": "^7.1.0" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.18.0", "@nestjs/cli": "^11.0.0", "@nestjs/schematics": "^11.0.0", "@nestjs/testing": "^11.0.1", "@types/bcrypt": "^5.0.2", "@types/express": "^5.0.0", "@types/express-session": "^1.18.0", "@types/jsonwebtoken": "^9.0.7", "@types/jest": "^30.0.0", "@types/node": "^22.10.7", "@types/supertest": "^6.0.2", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.1", "eslint-plugin-prettier": "^5.2.2", "globals": "^16.0.0", "jest": "^30.0.0", "prettier": "^3.4.2", "source-map-support": "^0.5.21", "supertest": "^7.0.0", "ts-jest": "^29.2.5", "ts-loader": "^9.5.2", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.7.3", "typescript-eslint": "^8.20.0" } }