mirror of https://github.com/buster-so/buster.git
136 lines
5.3 KiB
Markdown
136 lines
5.3 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides core guidance to Claude/AI assistants when working with the Buster monorepo.
|
|
|
|
**Note**: Each package and app has its own CLAUDE.md with specific implementation details. This document contains only universal principles.
|
|
|
|
## Monorepo Philosophy
|
|
|
|
### Architecture Principles
|
|
1. **Packages are standalone building blocks** - Modular components with minimal cross-dependencies
|
|
2. **Apps assemble packages** - Apps piece together package code, never contain business logic directly
|
|
3. **Avoid spaghetti dependencies** - Keep clean boundaries between packages
|
|
4. **Type flow hierarchy** - Types flow: `database` → `server-shared` → `apps`
|
|
|
|
### Critical Package Boundaries
|
|
- **`@buster/database`** - Owns ALL database queries. No direct Drizzle usage elsewhere
|
|
- **`@buster/server-shared`** - API contract layer. All request/response types live here
|
|
- **`@buster/data-source`** - Isolated data source connection logic for customer databases
|
|
- **Package imports** - Packages can use each other but maintain clear, logical dependencies
|
|
|
|
## Development Principles
|
|
|
|
### Functional Programming First
|
|
- **Pure functions only** - No classes for business logic
|
|
- **Composable modules** - Build features by composing small, focused functions
|
|
- **Immutable data** - Never mutate; always create new data structures
|
|
- **Higher-order functions** - Use functions that return configured functions for dependency injection
|
|
- **No OOP** - No classes, no inheritance, no `this` keyword in business logic
|
|
|
|
### Type Safety Standards
|
|
- **Zod-first everything** - Define ALL types as Zod schemas with descriptions
|
|
- **Export inferred types** - Always use `z.infer<typeof Schema>` for TypeScript types
|
|
- **Runtime validation** - Use `.parse()` for trusted data, `.safeParse()` for user input
|
|
- **No implicit any** - Every variable, parameter, and return type must be explicitly typed
|
|
- **Constants for strings** - Use const assertions for type-safe string literals
|
|
|
|
### Testing Philosophy
|
|
- **Test-driven development** - Write tests and assertions first, then implement
|
|
- **Colocate tests** - Keep `.test.ts` (unit) and `.int.test.ts` (integration) next to implementation
|
|
- **Test naming** - If file is `user.ts`, tests are `user.test.ts` and/or `user.int.test.ts`
|
|
- **Minimize integration dependencies** - Most logic should be testable with unit tests
|
|
- **Test descriptions** - Test names should describe the assertion and situation clearly
|
|
|
|
## Development Workflow
|
|
|
|
### Command Standards
|
|
**CRITICAL**: Only use Turbo commands. Never use pnpm, npm, or vitest directly.
|
|
|
|
```bash
|
|
# Build commands
|
|
turbo build # Build entire monorepo
|
|
turbo build --filter=@buster/ai # Build specific package
|
|
|
|
# Linting
|
|
turbo lint # Lint entire monorepo
|
|
turbo lint --filter=@buster-app/web # Lint specific app
|
|
|
|
# Testing
|
|
turbo test:unit # Run all unit tests
|
|
turbo test:unit --filter=@buster/database # Test specific package
|
|
turbo test:integration --filter=@buster/ai # Integration tests for specific package
|
|
|
|
# Development
|
|
turbo dev # Start development servers
|
|
```
|
|
|
|
### Pre-Completion Checklist
|
|
Before completing any task:
|
|
1. Run `turbo build` - Ensure everything compiles
|
|
2. Run `turbo lint` - Fix all linting issues
|
|
3. Run `turbo test:unit` - All unit tests must pass
|
|
|
|
## Code Organization
|
|
|
|
### File Structure
|
|
- **Small, focused files** - Each file has a single responsibility
|
|
- **Deep nesting is OK** - Organize into logical subdirectories
|
|
- **Explicit exports** - Use named exports and comprehensive index.ts files
|
|
- **Functional patterns** - Export factory functions that return configured function sets
|
|
|
|
### Module Patterns
|
|
```typescript
|
|
// Good: Functional approach with Zod
|
|
import { z } from 'zod';
|
|
|
|
const UserParamsSchema = z.object({
|
|
userId: z.string().describe('Unique user identifier'),
|
|
orgId: z.string().describe('Organization identifier')
|
|
});
|
|
|
|
type UserParams = z.infer<typeof UserParamsSchema>;
|
|
|
|
export function validateUser(params: UserParams) {
|
|
const validated = UserParamsSchema.parse(params);
|
|
// Implementation
|
|
}
|
|
|
|
// Bad: Class-based approach
|
|
class UserService { // Never do this
|
|
validateUser() { }
|
|
}
|
|
```
|
|
|
|
## Cross-Cutting Concerns
|
|
|
|
### Environment Variables
|
|
- Centralized at root level in `.env` file
|
|
- Turbo passes variables via `globalEnv` configuration
|
|
- Individual packages validate their required variables
|
|
|
|
### Database Operations
|
|
- ALL queries go through `@buster/database` package
|
|
- Never use Drizzle directly outside the database package
|
|
- Soft deletes only (use `deleted_at` field)
|
|
- Prefer upserts over updates
|
|
|
|
### API Development
|
|
- Request/response types in `@buster/server-shared`
|
|
- Import database types through server-shared for consistency
|
|
- Validate with Zod at API boundaries
|
|
- Use type imports: `import type { User } from '@buster/database'`
|
|
|
|
## Legacy Code Migration
|
|
- **Rust code** (`apps/api`) is legacy and being migrated to TypeScript
|
|
- Focus new development on TypeScript patterns
|
|
- Follow patterns in `apps/server` for new API development
|
|
|
|
## Agent Workflows
|
|
- Use `planner` agent for spec, plan, ticket, research development workflows.
|
|
|
|
## Important Reminders
|
|
- Do only what has been asked; nothing more, nothing less
|
|
- Never create files unless absolutely necessary
|
|
- Always prefer editing existing files over creating new ones
|
|
- Never proactively create documentation unless explicitly requested
|
|
- Check package/app-specific CLAUDE.md files for implementation details |