Files
2026-06-06 10:40:48 +08:00

1 line
25 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"projectName":"PetCare","domain":"pet","contract":{"projectName":"PetCare","domain":"pet","entities":[{"name":"User","table":"users","description":"系统用户","fields":[{"name":"id","type":"UUID","isPrimary":true,"isAuto":true},{"name":"username","type":"VARCHAR(128)","required":true,"unique":true,"validation":{"minLength":2,"maxLength":50}},{"name":"password_hash","type":"VARCHAR(256)","required":true,"isSecret":true},{"name":"nickname","type":"VARCHAR(128)"},{"name":"role","type":"VARCHAR(32)","defaultValue":"user","enum":["user","admin"]},{"name":"phone","type":"VARCHAR(20)"},{"name":"avatar_url","type":"TEXT"},{"name":"created_at","type":"TIMESTAMP","isAuto":true},{"name":"updated_at","type":"TIMESTAMP","isAuto":true}],"relationships":[]},{"name":"Pet","table":"pets","description":"宠物","fields":[{"name":"id","type":"UUID","isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":true,"fkEntity":"users","fkColumn":"id"},{"name":"name","type":"VARCHAR(64)","required":true},{"name":"species","type":"VARCHAR(32)"},{"name":"breed","type":"VARCHAR(64)"},{"name":"birth_date","type":"DATE"},{"name":"weight_kg","type":"DECIMAL(5,2)"},{"name":"avatar_url","type":"TEXT"},{"name":"created_at","type":"TIMESTAMP","isAuto":true},{"name":"updated_at","type":"TIMESTAMP","isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]},{"name":"Schedules","table":"schedules","description":"疫苗提醒、驱虫提醒、体检预约表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"course_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"courses","fkColumn":"id"},{"name":"classroom_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"classrooms","fkColumn":"id"},{"name":"instructor_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"instructors","fkColumn":"id"},{"name":"day_of_week","type":"INTEGER","required":false,"isPrimary":false,"isAuto":false},{"name":"start_time","type":"TIME","required":false,"isPrimary":false,"isAuto":false},{"name":"end_time","type":"TIME","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"},{"type":"belongsTo","entity":"courses","via":"course_id"},{"type":"belongsTo","entity":"classrooms","via":"classroom_id"},{"type":"belongsTo","entity":"instructors","via":"instructor_id"}]},{"name":"Records","table":"records","description":"饮食、运动、排泄、体重变化记录表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"title","type":"VARCHAR(256)","required":true,"isPrimary":false,"isAuto":false},{"name":"description","type":"TEXT","required":false,"isPrimary":false,"isAuto":false},{"name":"status","type":"VARCHAR(32)","required":false,"isPrimary":false,"isAuto":true},{"name":"data","type":"JSONB","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]},{"name":"Albums","table":"albums","description":"按时间线记录宠物成长照片表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"title","type":"VARCHAR(128)","required":false,"isPrimary":false,"isAuto":false},{"name":"image_url","type":"TEXT","required":true,"isPrimary":false,"isAuto":false},{"name":"caption","type":"TEXT","required":false,"isPrimary":false,"isAuto":false},{"name":"taken_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]},{"name":"Hospitals","table":"hospitals","description":"地图显示附近宠物医院,支持预约挂号表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"name","type":"VARCHAR(128)","required":true,"isPrimary":false,"isAuto":false},{"name":"address","type":"TEXT","required":false,"isPrimary":false,"isAuto":false},{"name":"phone","type":"VARCHAR(20)","required":false,"isPrimary":false,"isAuto":false},{"name":"rating","type":"DECIMAL(2,1)","required":false,"isPrimary":false,"isAuto":false},{"name":"lat","type":"DECIMAL(9,6)","required":false,"isPrimary":false,"isAuto":false},{"name":"lng","type":"DECIMAL(9,6)","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]},{"name":"Items","table":"items","description":"常见宠物疾病、护理知识库表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"title","type":"VARCHAR(256)","required":true,"isPrimary":false,"isAuto":false},{"name":"description","type":"TEXT","required":false,"isPrimary":false,"isAuto":false},{"name":"status","type":"VARCHAR(32)","required":false,"isPrimary":false,"isAuto":true},{"name":"data","type":"JSONB","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]},{"name":"Daily-logs","table":"daily-logs","description":"daily-logs表","fields":[{"name":"id","type":"UUID","required":true,"isPrimary":true,"isAuto":true},{"name":"user_id","type":"UUID","required":false,"isPrimary":false,"isAuto":false,"fkEntity":"users","fkColumn":"id"},{"name":"title","type":"VARCHAR(256)","required":true,"isPrimary":false,"isAuto":false},{"name":"data","type":"JSONB","required":false,"isPrimary":false,"isAuto":false},{"name":"created_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true},{"name":"updated_at","type":"TIMESTAMPTZ","required":false,"isPrimary":false,"isAuto":true}],"relationships":[{"type":"belongsTo","entity":"users","via":"user_id"}]}],"auth":{"registrationFields":["username","password","nickname"],"loginFields":["username","password"],"jwtPayload":["userId","username","role"],"passwordPolicy":{"minLength":6,"requireSpecial":false}},"permissions":[{"role":"admin","allow":["*"]},{"role":"user","allow":["read:own","create:*","update:own","delete:own"]}],"fieldMapping":{"snakeToCamel":{"created_at":"createdAt","updated_at":"updatedAt","user_id":"userId","password_hash":"passwordHash","avatar_url":"avatarUrl","birth_date":"birthDate","weight_kg":"weightKg","course_id":"courseId","classroom_id":"classroomId","instructor_id":"instructorId","day_of_week":"dayOfWeek","start_time":"startTime","end_time":"endTime","image_url":"imageUrl","taken_at":"takenAt","id":"id","username":"username","nickname":"nickname","role":"role","phone":"phone","title":"title","description":"description","status":"status","data":"data","amount":"amount","party_a":"partyA","party_b":"partyB","signed_at":"signedAt","expires_at":"expiresAt","file_url":"fileUrl","entity_type":"entityType","entity_id":"entityId","applicant_id":"applicantId","form_data":"formData","name":"name","email":"email","company":"company","source":"source","tags":"tags","breed":"breed","species":"species","price":"price","stock":"stock","images":"images","total_amount":"totalAmount","address_id":"addressId","remind_at":"remindAt","message":"message","sent":"sent"},"camelToSnake":{"createdAt":"created_at","updatedAt":"updated_at","userId":"user_id","passwordHash":"password_hash","avatarUrl":"avatar_url","birthDate":"birth_date","weightKg":"weight_kg","courseId":"course_id","classroomId":"classroom_id","instructorId":"instructor_id","dayOfWeek":"day_of_week","startTime":"start_time","endTime":"end_time","imageUrl":"image_url","takenAt":"taken_at","id":"id","username":"username","nickname":"nickname","role":"role","phone":"phone","title":"title","description":"description","status":"status","data":"data","amount":"amount","partyA":"party_a","partyB":"party_b","signedAt":"signed_at","expiresAt":"expires_at","fileUrl":"file_url","entityType":"entity_type","entityId":"entity_id","applicantId":"applicant_id","formData":"form_data","name":"name","email":"email","company":"company","source":"source","tags":"tags","breed":"breed","species":"species","price":"price","stock":"stock","images":"images","totalAmount":"total_amount","addressId":"address_id","remindAt":"remind_at","message":"message","sent":"sent"}},"validation":{"User":{"username":{"minLength":2,"maxLength":50,"required":true,"unique":true},"password_hash":{"required":true},"role":{"enum":["user","admin"],"defaultValue":"user"}},"Pet":{"user_id":{"required":true},"name":{"required":true}},"Schedules":{"id":{"required":true}},"Records":{"id":{"required":true},"title":{"required":true}},"Albums":{"id":{"required":true},"image_url":{"required":true}},"Hospitals":{"id":{"required":true},"name":{"required":true}},"Items":{"id":{"required":true},"title":{"required":true}},"Daily-logs":{"id":{"required":true},"title":{"required":true}}}},"techStack":{"frontend":"React Native 0.76 + Expo / Flutter 3.x","backend":"NestJS + Prisma","database":"PostgreSQL 15 + Redis 7 + MinIO(文件存储)","deployment":"Docker Compose + Nginx / K8s(规模化)","considerations":[]},"architectureDiagram":"┌─────────────────────────────────────────────────────────┐\n│ PetCare — System Architecture │\n├─────────────────────────────────────────────────────────┤\n│ │\n│ ┌──────────────────────┐ ┌──────────────────────┐ │\n│ │ Client Layer │ │ Admin / Web │ │\n│ │ React Native 0.76 + Expo / Flutter 3.x │ │ React + Vite (Web) │ │\n│ └──────────┬───────────┘ └──────────┬───────────┘ │\n│ │ │ │\n│ └──────────┬────────────────┘ │\n│ │ │\n│ ┌─────────▼──────────┐ │\n│ │ API Gateway │ │\n│ │ Nginx / Kong │ │\n│ └─────────┬──────────┘ │\n│ │ │\n│ ┌─────────▼──────────┐ │\n│ │ Backend Services │ │\n│ │ NestJS + Prisma │ │\n│ └─────────┬──────────┘ │\n│ │ │\n│ ┌───────────────┼───────────────┐ │\n│ │ │ │ │\n│ ┌─────▼─────┐ ┌──────▼──────┐ ┌────▼─────┐ │\n│ │ PostgreSQL 15│ │ Redis Cache │ │ MinIO │ │\n│ │ Primary │ │ Session │ │ Files │ │\n│ └───────────┘ └─────────────┘ └──────────┘ │\n│ │\n├─────────────────────────────────────────────────────────┤\n│ Modules: │\n│ 1 宠物档案 │\n│ 2 Schedule │\n│ 3 日常记录 │\n│ 4 Storage │\n│ 5 附近医院 │\n│ 6 健康百科 │\n│ │\n└─────────────────────────────────────────────────────────┘","dataFlows":[{"page":"宠物档案","route":"/pets","description":"记录宠物的基本信息、品种、年龄、体重","dataFlow":["POST /api/pets → 添加宠物档案","GET /api/pets/:id → 获取宠物详情"],"direction":"Client → API Gateway → Backend → Database → Response → Client"},{"page":"健康日程","route":"/schedules","description":"疫苗提醒、驱虫提醒、体检预约","dataFlow":["GET /api/schedules → 获取健康日程列表","POST /api/schedules → 创建健康日程"],"direction":"Client → API Gateway → Backend → Database → Response → Client"},{"page":"成长相册","route":"/albums","description":"按时间线记录宠物成长照片","dataFlow":["POST /api/albums → 上传宠物照片"],"direction":"Client → API Gateway → Backend → Database → Response → Client"}],"modules":[{"name":"宠物档案","label":"宠物档案","features":["宠物档案"],"responsibilities":["提供 宠物档案 相关功能"]},{"name":"schedule","label":"Schedule","features":["健康日程"],"responsibilities":["提供 健康日程 相关功能"]},{"name":"日常记录","label":"日常记录","features":["日常记录"],"responsibilities":["提供 日常记录 相关功能"]},{"name":"storage","label":"Storage","features":["成长相册"],"responsibilities":["提供 成长相册 相关功能"]},{"name":"附近医院","label":"附近医院","features":["附近医院"],"responsibilities":["提供 附近医院 相关功能"]},{"name":"健康百科","label":"健康百科","features":["健康百科"],"responsibilities":["提供 健康百科 相关功能"]},{"name":"content","label":"Content","features":["社区分享"],"responsibilities":["提供 社区分享 相关功能"]},{"name":"pet","label":"宠物管理","features":["宠物档案","健康日程"],"responsibilities":["提供 宠物档案 相关功能","提供 健康日程 相关功能"]}],"databaseSchema":[{"table":"users","description":"用户表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"phone","type":"VARCHAR(20)","constraints":"UNIQUE"},{"name":"nickname","type":"VARCHAR(64)"},{"name":"avatar_url","type":"TEXT"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_users_phone ON users(phone)"]},{"table":"pets","description":"记录宠物的基本信息、品种、年龄、体重表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"name","type":"VARCHAR(64)","constraints":"NOT NULL"},{"name":"species","type":"VARCHAR(32)"},{"name":"breed","type":"VARCHAR(64)"},{"name":"birth_date","type":"DATE"},{"name":"weight_kg","type":"DECIMAL(5,2)"},{"name":"avatar_url","type":"TEXT"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_pets_user ON pets(user_id)"]},{"table":"schedules","description":"疫苗提醒、驱虫提醒、体检预约表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"course_id","type":"UUID","constraints":"FK → courses.id"},{"name":"classroom_id","type":"UUID","constraints":"FK → classrooms.id"},{"name":"instructor_id","type":"UUID","constraints":"FK → users.id"},{"name":"day_of_week","type":"INTEGER","constraints":"CHECK (day_of_week >= 0 AND day_of_week <= 6)"},{"name":"start_time","type":"TIME"},{"name":"end_time","type":"TIME"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_schedules_user ON schedules(user_id)"]},{"table":"records","description":"饮食、运动、排泄、体重变化记录表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"title","type":"VARCHAR(256)","constraints":"NOT NULL"},{"name":"description","type":"TEXT"},{"name":"status","type":"VARCHAR(32)","constraints":"DEFAULT 'active'"},{"name":"data","type":"JSONB"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_records_user ON records(user_id)"]},{"table":"albums","description":"按时间线记录宠物成长照片表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"title","type":"VARCHAR(128)"},{"name":"image_url","type":"TEXT","constraints":"NOT NULL"},{"name":"caption","type":"TEXT"},{"name":"taken_at","type":"TIMESTAMPTZ"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_albums_user ON albums(user_id)"]},{"table":"hospitals","description":"地图显示附近宠物医院,支持预约挂号表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"name","type":"VARCHAR(128)","constraints":"NOT NULL"},{"name":"address","type":"TEXT"},{"name":"phone","type":"VARCHAR(20)"},{"name":"rating","type":"DECIMAL(2,1)"},{"name":"lat","type":"DECIMAL(9,6)"},{"name":"lng","type":"DECIMAL(9,6)"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_hospitals_user ON hospitals(user_id)"]},{"table":"items","description":"常见宠物疾病、护理知识库表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"title","type":"VARCHAR(256)","constraints":"NOT NULL"},{"name":"description","type":"TEXT"},{"name":"status","type":"VARCHAR(32)","constraints":"DEFAULT 'active'"},{"name":"data","type":"JSONB"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}],"indexes":["idx_items_user ON items(user_id)"]},{"table":"daily-logs","description":"daily-logs表","fields":[{"name":"id","type":"UUID","constraints":"PK, DEFAULT gen_random_uuid()"},{"name":"user_id","type":"UUID","constraints":"FK → users.id"},{"name":"title","type":"VARCHAR(256)","constraints":"NOT NULL"},{"name":"data","type":"JSONB"},{"name":"created_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"},{"name":"updated_at","type":"TIMESTAMPTZ","constraints":"DEFAULT NOW()"}]}],"apiDesign":[{"resource":"albums","basePath":"/api/albums","endpoints":[{"method":"POST","path":"/api/albums","description":"上传宠物照片"}]},{"resource":"daily-logs","basePath":"/api/daily-logs","endpoints":[{"method":"POST","path":"/api/daily-logs","description":"记录日常活动"},{"method":"GET","path":"/api/daily-logs","description":"查询日常记录"}]},{"resource":"hospitals","basePath":"/api/hospitals","endpoints":[{"method":"GET","path":"/api/hospitals","description":"查询附近医院"}]},{"resource":"pets","basePath":"/api/pets","endpoints":[{"method":"POST","path":"/api/pets","description":"添加宠物档案"},{"method":"GET","path":"/api/pets/:id","description":"获取宠物详情"},{"method":"PUT","path":"/api/pets/:id","description":"更新宠物信息"}]},{"resource":"schedules","basePath":"/api/schedules","endpoints":[{"method":"GET","path":"/api/schedules","description":"获取健康日程列表"},{"method":"POST","path":"/api/schedules","description":"创建健康日程"}]}],"directoryStructure":["petcare/","├── apps/","│ ├── mobile/ # React Native / Flutter 移动端","│ │ ├── src/","│ │ │ ├── screens/ # 页面组件","│ │ │ │ ├── 宠物档案/","│ │ │ │ ├── schedule/","│ │ │ │ ├── 日常记录/","│ │ │ │ ├── storage/","│ │ │ ├── components/ # 通用组件","│ │ │ ├── hooks/ # 自定义 Hooks","│ │ │ ├── services/ # API 调用层","│ │ │ ├── store/ # 状态管理","│ │ │ └── utils/ # 工具函数","│ │ ├── app.json","│ │ └── package.json","│ └── web/ # Web 管理后台","│ ├── src/","│ │ ├── pages/","│ │ ├── components/","│ │ └── layouts/","│ └── package.json","├── packages/","│ └── shared/ # 共享类型/常量","├── server/ # NestJS 后端服务","│ ├── src/","│ │ ├── modules/ # 业务模块","│ │ │ ├── 宠物档案/","│ │ │ │ ├── 宠物档案.controller.ts","│ │ │ │ ├── 宠物档案.service.ts","│ │ │ │ ├── 宠物档案.module.ts","│ │ │ │ └── dto/","│ │ │ ├── schedule/","│ │ │ │ ├── schedule.controller.ts","│ │ │ │ ├── schedule.service.ts","│ │ │ │ ├── schedule.module.ts","│ │ │ │ └── dto/","│ │ │ ├── 日常记录/","│ │ │ │ ├── 日常记录.controller.ts","│ │ │ │ ├── 日常记录.service.ts","│ │ │ │ ├── 日常记录.module.ts","│ │ │ │ └── dto/","│ │ │ ├── storage/","│ │ │ │ ├── storage.controller.ts","│ │ │ │ ├── storage.service.ts","│ │ │ │ ├── storage.module.ts","│ │ │ │ └── dto/","│ │ │ ├── 附近医院/","│ │ │ │ ├── 附近医院.controller.ts","│ │ │ │ ├── 附近医院.service.ts","│ │ │ │ ├── 附近医院.module.ts","│ │ │ │ └── dto/","│ │ ├── common/ # 通用(guards, filters, interceptors","│ │ ├── prisma/ # Prisma ORM","│ │ │ └── schema.prisma","│ │ ├── config/ # 环境配置","│ │ └── main.ts","│ ├── test/","│ ├── Dockerfile","│ └── package.json","├── docker-compose.yml","├── .github/workflows/ # CI/CD","│ └── ci.yml","├── .env.example","├── README.md","└── turbo.json # Monorepo 配置"],"deployment":{"environments":["development","staging","production"],"strategy":"Docker Compose + Nginx / K8s(规模化)","services":["API Server (NestJS)","PostgreSQL 15","Redis 7"],"ci":"GitHub Actions → Build → Test → Deploy"},"meta":{"generatedAt":"2026-06-05T22:08:33.517Z","sourceDomain":"pet","moduleCount":8,"tableCount":8,"apiEndpointCount":9}}