-
Notifications
You must be signed in to change notification settings - Fork 0
Database Schema
Prisma 7.5.0-dev.33 with Neon PostgreSQL serverless adapter. Schema: packages/database/prisma/schema.prisma.
| Model | Key Fields | Notes |
|---|---|---|
| User | id, email (unique), name, image, bio, role, tokenVersion | Relations to all content models |
| Account | userId, provider, providerAccountId, tokens | NextAuth OAuth accounts |
| Session | sessionToken (unique), userId, expires | NextAuth sessions |
| VerificationToken | identifier, token, expires | Email verification |
| Model | Key Fields | Notes |
|---|---|---|
| Worksheet | title, description, content (JSON), visibility, views, version | Soft-deletable, folder-organized |
| Folder | name, description, parentId | Nested hierarchy, unique per user+name+parent |
| WorksheetShare | worksheetId, sharedWith, permission | Unique per worksheet+user |
| CalculationHistory | expression, result, mode, latex | User calculation history |
| SharedCalculation | shortCode (unique, 8 chars), latex, expression, title, result, expiresAt | Anonymous sharing supported |
| Model | Key Fields | Notes |
|---|---|---|
| ForumPost | title, content, tags[], views, isPinned, isClosed | Soft-deletable |
| Comment | content, postId, parentId | Self-referential for replies, soft-deletable |
| Upvote | userId, targetId, targetType (POST/COMMENT) | Unique per user+target |
| Model | Key Fields | Notes |
|---|---|---|
| AuditLog | userId, action, entity, entityId, metadata (JSON), ipAddress | Activity tracking |
| Model | Key Fields |
|---|---|
| Problem | title, slug (unique), difficulty, content, solution, points, successRate |
| Hint | problemId, content, order, pointCost |
| TestCase | problemId, input, expected, isHidden |
| Example | problemId, topicId, title, code, explanation |
| Topic | name, slug (unique), category, parentId (hierarchy) |
| ProblemTopic | problemId, topicId (junction) |
| Theorem | name, statement, proof, topicId |
| Resource | title, url, type (VIDEO/ARTICLE/BOOK/PAPER), topicId |
| Model | Key Fields |
|---|---|
| Algorithm | name, slug, timeComplexity, spaceComplexity, category |
| Implementation | algorithmId, language, code, explanation |
| Model | Key Fields |
|---|---|
| UserProgress | userId (unique), problemsSolved, totalPoints, streak, level, experience |
| TopicProgress | topicId, masteryLevel (0.0-1.0), timeSpent |
| Attempt | problemId, correct, timeSpent, hintsUsed, pointsEarned |
| PracticeSession | topic, difficulty, score, accuracy, totalTime |
| Achievement | name, type, icon, requirement (JSON), points |
| UserAchievement | userProgressId, achievementId, earnedAt |
| Favorite | resourceType (PROBLEM/DEFINITION), problemId |
| Enum | Values |
|---|---|
UserRole |
USER, MODERATOR, ADMIN |
WorksheetVisibility |
PRIVATE, UNLISTED, PUBLIC |
SharePermission |
VIEW, EDIT |
CellType |
CALCULATION, TEXT, HEADING, IMAGE, PLOT |
UpvoteTargetType |
POST, COMMENT |
Difficulty |
BEGINNER, INTERMEDIATE, ADVANCED, MASTER |
Category |
CALCULUS, ALGEBRA, TOPOLOGY, ANALYSIS, GEOMETRY, NUMBER_THEORY, ALGORITHMS, GAME_THEORY, CHAOS_THEORY, CRYPTOGRAPHY, QUANTUM, OPTIMIZATION, PROBABILITY, STATISTICS |
AlgorithmCategory |
SORTING, SEARCHING, GRAPH, DYNAMIC_PROGRAMMING, GREEDY, DIVIDE_CONQUER, ML_OPTIMIZATION, CRYPTOGRAPHIC, QUANTUM, NUMERICAL, STRING |
AchievementType |
PROBLEM_SOLVING, STREAK, MASTERY, SPEED, EXPLORATION, SOCIAL |
FavoriteType |
PROBLEM, DEFINITION |
- Provider: Neon PostgreSQL (serverless)
-
Adapter:
@prisma/adapter-neonwithPrismaNeon({ connectionString }) -
Config:
packages/database/prisma.config.ts(loads env fromapps/web/.env.local) -
Generated:
packages/database/src/generated/prisma/(gitignored)
Always import from @nextcalc/database, never from @prisma/client.
Models that support deletion use a deletedAt: DateTime? field instead of hard deletes. Queries filter WHERE deletedAt IS NULL by default. This applies to Worksheet, ForumPost, and Comment. To include deleted records (e.g., for admin views), explicitly remove the filter.
Forum post views and upvote counts use Prisma increment operations to prevent race conditions:
await prisma.forumPost.update({
where: { id: postId },
data: { views: { increment: 1 } },
});This avoids the read-then-write pattern that can lose increments under concurrent requests.
Key indexes for query performance:
| Index | Model | Purpose |
|---|---|---|
userId |
Worksheet, Folder, ForumPost, Comment, Upvote, CalculationHistory | Filter content by owner |
folderId |
Worksheet | List worksheets in a folder |
worksheetId |
WorksheetShare | Find shares for a worksheet |
postId |
Comment | List comments on a post |
parentId |
Folder, Comment | Traverse nested hierarchies |
shortCode |
SharedCalculation | Unique lookup for shared links |
Filtered indexes that only include non-deleted records. PostgreSQL automatically prefers these smaller indexes when queries include WHERE deletedAt IS NULL, dramatically reducing I/O for the vast majority of reads.
| Index Name | Model | Columns | Filter |
|---|---|---|---|
worksheets_userId_visibility_active_idx |
Worksheet | userId, visibility | deletedAt IS NULL |
worksheets_createdAt_active_idx |
Worksheet | createdAt DESC | deletedAt IS NULL |
forum_posts_createdAt_active_idx |
ForumPost | createdAt DESC | deletedAt IS NULL |
forum_posts_isPinned_createdAt_active_idx |
ForumPost | isPinned, createdAt DESC | deletedAt IS NULL |
comments_postId_active_idx |
Comment | postId | deletedAt IS NULL |
comments_parentId_active_idx |
Comment | parentId | deletedAt IS NULL |
problems_difficulty_popularity_active_idx |
Problem | difficulty, popularity DESC | deletedAt IS NULL |
problems_createdAt_active_idx |
Problem | createdAt DESC | deletedAt IS NULL |
Defined in schema using Prisma 7.4's type-safe syntax: @@index([field], map: "name", where: { deletedAt: null })
NextCalc Pro v1.2.1 | Home | Getting Started | Architecture | API Reference | Deployment | GitHub | Release Notes | Live Demo
v1.2.1
🏠 NextCalc Pro
📦 Packages
🔧 Backend
🚀 Operations