chore: migrate to pnpm workspaces monorepo with Turborepo
- Restructure directories: apps/api, apps/admin, apps/website - Add root pnpm-workspace.yaml, turbo.json, .prettierrc, .gitignore - Rename packages to @inkreach/api, @inkreach/admin, @inkreach/website - Add shared packages: packages/tsconfig, packages/shared-types - Add pnpm.onlyBuiltDependencies for native builds - Update docs: README.md, structs.md - All three projects build successfully
This commit is contained in:
+48
-35
@@ -1,45 +1,49 @@
|
||||
# InkReach Product Center — Monorepo Structure
|
||||
|
||||
> 全局根目录结构说明。三个子项目独立维护各自 `package.json` 与技术栈,通过约定的端口协同工作。
|
||||
> pnpm workspaces + Turborepo 统一管理三个子项目与共享包。所有子项目位于 `apps/`,共享代码位于 `packages/`。
|
||||
|
||||
## 根目录
|
||||
|
||||
```
|
||||
inkreach-official/
|
||||
├── .agents/ # AI Agent 共享技能(brainstorming / TDD / git-spec / ...)
|
||||
├── apps/
|
||||
│ ├── api/ # NestJS 后端 (package: @inkreach/api)
|
||||
│ ├── admin/ # Vue 3 后台 (package: @inkreach/admin)
|
||||
│ └── website/ # Nuxt 4 官网 (package: @inkreach/website)
|
||||
├── packages/
|
||||
│ ├── tsconfig/ # 共享 TypeScript 配置 (base / api / vue)
|
||||
│ └── shared-types/ # 共享类型定义(PaginatedResult, BackendEnvelope, 实体接口)
|
||||
├── .agents/ # AI Agent 共享技能
|
||||
├── docs/ # 跨子项目文档
|
||||
│ ├── dev/ # 设计文档(数据库表设计、PRD、原型图)
|
||||
│ │ ├── database-table-design.md
|
||||
│ │ ├── product-center-prd.md
|
||||
│ │ └── product-center-{1,2,3}.png
|
||||
│ ├── references/
|
||||
│ │ └── structs.md # 本文件
|
||||
│ └── superpowers/specs/ # superpowers 规格说明
|
||||
├── plans/ # 跨子项目计划
|
||||
│ └── feature/
|
||||
├── AGENTS.md # 根级 AI Agent 开发规范
|
||||
├── skills-lock.json # 技能版本锁定
|
||||
├── package.json # 根 workspace 配置(scripts + devDependencies)
|
||||
├── pnpm-workspace.yaml # pnpm workspace 定义(apps/*, packages/*)
|
||||
├── turbo.json # Turborepo 任务流水线
|
||||
├── .prettierrc # 统一代码格式化
|
||||
├── .gitignore # 全局忽略规则
|
||||
├── .env # 根级环境变量(DATABASE_URL 等)
|
||||
├── .git/ # 单一 Git 仓库,trunk-based
|
||||
├── inkreach-official-nestjs/ # 子项目 1:NestJS 后端
|
||||
├── inkreach-official-admin/ # 子项目 2:Vue 3 后台
|
||||
└── inkreach-official-website/ # 子项目 3:Nuxt 4 官网
|
||||
├── AGENTS.md # 根级 AI Agent 开发规范
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## 端口与子项目
|
||||
|
||||
| 子项目 | 端口 | 启动命令 | 说明 |
|
||||
|--------|------|----------|------|
|
||||
| inkreach-official-nestjs | 3001 | `npm run start:dev` | NestJS + Prisma + PostgreSQL 后端 API;Swagger 文档 `/api/docs` |
|
||||
| inkreach-official-admin | 5173 | `npm run dev` | Vue 3 + Element Plus 后台管理;通过 Vite proxy `/api → :3001` |
|
||||
| inkreach-official-website | 3000 | `npm run dev` | Nuxt 4 官网;通过 Nitro `server/api/backend/*` 代理 `:3001` |
|
||||
| 子项目 | 包名 | 端口 | 启动命令 | 说明 |
|
||||
|--------|------|------|----------|------|
|
||||
| `apps/api` | `@inkreach/api` | 3001 | `pnpm --filter @inkreach/api start:dev` | NestJS + Prisma + PostgreSQL 后端 API;Swagger 文档 `/api/docs` |
|
||||
| `apps/admin` | `@inkreach/admin` | 5173 | `pnpm --filter @inkreach/admin dev` | Vue 3 + Element Plus 后台管理;通过 Vite proxy `/api → :3001` |
|
||||
| `apps/website` | `@inkreach/website` | 3000 | `pnpm --filter @inkreach/website dev` | Nuxt 4 官网;通过 Nitro `server/api/backend/*` 代理 `:3001` |
|
||||
|
||||
启动顺序:先启动 `inkreach-official-nestjs`,再启动另两个。
|
||||
启动顺序:先启动 `apps/api`,再启动另两个。
|
||||
|
||||
## 子项目 1:inkreach-official-nestjs(后端)
|
||||
## 子项目 1:apps/api(后端,@inkreach/api)
|
||||
|
||||
```
|
||||
inkreach-official-nestjs/
|
||||
apps/api/
|
||||
├── prisma/
|
||||
│ ├── schema.prisma # 数据模型(OriginGood/Country/Category/Tag/Position/Good/User/SyncLog)
|
||||
│ └── migrations/ # Prisma migrate 历史
|
||||
@@ -51,6 +55,7 @@ inkreach-official-nestjs/
|
||||
│ ├── countries/ # 国家 CRUD(受 JWT 保护)
|
||||
│ ├── categories/ # 品类 CRUD(受 JWT 保护,自引用树)
|
||||
│ ├── tags/ # 标签 CRUD(受 JWT 保护)
|
||||
│ ├── tag-groups/ # 标签分组 CRUD(受 JWT 保护,含批量排序)
|
||||
│ ├── positions/ # 坑位 CRUD(受 JWT 保护)
|
||||
│ ├── origin-goods/ # SDS 原始商品快照(只读分页)
|
||||
│ ├── goods/ # 商品 CRUD + 批量优先级 + 批量创建
|
||||
@@ -75,7 +80,8 @@ inkreach-official-nestjs/
|
||||
| `OriginGood` | SDS 原始商品缓存,关联 `sds_good_id`(唯一) |
|
||||
| `Country` | 国家,关联 goods / positions |
|
||||
| `Category` | 自引用树形品类,可选 `sds_category_id` |
|
||||
| `Tag` | 标签,含 `tagColor`、`timing` |
|
||||
| `Tag` | 标签,含 `tagColor`、`tagFontColor`、`tagGroupId`、`sortOrder`、`timing` |
|
||||
| `TagGroup` | 标签分组(含 `groupName`、`groupColor`、`groupIcon`、`sortOrder`),删除分组时组内 tag 的 `tagGroupId` 通过 `onDelete: SetNull` 自动置空 |
|
||||
| `Position` | 坑位:`(country, category)` 维度,关联多个 goods |
|
||||
| `Good` | 商品:`originGood × country × category × tag? × position?`,含 `goodPriority` |
|
||||
| `User` | 后台用户(bcrypt 哈希) |
|
||||
@@ -98,9 +104,13 @@ inkreach-official-nestjs/
|
||||
| `/auth/login` `POST` | 登录获取 JWT | 公开 |
|
||||
| `/public/categories` `GET` | 公开品类树(仅含已挂商品的品类) | 公开 |
|
||||
| `/public/countries` `GET` | 公开国家列表(仅含已挂商品的国家) | 公开 |
|
||||
| `/public/goods` `GET` | 分页商品(支持 `countryId/categoryId/tagId/keyword/page/pageSize`) | 公开 |
|
||||
| `/public/tags` `GET` | 公开标签列表(带 `group` 字段,按 group 排序) | 公开 |
|
||||
| `/public/tag-groups` `GET` | 公开标签分组列表 | 公开 |
|
||||
| `/public/goods` `GET` | 分页商品(支持 `countryId/categoryId/tagIds(逗号分隔)/keyword/page/pageSize`,`tagIds` 为 AND 关系) | 公开 |
|
||||
| `/public/goods/:id` `GET` | 商品详情 | 公开 |
|
||||
| `/categories` `/tags` `/countries` `/positions` | 后台 CRUD | JWT |
|
||||
| `/categories` `/tags` `/tag-groups` `/countries` `/positions` | 后台 CRUD | JWT |
|
||||
| `/tags/sort` `PATCH` | 批量更新 tag 排序和分组归属 | JWT |
|
||||
| `/tag-groups/sort` `PATCH` | 批量更新分组排序 | JWT |
|
||||
| `/origin-goods` `GET` | SDS 原始商品快照分页 | JWT |
|
||||
| `/goods` | 后台商品 CRUD + `POST /goods/batch` + `PATCH /goods/batch-priority` | JWT |
|
||||
| `/sync/categories` `POST` | 手动触发分类同步 | JWT |
|
||||
@@ -108,10 +118,10 @@ inkreach-official-nestjs/
|
||||
| `/sync/status` `GET` | 最近同步日志(`?limit=20`) | JWT |
|
||||
| `/api/docs` | Swagger UI | 公开 |
|
||||
|
||||
## 子项目 2:inkreach-official-admin(后台)
|
||||
## 子项目 2:apps/admin(后台,@inkreach/admin)
|
||||
|
||||
```
|
||||
inkreach-official-admin/
|
||||
apps/admin/
|
||||
├── public/ # 静态资源
|
||||
├── src/
|
||||
│ ├── main.ts # 入口:Pinia + Vue Router + ElementPlus
|
||||
@@ -123,7 +133,8 @@ inkreach-official-admin/
|
||||
│ │ ├── goods.ts # 商品 CRUD + 批量
|
||||
│ │ ├── categories.ts # 品类 CRUD
|
||||
│ │ ├── countries.ts # 国家 CRUD
|
||||
│ │ ├── tags.ts # 标签 CRUD
|
||||
│ │ ├── tags.ts # 标签 CRUD(含批量排序)
|
||||
│ │ ├── tag-groups.ts # 标签分组 CRUD
|
||||
│ │ ├── positions.ts # 坑位 CRUD
|
||||
│ │ ├── origin-goods.ts # 原始商品快照
|
||||
│ │ └── sync.ts # 同步触发 + 日志
|
||||
@@ -170,10 +181,10 @@ inkreach-official-admin/
|
||||
- **路由守卫**:未登录访问受保护路由跳 `/login`;已登录访问 `/login` 跳 `/`。
|
||||
- **Pinia 持久化**:`auth` store 主动读写 `localStorage`(`token` + `user`)。
|
||||
|
||||
## 子项目 3:inkreach-official-website(官网)
|
||||
## 子项目 3:apps/website(官网,@inkreach/website)
|
||||
|
||||
```
|
||||
inkreach-official-website/
|
||||
apps/website/
|
||||
├── app/
|
||||
│ ├── app.vue # 根容器:<NuxtPage />
|
||||
│ ├── pages/
|
||||
@@ -212,6 +223,8 @@ inkreach-official-website/
|
||||
│ │ └── backend/ # NestJS 后端代理(同源 + Nitro 缓存 60s)
|
||||
│ │ ├── categories.get.ts # → GET :3001/public/categories
|
||||
│ │ ├── countries.get.ts # → GET :3001/public/countries
|
||||
│ │ ├── tags.get.ts # → GET :3001/public/tags
|
||||
│ │ ├── tag-groups.get.ts # → GET :3001/public/tag-groups
|
||||
│ │ ├── goods.get.ts # → GET :3001/public/goods
|
||||
│ │ └── goods/[id].get.ts # → GET :3001/public/goods/:id
|
||||
│ └── utils/pod-api.ts
|
||||
@@ -227,7 +240,7 @@ inkreach-official-website/
|
||||
└── package.json
|
||||
```
|
||||
|
||||
> 子项目内部的页面、组件、composable、代理路由、组件响应式断点等详细信息见 `inkreach-official-website/docs/references/structs.md`。
|
||||
> 子项目内部的页面、组件、composable、代理路由、组件响应式断点等详细信息见 `apps/website/docs/references/structs.md`。
|
||||
|
||||
## 数据库
|
||||
|
||||
@@ -236,15 +249,15 @@ inkreach-official-website/
|
||||
- 所有 `TIMESTAMPTZ` 列:`@db.Timestamptz(6)`
|
||||
- 所有主键:`BigInt @default(autoincrement())`
|
||||
- 表名与列名通过 `@map` / `@@map` 映射为 `snake_case`
|
||||
- 迁移位于 `inkreach-official-nestjs/prisma/migrations/`
|
||||
- 迁移位于 `apps/api/prisma/migrations/`
|
||||
|
||||
## 环境变量总览
|
||||
|
||||
| 变量 | 位置 | 用途 | 默认 |
|
||||
|------|------|------|------|
|
||||
| `DATABASE_URL` | 根 `.env` | PostgreSQL 连接串 | — |
|
||||
| `JWT_SECRET` | inkreach-official-nestjs | JWT 签名密钥 | — |
|
||||
| `PORT` | inkreach-official-nestjs | 后端端口 | `3001` |
|
||||
| `SDS_API_*` | inkreach-official-nestjs | 同步上游 SDS 接口凭据 | — |
|
||||
| `VITE_API_BASE` | inkreach-official-admin | axios baseURL | `/api` |
|
||||
| `NUXT_PUBLIC_BACKEND_URL` | inkreach-official-website | NestJS 后端地址 | `http://localhost:3001` |
|
||||
| `JWT_SECRET` | `apps/api` | JWT 签名密钥 | — |
|
||||
| `PORT` | `apps/api` | 后端端口 | `3001` |
|
||||
| `SDS_API_*` | `apps/api` | 同步上游 SDS 接口凭据 | — |
|
||||
| `VITE_API_BASE` | `apps/admin` | axios baseURL | `/api` |
|
||||
| `NUXT_PUBLIC_BACKEND_URL` | `apps/website` | NestJS 后端地址 | `http://localhost:3001` |
|
||||
|
||||
Reference in New Issue
Block a user