docs: Restructure documentation with Bookstack-compatible hierarchy
- Organized docs into numbered shelf/book/chapter/page structure - Created comprehensive README.md with project overview - Added Getting Started book (quick start, installation, configuration) - Added Development book (workflow, testing, type sharing) - Added Architecture book (design principles, PDA-friendly patterns) - Added API Reference book (conventions, authentication) - Moved TYPE-SHARING.md to proper location - Updated all cross-references in main README - Created docs/README.md as master index - Removed old QA automation reports - Removed deprecated SETUP.md (content split into new structure) Documentation structure follows Bookstack best practices: - Numbered books: 1-getting-started, 2-development, 3-architecture, 4-api - Numbered chapters and pages for ordering - Clear hierarchy and navigation - Cross-referenced throughout Complete documentation available at: docs/README.md Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
276
docs/2-development/1-workflow/1-branching.md
Normal file
276
docs/2-development/1-workflow/1-branching.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# Branching Strategy
|
||||
|
||||
Git workflow and branching conventions for Mosaic Stack.
|
||||
|
||||
## Branch Types
|
||||
|
||||
### Main Branches
|
||||
|
||||
**`main`** — Production-ready code only
|
||||
- Never commit directly
|
||||
- Only merge from `develop` via release
|
||||
- Tagged with version numbers
|
||||
|
||||
**`develop`** — Active development (default branch)
|
||||
- All features merge here first
|
||||
- Must always build and pass tests
|
||||
- Protected branch
|
||||
|
||||
### Supporting Branches
|
||||
|
||||
**`feature/*`** — New features
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: feature/issue-number-description
|
||||
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
git checkout -b feature/6-frontend-auth
|
||||
```
|
||||
|
||||
**`fix/*`** — Bug fixes
|
||||
```bash
|
||||
# From: develop (or main for hotfixes)
|
||||
# Merge to: develop (or both main and develop)
|
||||
# Naming: fix/issue-number-description
|
||||
|
||||
git checkout develop
|
||||
git checkout -b fix/12-session-timeout
|
||||
```
|
||||
|
||||
**`refactor/*`** — Code improvements
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: refactor/area-description
|
||||
|
||||
git checkout -b refactor/auth-service-cleanup
|
||||
```
|
||||
|
||||
**`docs/*`** — Documentation updates
|
||||
```bash
|
||||
# From: develop
|
||||
# Merge to: develop
|
||||
# Naming: docs/topic
|
||||
|
||||
git checkout -b docs/api-reference
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Start New Work
|
||||
|
||||
```bash
|
||||
# Always start from latest develop
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
|
||||
# Create feature branch
|
||||
git checkout -b feature/7-task-management
|
||||
|
||||
# Optional: Use git worktree for parallel work
|
||||
git worktree add ../mosaic-stack_worktrees/7-task-management -b feature/7-task-management
|
||||
```
|
||||
|
||||
### 2. Make Changes
|
||||
|
||||
```bash
|
||||
# Make changes, write tests first (TDD)
|
||||
# Build and test after each change
|
||||
pnpm test
|
||||
pnpm build
|
||||
|
||||
# Commit frequently with conventional format
|
||||
git add .
|
||||
git commit -m "feat(#7): Add task creation endpoint"
|
||||
```
|
||||
|
||||
### 3. Stay Updated
|
||||
|
||||
```bash
|
||||
# Regularly sync with develop
|
||||
git checkout develop
|
||||
git pull --rebase
|
||||
git checkout feature/7-task-management
|
||||
git rebase develop
|
||||
|
||||
# Resolve conflicts if any
|
||||
```
|
||||
|
||||
### 4. Push Changes
|
||||
|
||||
```bash
|
||||
# Push feature branch
|
||||
git push -u origin feature/7-task-management
|
||||
```
|
||||
|
||||
### 5. Create Pull Request
|
||||
|
||||
```bash
|
||||
# Use git.mosaicstack.dev web UI or
|
||||
pr-create.sh -t "Implement task management" \
|
||||
-b "Adds full CRUD for tasks with tests" \
|
||||
-i 7
|
||||
|
||||
# Or with gh CLI
|
||||
gh pr create --title "feat(#7): Implement task management" \
|
||||
--body "Full task management implementation..." \
|
||||
--base develop \
|
||||
--head feature/7-task-management
|
||||
```
|
||||
|
||||
### 6. Code Review
|
||||
|
||||
- All PRs require review before merge
|
||||
- Address review comments
|
||||
- Keep commits clean (squash if messy)
|
||||
|
||||
### 7. Merge
|
||||
|
||||
```bash
|
||||
# After approval, squash and merge
|
||||
pr-merge.sh -n 7 -m squash -d
|
||||
|
||||
# Or via web UI: "Squash and Merge"
|
||||
```
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
```
|
||||
<type>(#issue): Brief description
|
||||
|
||||
Detailed explanation if needed.
|
||||
|
||||
Fixes #123
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
- `feat` — New feature
|
||||
- `fix` — Bug fix
|
||||
- `docs` — Documentation
|
||||
- `test` — Test additions/changes
|
||||
- `refactor` — Code restructuring
|
||||
- `chore` — Maintenance tasks
|
||||
- `perf` — Performance improvements
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
feat(#7): Add task creation endpoint
|
||||
|
||||
Implements POST /api/tasks with validation and tests.
|
||||
Includes database migration for task table.
|
||||
|
||||
Fixes #7
|
||||
|
||||
---
|
||||
|
||||
fix(#12): Resolve session timeout issue
|
||||
|
||||
Sessions were expiring prematurely due to incorrect JWT config.
|
||||
Updated JWT_EXPIRATION to use proper time format.
|
||||
|
||||
Fixes #12
|
||||
|
||||
---
|
||||
|
||||
docs(#15): Add API authentication guide
|
||||
|
||||
Complete guide for auth endpoints with examples.
|
||||
|
||||
Refs #15
|
||||
```
|
||||
|
||||
## Protected Branch Rules
|
||||
|
||||
### `main` Branch
|
||||
|
||||
- No direct commits
|
||||
- Require PR approval
|
||||
- Require passing tests
|
||||
- Require up-to-date branch
|
||||
|
||||
### `develop` Branch
|
||||
|
||||
- No direct commits (use PRs)
|
||||
- Require passing tests
|
||||
- Auto-delete head branches after merge
|
||||
|
||||
## Git Worktrees
|
||||
|
||||
For working on multiple issues simultaneously:
|
||||
|
||||
```bash
|
||||
# Structure: {project_name}_worktrees/{issue-name}/
|
||||
mkdir ~/src/mosaic-stack_worktrees
|
||||
|
||||
# Create worktree for issue #7
|
||||
cd ~/src/mosaic-stack
|
||||
git worktree add ../mosaic-stack_worktrees/7-task-management -b feature/7-task-management
|
||||
|
||||
# Work in worktree
|
||||
cd ../mosaic-stack_worktrees/7-task-management
|
||||
# Make changes, commit, push
|
||||
|
||||
# List worktrees
|
||||
git worktree list
|
||||
|
||||
# Remove after merge
|
||||
git worktree remove ../mosaic-stack_worktrees/7-task-management
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always start from `develop`**
|
||||
2. **Keep branches short-lived** (max 1-2 weeks)
|
||||
3. **Write tests first** (TDD approach)
|
||||
4. **Commit frequently** with clear messages
|
||||
5. **Rebase, don't merge** when syncing with develop
|
||||
6. **Squash commits** before merging PR
|
||||
7. **Delete branches** after merging
|
||||
8. **Reference issues** in all commits
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Conflicts During Rebase
|
||||
|
||||
```bash
|
||||
# Start rebase
|
||||
git rebase develop
|
||||
|
||||
# Conflicts occur
|
||||
# Edit conflicting files
|
||||
|
||||
# Mark as resolved
|
||||
git add <conflicted-files>
|
||||
git rebase --continue
|
||||
|
||||
# Or abort and try later
|
||||
git rebase --abort
|
||||
```
|
||||
|
||||
### Accidentally Committed to `develop`
|
||||
|
||||
```bash
|
||||
# Undo last commit (keep changes)
|
||||
git reset --soft HEAD~1
|
||||
|
||||
# Create proper feature branch
|
||||
git checkout -b feature/my-changes
|
||||
|
||||
# Commit again
|
||||
git commit -m "feat: My changes"
|
||||
|
||||
# Force-push develop back to origin (if already pushed)
|
||||
git checkout develop
|
||||
git reset --hard origin/develop
|
||||
git push --force
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Testing Requirements** — [Testing](2-testing.md)
|
||||
- **Commit Guidelines** — [Committing](3-committing.md)
|
||||
- **Database Migrations** — [Database](../2-database/2-migrations.md)
|
||||
336
docs/2-development/1-workflow/2-testing.md
Normal file
336
docs/2-development/1-workflow/2-testing.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# Testing Requirements
|
||||
|
||||
Test-driven development standards and practices for Mosaic Stack.
|
||||
|
||||
## Testing Philosophy
|
||||
|
||||
- **Test-Driven Development (TDD)** — Write tests before implementation
|
||||
- **Minimum 85% coverage** for all new code
|
||||
- **All tests must pass** before PR approval
|
||||
- **No untested code** in production
|
||||
|
||||
## Test Types
|
||||
|
||||
### Unit Tests
|
||||
|
||||
Test individual functions and methods in isolation.
|
||||
|
||||
**Location:** `*.spec.ts` next to source file
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.service.spec.ts
|
||||
describe('AuthService', () => {
|
||||
it('should create a session for valid user', async () => {
|
||||
const result = await authService.createSession(mockUser);
|
||||
expect(result.session.token).toBeDefined();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
Test interactions between components.
|
||||
|
||||
**Location:** `*.integration.spec.ts` in module directory
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.integration.spec.ts
|
||||
describe('Auth Integration', () => {
|
||||
it('should complete full login flow', async () => {
|
||||
const login = await request(app.getHttpServer())
|
||||
.post('/auth/sign-in')
|
||||
.send({ email, password });
|
||||
expect(login.status).toBe(200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### E2E Tests
|
||||
|
||||
Test complete user flows across the entire stack.
|
||||
|
||||
**Location:** `apps/web/tests/e2e/` (when implemented)
|
||||
|
||||
**Framework:** Playwright
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# All tests
|
||||
pnpm test
|
||||
|
||||
# Watch mode (re-run on changes)
|
||||
pnpm test:watch
|
||||
|
||||
# Coverage report
|
||||
pnpm test:coverage
|
||||
|
||||
# Specific file
|
||||
pnpm test apps/api/src/auth/auth.service.spec.ts
|
||||
|
||||
# API tests only
|
||||
pnpm test:api
|
||||
|
||||
# E2E tests (when implemented)
|
||||
pnpm test:e2e
|
||||
```
|
||||
|
||||
## Writing Tests
|
||||
|
||||
### Structure
|
||||
|
||||
```typescript
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
|
||||
describe('ComponentName', () => {
|
||||
beforeEach(() => {
|
||||
// Setup
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Cleanup
|
||||
});
|
||||
|
||||
describe('methodName', () => {
|
||||
it('should handle normal case', () => {
|
||||
// Arrange
|
||||
const input = 'test';
|
||||
|
||||
// Act
|
||||
const result = component.method(input);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe('expected');
|
||||
});
|
||||
|
||||
it('should handle error case', () => {
|
||||
expect(() => component.method(null)).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Mocking
|
||||
|
||||
```typescript
|
||||
// Mock service dependency
|
||||
const mockPrismaService = {
|
||||
user: {
|
||||
findUnique: vi.fn(),
|
||||
create: vi.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
// Mock module
|
||||
vi.mock('./some-module', () => ({
|
||||
someFunction: vi.fn(() => 'mocked'),
|
||||
}));
|
||||
```
|
||||
|
||||
### Testing Async Code
|
||||
|
||||
```typescript
|
||||
it('should complete async operation', async () => {
|
||||
const result = await asyncFunction();
|
||||
expect(result).toBeDefined();
|
||||
});
|
||||
|
||||
// Or with resolves/rejects
|
||||
it('should resolve with data', async () => {
|
||||
await expect(asyncFunction()).resolves.toBe('data');
|
||||
});
|
||||
|
||||
it('should reject with error', async () => {
|
||||
await expect(failingFunction()).rejects.toThrow('Error');
|
||||
});
|
||||
```
|
||||
|
||||
## Coverage Requirements
|
||||
|
||||
### Minimum Coverage
|
||||
|
||||
- **Statements:** 85%
|
||||
- **Branches:** 80%
|
||||
- **Functions:** 85%
|
||||
- **Lines:** 85%
|
||||
|
||||
### View Coverage Report
|
||||
|
||||
```bash
|
||||
pnpm test:coverage
|
||||
|
||||
# Opens HTML report
|
||||
open coverage/index.html
|
||||
```
|
||||
|
||||
### Exemptions
|
||||
|
||||
Some code types may have lower coverage requirements:
|
||||
- **DTOs/Interfaces:** No coverage required (type checking sufficient)
|
||||
- **Constants:** No coverage required
|
||||
- **Database migrations:** Manual verification acceptable
|
||||
|
||||
Always document exemptions in PR description.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Test Behavior, Not Implementation
|
||||
|
||||
**❌ Bad:**
|
||||
```typescript
|
||||
it('should call getUserById', () => {
|
||||
service.login(email, password);
|
||||
expect(mockService.getUserById).toHaveBeenCalled();
|
||||
});
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```typescript
|
||||
it('should return session for valid credentials', async () => {
|
||||
const result = await service.login(email, password);
|
||||
expect(result.session.token).toBeDefined();
|
||||
expect(result.user.email).toBe(email);
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Use Descriptive Test Names
|
||||
|
||||
**❌ Bad:**
|
||||
```typescript
|
||||
it('works', () => { ... });
|
||||
it('test 1', () => { ... });
|
||||
```
|
||||
|
||||
**✅ Good:**
|
||||
```typescript
|
||||
it('should return 401 for invalid credentials', () => { ... });
|
||||
it('should create session with 24h expiration', () => { ... });
|
||||
```
|
||||
|
||||
### 3. Arrange-Act-Assert Pattern
|
||||
|
||||
```typescript
|
||||
it('should calculate total correctly', () => {
|
||||
// Arrange - Set up test data
|
||||
const items = [{ price: 10 }, { price: 20 }];
|
||||
|
||||
// Act - Execute the code being tested
|
||||
const total = calculateTotal(items);
|
||||
|
||||
// Assert - Verify the result
|
||||
expect(total).toBe(30);
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Test Edge Cases
|
||||
|
||||
```typescript
|
||||
describe('validateEmail', () => {
|
||||
it('should accept valid email', () => {
|
||||
expect(validateEmail('user@example.com')).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject empty string', () => {
|
||||
expect(validateEmail('')).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject null', () => {
|
||||
expect(validateEmail(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should reject invalid format', () => {
|
||||
expect(validateEmail('notanemail')).toBe(false);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Keep Tests Independent
|
||||
|
||||
```typescript
|
||||
// ❌ Bad - Tests depend on order
|
||||
let userId;
|
||||
it('should create user', () => {
|
||||
userId = createUser();
|
||||
});
|
||||
it('should get user', () => {
|
||||
getUser(userId); // Fails if previous test fails
|
||||
});
|
||||
|
||||
// ✅ Good - Each test is independent
|
||||
it('should create user', () => {
|
||||
const userId = createUser();
|
||||
expect(userId).toBeDefined();
|
||||
});
|
||||
it('should get user', () => {
|
||||
const userId = createUser(); // Create fresh data
|
||||
const user = getUser(userId);
|
||||
expect(user).toBeDefined();
|
||||
});
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
Tests run automatically on:
|
||||
- Every push to feature branch
|
||||
- Every pull request
|
||||
- Before merge to `develop`
|
||||
|
||||
**Pipeline must pass** before merging.
|
||||
|
||||
## Debugging Tests
|
||||
|
||||
### Run Single Test
|
||||
|
||||
```typescript
|
||||
it.only('should test specific case', () => {
|
||||
// Only this test runs
|
||||
});
|
||||
```
|
||||
|
||||
### Skip Test
|
||||
|
||||
```typescript
|
||||
it.skip('should test something', () => {
|
||||
// This test is skipped
|
||||
});
|
||||
```
|
||||
|
||||
### Verbose Output
|
||||
|
||||
```bash
|
||||
pnpm test --reporter=verbose
|
||||
```
|
||||
|
||||
### Debug in VS Code
|
||||
|
||||
Add to `.vscode/launch.json`:
|
||||
```json
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Vitest",
|
||||
"runtimeExecutable": "pnpm",
|
||||
"runtimeArgs": ["test", "--no-coverage"],
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
```
|
||||
|
||||
## Test Database
|
||||
|
||||
Use separate test database:
|
||||
|
||||
```bash
|
||||
# .env.test
|
||||
TEST_DATABASE_URL=postgresql://mosaic:mosaic@localhost:5432/mosaic_test
|
||||
|
||||
# Reset test DB before each run
|
||||
pnpm test:db:reset
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **Review Commit Guidelines** — [Committing](3-committing.md)
|
||||
- **Learn Database Testing** — [Database](../2-database/3-prisma.md)
|
||||
- **Check Code Style** — [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
|
||||
287
docs/2-development/3-type-sharing/1-strategy.md
Normal file
287
docs/2-development/3-type-sharing/1-strategy.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# Type Sharing Strategy
|
||||
|
||||
This document explains how types are shared between the frontend and backend in the Mosaic Stack monorepo.
|
||||
|
||||
## Overview
|
||||
|
||||
All types that are used by both frontend and backend live in the `@mosaic/shared` package. This ensures:
|
||||
- **Type safety** across the entire stack
|
||||
- **Single source of truth** for data structures
|
||||
- **Automatic type updates** when the API changes
|
||||
- **Reduced duplication** and maintenance burden
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
packages/shared/
|
||||
├── src/
|
||||
│ ├── types/
|
||||
│ │ ├── index.ts # Main export file
|
||||
│ │ ├── enums.ts # Shared enums (TaskStatus, etc.)
|
||||
│ │ ├── database.types.ts # Database entity types
|
||||
│ │ └── auth.types.ts # Authentication types (NEW)
|
||||
│ ├── utils/
|
||||
│ └── constants.ts
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## Authentication Types
|
||||
|
||||
### Shared Types (`@mosaic/shared`)
|
||||
|
||||
These types are used by **both** frontend and backend:
|
||||
|
||||
#### `AuthUser`
|
||||
The authenticated user object that's safe to expose to clients.
|
||||
```typescript
|
||||
interface AuthUser {
|
||||
readonly id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
image?: string;
|
||||
emailVerified?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
#### `AuthSession`
|
||||
Session data returned after successful authentication.
|
||||
```typescript
|
||||
interface AuthSession {
|
||||
user: AuthUser;
|
||||
session: {
|
||||
id: string;
|
||||
token: string;
|
||||
expiresAt: Date;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### `Session`, `Account`
|
||||
Full database entity types for sessions and OAuth accounts.
|
||||
|
||||
#### `LoginRequest`, `LoginResponse`
|
||||
Request/response payloads for authentication endpoints.
|
||||
|
||||
#### `OAuthProvider`
|
||||
Supported OAuth providers: `"authentik" | "google" | "github"`
|
||||
|
||||
#### `OAuthCallbackParams`
|
||||
Query parameters from OAuth callback redirects.
|
||||
|
||||
### Backend-Only Types
|
||||
|
||||
Types that are only used by the backend stay in `apps/api/src/auth/types/`:
|
||||
|
||||
#### `BetterAuthRequest`
|
||||
Internal type for BetterAuth handler compatibility (extends web standard `Request`).
|
||||
|
||||
**Why backend-only?** This is an implementation detail of how NestJS integrates with BetterAuth. The frontend doesn't need to know about it.
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### In the Backend (API)
|
||||
|
||||
```typescript
|
||||
// apps/api/src/auth/auth.controller.ts
|
||||
import { AuthUser } from "@mosaic/shared";
|
||||
|
||||
@Get("profile")
|
||||
@UseGuards(AuthGuard)
|
||||
getProfile(@CurrentUser() user: AuthUser) {
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### In the Frontend (Web)
|
||||
|
||||
```typescript
|
||||
// apps/web/app/components/UserProfile.tsx
|
||||
import type { AuthUser } from "@mosaic/shared";
|
||||
|
||||
export function UserProfile({ user }: { user: AuthUser }) {
|
||||
return (
|
||||
<div>
|
||||
<h1>{user.name}</h1>
|
||||
<p>{user.email}</p>
|
||||
{user.emailVerified && <Badge>Verified</Badge>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### API Response Types
|
||||
|
||||
```typescript
|
||||
// Both FE and BE can use this
|
||||
import type { ApiResponse, AuthSession } from "@mosaic/shared";
|
||||
|
||||
// Backend returns this
|
||||
const response: ApiResponse<AuthSession> = {
|
||||
success: true,
|
||||
data: {
|
||||
user: { id: "...", email: "...", name: "..." },
|
||||
session: { id: "...", token: "...", expiresAt: new Date() },
|
||||
},
|
||||
};
|
||||
|
||||
// Frontend consumes this
|
||||
async function login(email: string, password: string) {
|
||||
const response = await fetch("/api/auth/login", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
|
||||
const data: ApiResponse<AuthSession> = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
// TypeScript knows data.data exists and is AuthSession
|
||||
saveSession(data.data);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Database Types
|
||||
|
||||
The `@mosaic/shared` package also exports database entity types that match the Prisma schema:
|
||||
|
||||
- `User` - Full user entity (includes all fields from DB)
|
||||
- `Workspace`, `Task`, `Event`, `Project` - Other entities
|
||||
- Enums: `TaskStatus`, `TaskPriority`, `ProjectStatus`, etc.
|
||||
|
||||
### Key Difference: `User` vs `AuthUser`
|
||||
|
||||
| Type | Purpose | Fields | Used By |
|
||||
|------|---------|--------|---------|
|
||||
| `User` | Full database entity | All DB fields including sensitive data | Backend internal logic |
|
||||
| `AuthUser` | Safe client-exposed subset | Only public fields (no preferences, etc.) | API responses, Frontend |
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// Backend internal logic
|
||||
import { User } from "@mosaic/shared";
|
||||
|
||||
async function updateUserPreferences(userId: string, prefs: User["preferences"]) {
|
||||
// Has access to all fields including preferences
|
||||
}
|
||||
|
||||
// API response
|
||||
import { AuthUser } from "@mosaic/shared";
|
||||
|
||||
function sanitizeUser(user: User): AuthUser {
|
||||
return {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
image: user.image,
|
||||
emailVerified: user.emailVerified,
|
||||
};
|
||||
// Preferences and other sensitive fields are excluded
|
||||
}
|
||||
```
|
||||
|
||||
## Adding New Shared Types
|
||||
|
||||
When adding new types that should be shared:
|
||||
|
||||
1. **Determine if it should be shared:**
|
||||
- ✅ API request/response payloads
|
||||
- ✅ Database entity shapes
|
||||
- ✅ Business domain types
|
||||
- ✅ Enums and constants
|
||||
- ❌ Backend-only implementation details
|
||||
- ❌ Frontend-only UI component props
|
||||
|
||||
2. **Add to the appropriate file:**
|
||||
- Database entities → `database.types.ts`
|
||||
- Auth-related → `auth.types.ts`
|
||||
- Enums → `enums.ts`
|
||||
- General API types → `index.ts`
|
||||
|
||||
3. **Export from `index.ts`:**
|
||||
```typescript
|
||||
export * from "./your-new-types";
|
||||
```
|
||||
|
||||
4. **Build the shared package:**
|
||||
```bash
|
||||
cd packages/shared
|
||||
pnpm build
|
||||
```
|
||||
|
||||
5. **Use in your apps:**
|
||||
```typescript
|
||||
import { YourType } from "@mosaic/shared";
|
||||
```
|
||||
|
||||
## Type Versioning
|
||||
|
||||
Since this is a monorepo, all packages use the same version of `@mosaic/shared`. When you:
|
||||
|
||||
1. **Change a shared type** - Both FE and BE automatically get the update
|
||||
2. **Add a new field** - TypeScript will show errors where the field is missing
|
||||
3. **Remove a field** - TypeScript will show errors where the field is still used
|
||||
|
||||
This ensures the frontend and backend never drift out of sync.
|
||||
|
||||
## Benefits
|
||||
|
||||
### Type Safety
|
||||
```typescript
|
||||
// If the backend changes AuthUser.name to AuthUser.displayName,
|
||||
// the frontend will get TypeScript errors everywhere AuthUser is used.
|
||||
// You'll fix all uses before deploying.
|
||||
```
|
||||
|
||||
### Auto-Complete
|
||||
```typescript
|
||||
// Frontend developers get full autocomplete for API types
|
||||
const user: AuthUser = await fetchUser();
|
||||
user. // <-- IDE shows: id, email, name, image, emailVerified
|
||||
```
|
||||
|
||||
### Refactoring
|
||||
```typescript
|
||||
// Rename a field? TypeScript finds all usages across FE and BE
|
||||
// No need to grep or search manually
|
||||
```
|
||||
|
||||
### Documentation
|
||||
```typescript
|
||||
// The types ARE the documentation
|
||||
// Frontend developers see exactly what the API returns
|
||||
```
|
||||
|
||||
## Current Shared Types
|
||||
|
||||
### Authentication (`auth.types.ts`)
|
||||
- `AuthUser` - Authenticated user info
|
||||
- `AuthSession` - Session data
|
||||
- `Session` - Full session entity
|
||||
- `Account` - OAuth account entity
|
||||
- `LoginRequest`, `LoginResponse`
|
||||
- `OAuthProvider`, `OAuthCallbackParams`
|
||||
|
||||
### Database Entities (`database.types.ts`)
|
||||
- `User` - Full user entity
|
||||
- `Workspace`, `WorkspaceMember`
|
||||
- `Task`, `Event`, `Project`
|
||||
- `ActivityLog`, `MemoryEmbedding`
|
||||
|
||||
### Enums (`enums.ts`)
|
||||
- `TaskStatus`, `TaskPriority`
|
||||
- `ProjectStatus`
|
||||
- `WorkspaceMemberRole`
|
||||
- `ActivityAction`, `EntityType`
|
||||
|
||||
### API Utilities (`index.ts`)
|
||||
- `ApiResponse<T>` - Standard response wrapper
|
||||
- `PaginatedResponse<T>` - Paginated data
|
||||
- `HealthStatus` - Health check format
|
||||
|
||||
---
|
||||
|
||||
**Remember:** If a type is used by both frontend and backend, it belongs in `@mosaic/shared`. If it's only used by one side, keep it local to that application.
|
||||
25
docs/2-development/README.md
Normal file
25
docs/2-development/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Development
|
||||
|
||||
Developer guide for contributing to Mosaic Stack.
|
||||
|
||||
## Chapters
|
||||
|
||||
1. **Workflow** — Git workflow, branching strategy, and testing requirements
|
||||
2. **Database** — Schema design, migrations, and Prisma usage
|
||||
3. **Type Sharing** — Type sharing strategy across the monorepo
|
||||
|
||||
## Development Standards
|
||||
|
||||
- **Test Coverage:** Minimum 85% for new code
|
||||
- **TDD Approach:** Write tests before implementation
|
||||
- **Code Style:** Follow Google Style Guides
|
||||
- **Type Safety:** Everything must be properly typed
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Complete the **Getting Started** book before diving into development.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Read **Architecture** to understand the system design
|
||||
- Review **API** for endpoint conventions
|
||||
Reference in New Issue
Block a user