MVP M5.9: SQLite persistence via Prisma + optimistic-local sync
State now survives a page refresh. Every applied op writes a fresh model
snapshot + a changelog row inside one transaction; the editor route
server-component loads the latest snapshot and seeds it as the initial
ModelStore state. Optimistic-local apply on the client + background POST
to /api/projects/[id]/apply gives the UI an instant feel without giving
up the server-as-truth contract.
apps/web/prisma
- schema.prisma: Project / ModelSnapshot / ChangelogEntry. SQLite for dev
(file:./dev.db). The same schema swaps to Postgres by changing the
provider line + DATABASE_URL.
apps/web/lib/db
- client.ts: PrismaClient singleton with hot-reload guard.
- repo.ts: loadProject() auto-seeds Aristotle from fromFixture();
applyOpsToProject() runs the pure applyOps() server-side inside a
$transaction, writes the snapshot + changelog atomically, returns
{ applied, model, version, idMapping, errors }. Optimistic-concurrency
via expectedVersion → returns the server model on mismatch so the
client can resync without losing its tab.
apps/web/app/api/projects/[projectId]
- route.ts (GET): returns latest { model, version }
- apply/route.ts (POST): body is { ops, expectedVersion?, reason? }
apps/web/lib/sync/ModelStore.tsx
- Now takes initialModel + initialVersion + projectId. apply() updates
local state immediately, then POSTs in the background. On response the
authoritative server model + version replace the optimistic state
(handles tempId resolution from the server). Network errors keep the
optimistic state; the next successful apply reconciles.
apps/web/app/editor/[projectId]/page.tsx
- Server component now: awaits loadProject(projectId), passes initialModel
+ initialVersion + projectId to EditorShell. EditorShell falls back to
the fixture path when those props are absent (legacy callers / tests).
package.json
- pnpm.onlyBuiltDependencies allowlists prisma + @prisma/client + @prisma/engines
- db:push / db:generate / db:reset scripts
.gitignore
- apps/web/prisma/dev.db + dev.db-journal excluded.
Pinned to prisma@6 (prisma@7 dropped url from schema in favor of the
new adapter pattern; not worth the churn for MVP).
This commit is contained in:
@@ -6,9 +6,20 @@
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
"lint": "eslint",
|
||||
"db:push": "prisma db push --skip-generate",
|
||||
"db:generate": "prisma generate",
|
||||
"db:reset": "rm -f prisma/dev.db && pnpm db:push && pnpm db:generate"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@prisma/client",
|
||||
"@prisma/engines",
|
||||
"prisma"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.19.3",
|
||||
"@tiptap/core": "^3.22.5",
|
||||
"@tiptap/extension-mention": "^3.22.5",
|
||||
"@tiptap/pm": "^3.22.5",
|
||||
@@ -17,6 +28,7 @@
|
||||
"@tiptap/suggestion": "^3.22.5",
|
||||
"@xyflow/react": "^12.10.2",
|
||||
"next": "16.2.4",
|
||||
"prisma": "^6.19.3",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user