feat: add database and API packages with contact management#2
feat: add database and API packages with contact management#2
Conversation
- Create @poly/database package with Prisma ORM - Set up multi-file schema structure (base.prisma + models/) - Add User model with UUID, email, role enum - Add Contact model (example) - Configure Prisma Client singleton pattern - Add database seed script with default users - Configure SQLite for development with PostgreSQL migration path 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…egration - Added Prisma and related dependencies to pnpm-workspace.yaml - Updated turbo.json to include database generation and migration tasks - Modified build, check-types, and dev tasks to depend on db:generate
Pull Request ReviewOverviewThis PR adds foundational database and API packages to the Poly CRM monorepo. The implementation follows a clean layered architecture with Prisma ORM, Zod validation, and Next.js Server Actions. Overall, this is a solid foundation with good architectural decisions. ✅ StrengthsArchitecture
Code Quality
|
- Add comprehensive JSDoc comments to all contact service methods - Enhance error handling in contact service (throw meaningful errors for not found cases) - Improve server actions error handling to distinguish between validation and runtime errors - Filter undefined values in update action to avoid Prisma issues - Replace raw SQL with simple Prisma query in health check endpoint - Add zod dependency to web app for ZodError handling - Fix eslint config imports to use @poly namespace - Add library export to eslint-config package All linting and type checks passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Pull Request Review: Database and API Packages✅ StrengthsArchitecture
Code Quality
🔍 Issues & Recommendations🔴 Critical Issues1. Security: Plaintext Password StorageLocation: password StringIssue: User model stores passwords as plain text. This is a critical security vulnerability. Fix: Hash passwords using bcrypt/argon2 before storage: import bcrypt from 'bcryptjs';
// In user service
async create(data) {
const hashedPassword = await bcrypt.hash(data.password, 10);
return prisma.user.create({
data: { ...data, password: hashedPassword }
});
}2. Race Condition in Contact ServiceLocation: async update(id: number, data: UpdateContactInput) {
await this.findById(id); // Separate query
return prisma.contact.update({ where: { id }, data });
}Issue: Two separate database queries create a window where the contact could be deleted between checks. Fix: Let Prisma handle the check: async update(id: number, data: UpdateContactInput) {
try {
return await prisma.contact.update({ where: { id }, data });
} catch (error) {
if (error.code === 'P2025') {
throw new Error(`Contact with ID ${id} not found`);
}
throw error;
}
}Same issue in 🟡 High Priority Issues3. Missing Input SanitizationLocation: phone: formData.get("phone") || undefined,
company: formData.get("company") || undefined,Issue: FormData can return null, empty strings, or whitespace. This creates inconsistent data. Fix: Add sanitization: const phone = formData.get("phone")?.toString().trim() || undefined;
const company = formData.get("company")?.toString().trim() || undefined;4. Database Path Configuration IssuesLocation: Multiple Issue: Inconsistent relative paths will cause the database file to be created in different locations depending on where commands are run. Fix: Use a single source of truth:
5. Incomplete Error TypingLocation: catch (error: unknown) {
return NextResponse.json({
status: 'error',
message: error instanceof Error ? error.message : 'Unknown error',Issue: Prisma errors have a Fix: Add Prisma error handling: import { Prisma } from '@prisma/client';
catch (error: unknown) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
return NextResponse.json({
status: 'error',
message: error.message,
code: error.code,
database: 'disconnected',
}, { status: 500 });
}
// ... rest
}🟢 Minor Issues & Suggestions6. Validation Could Be StricterLocation: phone: z.string().optional(),Suggestion: Add format validation: phone: z.string().regex(/^\+?[\d\s\-()]+$/, 'Invalid phone format').optional(),
company: z.string().min(1, 'Company cannot be empty').optional(),7. Missing Transaction Rollback TestIssue: Contact service doesn't test what happens if multiple operations fail mid-transaction (not currently in code, but worth noting for future features). Suggestion: When adding complex multi-step operations, use Prisma transactions: return await prisma.$transaction(async (tx) => {
const contact = await tx.contact.create({ data });
await tx.activity.create({ /* related activity */ });
return contact;
});8. Inconsistent Type ImportsLocation: Various files use different import styles // contacts.actions.ts
import type { CreateContactInput } from '../validation/contact.schema'
// contact.service.ts
import type { CreateContactInput, UpdateContactInput } from '../validation/contact.schema'Suggestion: Be consistent with 9. Missing Index on Commonly Queried FieldsLocation: Suggestion: If you frequently search by name/company, add indexes: @@index([name])
@@index([company])10. Seed File Excluded from GitLocation: Issue: This prevents version controlling the seed file. Seed files typically should be committed unless they contain sensitive data. Fix: Either:
📋 Testing RecommendationsMissing Test Coverage Areas:
Suggested Test Structure:// contact.service.test.ts
describe('contactService', () => {
describe('create', () => {
it('should create contact with valid data')
it('should throw on duplicate email')
it('should sanitize whitespace')
})
describe('update', () => {
it('should throw on non-existent contact')
it('should handle partial updates')
})
})🎯 Performance ConsiderationsCurrent Performance: ✅ Good
Future Optimization Opportunities:
async findAll(page = 1, limit = 50) {
return prisma.contact.findMany({
skip: (page - 1) * limit,
take: limit,
orderBy: { createdAt: 'desc' },
});
}
📚 Documentation✅ Excellent Documentation:
📝 Missing Documentation:
✅ Final VerdictOverall Assessment: Strong foundation with some critical security fixes needed Must Fix Before Merge:
Should Fix Before Merge:
Can Fix in Follow-up PRs:6-10. Minor improvements and future optimizations 🎉 SummaryThis PR establishes a solid, well-architected foundation for the CRM backend. The layered architecture, comprehensive documentation, and consistent patterns are excellent. The critical issues are fixable and mostly related to edge cases rather than fundamental design problems. Recommendation: Request changes for items 1-3, then approve after fixes. Great work on the architecture! 🚀 Review generated by Claude Code |
…view Critical Fixes: - Fix race condition in contact service update/delete methods by letting Prisma handle existence checks - Add comprehensive Prisma error handling (P2025 for not found records) - Add input sanitization in contact actions (trim whitespace, handle null values) - Fix database path configuration consistency (single source of truth in root .env) High Priority Fixes: - Improve health check error handling with Prisma-specific error types - Add stricter validation to contact schema (phone format regex, company min length) - Add critical security documentation to User model about password hashing Changes: - packages/api/src/services/contact.service.ts: Remove separate findById checks, use Prisma error codes - apps/web/actions/contacts.actions.ts: Add .toString().trim() to all form field extractions - apps/web/app/api/health/route.ts: Handle PrismaClientKnownRequestError and PrismaClientInitializationError - packages/api/src/validation/contact.schema.ts: Add phone regex and company min length validation - packages/database/prisma/schema/models/user.prisma: Add security warnings and bcrypt example - .env.example: Create root config file for DATABASE_URL - packages/database/.env.example: Remove (consolidate to root) - apps/web/.env.example: Update with reference to root config All linting and type checks passing ✅ Addresses review feedback from Claude Code GitHub Action. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Review: Database and API Packages with Contact Management✅ Overall AssessmentThis is a well-structured and thoughtfully implemented PR that successfully establishes the foundation for the CRM's backend architecture. The layered approach, comprehensive documentation, and attention to error handling demonstrate strong engineering practices. 🎯 Strengths1. Excellent Architecture & Separation of Concerns
2. Outstanding Documentation
3. Robust Error Handling
4. Strong Validation
5. Good Monorepo Configuration
🔍 Issues & RecommendationsCritical Issues
|
Add comprehensive error codes documentation to packages/api/CLAUDE.md: - Service error patterns for all contact service methods - Common Prisma error codes (P2025, P2002, P2003) - Server action error response format examples - Error handling best practices Addresses missing error codes documentation from code review. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Pull Request Review: Add Database and API PackagesOverall AssessmentThis is a well-structured PR that follows excellent architectural patterns. The implementation demonstrates solid understanding of layered architecture, separation of concerns, and TypeScript best practices. Great work on the comprehensive documentation! ✅ Strengths1. Excellent Architecture
2. Code Quality
3. Documentation
4. Developer Experience
🔍 Issues & RecommendationsCritical Issues1.
|
| Category | Count |
|---|---|
| Critical Issues | 2 |
| High Priority | 2 |
| Medium Priority | 4 |
| Low Priority | 2 |
| Total | 10 |
Recommended Action Plan
- Before merge: Fix critical issues Add Claude Code GitHub Workflow #1 (validation schema) and feat: add database and API packages with contact management #2 (.gitignore)
- Before merge: Address security concern chore: add Prettier configuration with Tailwind plugin #4 (health check error disclosure)
- Post-merge: Refactor error handling (feat: add Claude Code agent configurations #6) and add tests (#9)
- Future: Add pagination (#8) and improve phone validation (#7)
✨ Conclusion
This is excellent foundational work that sets up the project for success. The architecture is sound, the code is clean, and the documentation is thorough. With the critical fixes applied, this PR is ready to merge.
Great job on maintaining consistency with the project's conventions and providing such comprehensive documentation! 🎉
Reviewed with ❤️ by Claude Code
Summary
Changes
New Packages
Features
packages/api/src/services/contact.service.ts)packages/api/src/validation/contact.schema.ts)apps/web/actions/contacts.actions.ts)apps/web/app/api/health/route.ts)Infrastructure
Test plan
pnpm installworks correctlypnpm --filter @poly/database db:generateto generate Prisma Clientpnpm --filter @poly/database db:migrateto apply migrationspnpm devand verify all services run/api/healthpnpm --filter @poly/api check-typespnpm --filter @poly/api lint🤖 Generated with Claude Code