Setup initial project
This commit is contained in:
commit
db79af06f7
119 changed files with 20761 additions and 0 deletions
291
docs/instructions/turborepo.md
Normal file
291
docs/instructions/turborepo.md
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
# Turborepo Monorepo Best Practices — MeshiTrack
|
||||
|
||||
> Instruction file for managing the monorepo workspace.
|
||||
|
||||
## Workspace Structure
|
||||
|
||||
```
|
||||
MeshiTrack/
|
||||
├── packages/
|
||||
│ ├── api/ # NestJS backend → @meshitrack/api
|
||||
│ ├── web/ # Next.js frontend → @meshitrack/web
|
||||
│ └── shared/ # Shared types & DTOs → @meshitrack/shared
|
||||
├── docker/ # Docker configs (not a package)
|
||||
├── docs/ # Documentation (not a package)
|
||||
├── turbo.json # Turborepo pipeline config
|
||||
├── package.json # Root workspace config
|
||||
├── tsconfig.base.json
|
||||
├── .eslintrc.js
|
||||
├── .prettierrc
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
## Root package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "meshitrack",
|
||||
"private": true,
|
||||
"workspaces": ["packages/*"],
|
||||
"scripts": {
|
||||
"dev": "turbo run dev",
|
||||
"build": "turbo run build",
|
||||
"lint": "turbo run lint",
|
||||
"test": "turbo run test",
|
||||
"typecheck": "turbo run typecheck",
|
||||
"clean": "turbo run clean"
|
||||
},
|
||||
"devDependencies": {
|
||||
"turbo": "^2.x",
|
||||
"typescript": "^5.x",
|
||||
"eslint": "^9.x",
|
||||
"prettier": "^3.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## turbo.json Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://turbo.build/schema.json",
|
||||
"globalDependencies": ["**/.env.*local"],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
|
||||
},
|
||||
"dev": {
|
||||
"dependsOn": ["^build"],
|
||||
"cache": false,
|
||||
"persistent": true
|
||||
},
|
||||
"lint": {
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"typecheck": {
|
||||
"dependsOn": ["^build"]
|
||||
},
|
||||
"clean": {
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Key concepts
|
||||
|
||||
- **`dependsOn: ["^build"]`**: Before running a task in a package, first build all its dependencies. This ensures `shared` is built before `api` or `web` run.
|
||||
- **`outputs`**: What Turborepo caches. If outputs haven't changed, Turborepo replays from cache.
|
||||
- **`persistent: true`**: For long-running dev servers that shouldn't be cached.
|
||||
- **`cache: false`**: Disables caching for tasks that should always run.
|
||||
|
||||
## Package Dependencies
|
||||
|
||||
### Shared package is the foundation
|
||||
|
||||
```
|
||||
@meshitrack/shared ← @meshitrack/api
|
||||
← @meshitrack/web
|
||||
```
|
||||
|
||||
Both `api` and `web` depend on `shared`, but never on each other.
|
||||
|
||||
### Reference shared in package.json
|
||||
|
||||
```json
|
||||
// packages/api/package.json
|
||||
{
|
||||
"name": "@meshitrack/api",
|
||||
"dependencies": {
|
||||
"@meshitrack/shared": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
// packages/web/package.json
|
||||
{
|
||||
"name": "@meshitrack/web",
|
||||
"dependencies": {
|
||||
"@meshitrack/shared": "workspace:*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Import from shared
|
||||
|
||||
```typescript
|
||||
// In packages/api or packages/web
|
||||
import { Product, NutritionInfo, ProductCategory } from '@meshitrack/shared';
|
||||
import { CreateProductSchema } from '@meshitrack/shared/validation';
|
||||
```
|
||||
|
||||
## Shared Package Setup
|
||||
|
||||
### packages/shared/package.json
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@meshitrack/shared",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./validation": {
|
||||
"types": "./dist/validation/index.d.ts",
|
||||
"default": "./dist/validation/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"clean": "rm -rf dist",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "^3.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.x"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### packages/shared/tsconfig.json
|
||||
|
||||
```json
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"]
|
||||
}
|
||||
```
|
||||
|
||||
### Shared package must be platform-agnostic
|
||||
|
||||
Rules for code in `packages/shared`:
|
||||
|
||||
- **No** Node.js imports (`fs`, `path`, `http`, etc.)
|
||||
- **No** NestJS decorators or imports
|
||||
- **No** Next.js imports
|
||||
- **No** DOM/browser APIs
|
||||
- Only pure TypeScript: types, interfaces, enums, Zod schemas, utility functions
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
### Root tsconfig.base.json
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"incremental": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
```
|
||||
|
||||
Each package extends this and overrides as needed (e.g., `web` uses `"jsx": "preserve"`, `"module": "esnext"`).
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Start all packages in dev mode
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# Turborepo runs: shared (build) → then api (dev) + web (dev) in parallel
|
||||
```
|
||||
|
||||
### Build all packages
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# Turborepo builds shared first, then api and web in parallel
|
||||
```
|
||||
|
||||
### Run tasks for a specific package
|
||||
|
||||
```bash
|
||||
npx turbo run dev --filter=@meshitrack/api
|
||||
npx turbo run test --filter=@meshitrack/web
|
||||
```
|
||||
|
||||
### Add a dependency to a specific package
|
||||
|
||||
```bash
|
||||
cd packages/api
|
||||
npm install @nestjs/schedule
|
||||
# Or from root:
|
||||
npm install @nestjs/schedule --workspace=packages/api
|
||||
```
|
||||
|
||||
## Caching
|
||||
|
||||
### Turborepo remote caching (optional)
|
||||
|
||||
For CI, consider enabling remote caching to share build cache across machines:
|
||||
|
||||
```bash
|
||||
npx turbo login
|
||||
npx turbo link
|
||||
```
|
||||
|
||||
Or use a self-hosted cache server for full self-hosted setup.
|
||||
|
||||
### Local caching
|
||||
|
||||
Turborepo caches locally in `node_modules/.cache/turbo` by default. It's fast and requires no setup.
|
||||
|
||||
## CI Integration
|
||||
|
||||
```yaml
|
||||
# .github/workflows/ci.yml
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
- run: npm ci
|
||||
- run: npx turbo run build lint test typecheck
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. **Forgetting to build shared**: If `api` or `web` can't find types from `shared`, run `npm run build` from root. The `dependsOn: ["^build"]` config handles this in Turborepo tasks.
|
||||
|
||||
2. **Circular dependencies**: Never import from `api` in `web` or vice versa. Only import from `shared`.
|
||||
|
||||
3. **Version mismatches**: Keep TypeScript versions aligned across all packages. Pin in root `devDependencies`.
|
||||
|
||||
4. **Large `node_modules`**: Use `npm` workspaces hoisting. Most dependencies are installed at root level. Only package-specific versions go in package-level `node_modules`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue