Add Obsidian Wrapped feature (inside-LMS, client-side vault parsing)
- WrappedRun Prisma model + migration (aggregates only, no note names/text) - /wrapped authed route: FSA + webkitdirectory + drag-drop reader, Web Worker parser - archetype + score heuristics, ДС-2 result card - POST /api/wrapped/run (userId from session), public /share/wrapped/[token] - next/og OG image (Satori+resvg-wasm, alpine-safe) + Fira Mono ttf - middleware: /share/wrapped public Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
-- Obsidian Wrapped — агрегаты прогона (без имён/текстов заметок)
|
||||
CREATE TABLE "WrappedRun" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"period" TEXT NOT NULL DEFAULT 'year',
|
||||
"noteCount" INTEGER NOT NULL,
|
||||
"linkCount" INTEGER NOT NULL,
|
||||
"tagCount" INTEGER NOT NULL,
|
||||
"topTag" TEXT,
|
||||
"archetype" TEXT,
|
||||
"score" INTEGER NOT NULL DEFAULT 0,
|
||||
"shareToken" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
CONSTRAINT "WrappedRun_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "WrappedRun_shareToken_key" ON "WrappedRun"("shareToken");
|
||||
CREATE INDEX "WrappedRun_userId_idx" ON "WrappedRun"("userId");
|
||||
|
||||
ALTER TABLE "WrappedRun" ADD CONSTRAINT "WrappedRun_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -45,6 +45,27 @@ model User {
|
||||
questions StudentQuestion[]
|
||||
closedQuestions StudentQuestion[] @relation("QuestionClosedBy")
|
||||
questionMessages StudentQuestionMessage[]
|
||||
wrappedRuns WrappedRun[]
|
||||
}
|
||||
|
||||
// Obsidian Wrapped — агрегаты прогона (БЕЗ имён/текстов заметок; обработка волта 100% client-side)
|
||||
model WrappedRun {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
period String @default("year") // year | quarter | all
|
||||
noteCount Int
|
||||
linkCount Int
|
||||
tagCount Int
|
||||
topTag String?
|
||||
archetype String? // architect | gardener | librarian | pragmatist
|
||||
score Int @default(0) // 0..100
|
||||
shareToken String @unique // публичная ссылка /share/wrapped/[token]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model Session {
|
||||
|
||||
Reference in New Issue
Block a user