@goscribe/server 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTH_FRONTEND_SPEC.md +21 -0
- package/CHAT_FRONTEND_SPEC.md +474 -0
- package/MEETINGSUMMARY_FRONTEND_SPEC.md +28 -0
- package/PODCAST_FRONTEND_SPEC.md +595 -0
- package/STUDYGUIDE_FRONTEND_SPEC.md +18 -0
- package/WORKSHEETS_FRONTEND_SPEC.md +26 -0
- package/WORKSPACE_FRONTEND_SPEC.md +47 -0
- package/dist/context.d.ts +1 -1
- package/dist/lib/ai-session.d.ts +26 -0
- package/dist/lib/ai-session.js +343 -0
- package/dist/lib/auth.js +10 -6
- package/dist/lib/inference.d.ts +2 -0
- package/dist/lib/inference.js +21 -0
- package/dist/lib/pusher.d.ts +14 -0
- package/dist/lib/pusher.js +94 -0
- package/dist/lib/storage.d.ts +10 -2
- package/dist/lib/storage.js +63 -6
- package/dist/routers/_app.d.ts +878 -100
- package/dist/routers/_app.js +8 -2
- package/dist/routers/ai-session.d.ts +0 -0
- package/dist/routers/ai-session.js +1 -0
- package/dist/routers/auth.d.ts +13 -11
- package/dist/routers/auth.js +50 -21
- package/dist/routers/chat.d.ts +171 -0
- package/dist/routers/chat.js +270 -0
- package/dist/routers/flashcards.d.ts +51 -39
- package/dist/routers/flashcards.js +143 -31
- package/dist/routers/meetingsummary.d.ts +0 -0
- package/dist/routers/meetingsummary.js +377 -0
- package/dist/routers/podcast.d.ts +277 -0
- package/dist/routers/podcast.js +847 -0
- package/dist/routers/studyguide.d.ts +54 -0
- package/dist/routers/studyguide.js +125 -0
- package/dist/routers/worksheets.d.ts +147 -40
- package/dist/routers/worksheets.js +348 -33
- package/dist/routers/workspace.d.ts +163 -8
- package/dist/routers/workspace.js +453 -8
- package/dist/server.d.ts +1 -1
- package/dist/server.js +7 -2
- package/dist/trpc.d.ts +5 -5
- package/package.json +11 -3
- package/prisma/migrations/20250826124819_add_worksheet_difficulty_and_estimated_time/migration.sql +213 -0
- package/prisma/migrations/20250826133236_add_worksheet_question_progress/migration.sql +31 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +87 -6
- package/prisma/seed.mjs +135 -0
- package/src/lib/ai-session.ts +411 -0
- package/src/lib/auth.ts +1 -1
- package/src/lib/inference.ts +21 -0
- package/src/lib/pusher.ts +104 -0
- package/src/lib/storage.ts +89 -6
- package/src/routers/_app.ts +6 -0
- package/src/routers/auth.ts +8 -4
- package/src/routers/chat.ts +275 -0
- package/src/routers/flashcards.ts +151 -33
- package/src/routers/meetingsummary.ts +416 -0
- package/src/routers/podcast.ts +934 -0
- package/src/routers/studyguide.ts +144 -0
- package/src/routers/worksheets.ts +346 -18
- package/src/routers/workspace.ts +500 -8
- package/src/server.ts +7 -2
- package/test-ai-integration.js +134 -0
- package/dist/context.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/lib/auth.d.ts.map +0 -1
- package/dist/lib/file.d.ts.map +0 -1
- package/dist/lib/prisma.d.ts.map +0 -1
- package/dist/lib/storage.d.ts.map +0 -1
- package/dist/routers/_app.d.ts.map +0 -1
- package/dist/routers/auth.d.ts.map +0 -1
- package/dist/routers/sample.js +0 -21
- package/dist/routers/workspace.d.ts.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/trpc.d.ts.map +0 -1
package/prisma/migrations/20250826124819_add_worksheet_difficulty_and_estimated_time/migration.sql
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
-- CreateEnum
|
|
2
|
+
CREATE TYPE "public"."ArtifactType" AS ENUM ('STUDY_GUIDE', 'FLASHCARD_SET', 'WORKSHEET', 'MEETING_SUMMARY', 'PODCAST_EPISODE');
|
|
3
|
+
|
|
4
|
+
-- CreateEnum
|
|
5
|
+
CREATE TYPE "public"."Difficulty" AS ENUM ('EASY', 'MEDIUM', 'HARD');
|
|
6
|
+
|
|
7
|
+
-- CreateEnum
|
|
8
|
+
CREATE TYPE "public"."QuestionType" AS ENUM ('MULTIPLE_CHOICE', 'TEXT', 'NUMERIC', 'TRUE_FALSE', 'MATCHING', 'FILL_IN_THE_BLANK');
|
|
9
|
+
|
|
10
|
+
-- CreateTable
|
|
11
|
+
CREATE TABLE "public"."User" (
|
|
12
|
+
"id" TEXT NOT NULL,
|
|
13
|
+
"name" TEXT,
|
|
14
|
+
"email" TEXT,
|
|
15
|
+
"emailVerified" TIMESTAMP(3),
|
|
16
|
+
"passwordHash" TEXT,
|
|
17
|
+
"image" TEXT,
|
|
18
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
19
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
20
|
+
|
|
21
|
+
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
-- CreateTable
|
|
25
|
+
CREATE TABLE "public"."Session" (
|
|
26
|
+
"id" TEXT NOT NULL,
|
|
27
|
+
"userId" TEXT NOT NULL,
|
|
28
|
+
"expires" TIMESTAMP(3) NOT NULL,
|
|
29
|
+
|
|
30
|
+
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
-- CreateTable
|
|
34
|
+
CREATE TABLE "public"."VerificationToken" (
|
|
35
|
+
"identifier" TEXT NOT NULL,
|
|
36
|
+
"token" TEXT NOT NULL,
|
|
37
|
+
"expires" TIMESTAMP(3) NOT NULL
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
-- CreateTable
|
|
41
|
+
CREATE TABLE "public"."Folder" (
|
|
42
|
+
"id" TEXT NOT NULL,
|
|
43
|
+
"name" TEXT NOT NULL,
|
|
44
|
+
"ownerId" TEXT NOT NULL,
|
|
45
|
+
"parentId" TEXT,
|
|
46
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
47
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
48
|
+
|
|
49
|
+
CONSTRAINT "Folder_pkey" PRIMARY KEY ("id")
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- CreateTable
|
|
53
|
+
CREATE TABLE "public"."Workspace" (
|
|
54
|
+
"id" TEXT NOT NULL,
|
|
55
|
+
"title" TEXT NOT NULL,
|
|
56
|
+
"description" TEXT,
|
|
57
|
+
"ownerId" TEXT NOT NULL,
|
|
58
|
+
"folderId" TEXT,
|
|
59
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
60
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
61
|
+
|
|
62
|
+
CONSTRAINT "Workspace_pkey" PRIMARY KEY ("id")
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
-- CreateTable
|
|
66
|
+
CREATE TABLE "public"."FileAsset" (
|
|
67
|
+
"id" TEXT NOT NULL,
|
|
68
|
+
"workspaceId" TEXT NOT NULL,
|
|
69
|
+
"userId" TEXT NOT NULL,
|
|
70
|
+
"name" TEXT NOT NULL,
|
|
71
|
+
"mimeType" TEXT NOT NULL,
|
|
72
|
+
"size" INTEGER NOT NULL,
|
|
73
|
+
"bucket" TEXT,
|
|
74
|
+
"objectKey" TEXT,
|
|
75
|
+
"url" TEXT,
|
|
76
|
+
"checksum" TEXT,
|
|
77
|
+
"meta" JSONB,
|
|
78
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
79
|
+
|
|
80
|
+
CONSTRAINT "FileAsset_pkey" PRIMARY KEY ("id")
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
-- CreateTable
|
|
84
|
+
CREATE TABLE "public"."Artifact" (
|
|
85
|
+
"id" TEXT NOT NULL,
|
|
86
|
+
"workspaceId" TEXT NOT NULL,
|
|
87
|
+
"type" "public"."ArtifactType" NOT NULL,
|
|
88
|
+
"title" TEXT NOT NULL,
|
|
89
|
+
"isArchived" BOOLEAN NOT NULL DEFAULT false,
|
|
90
|
+
"difficulty" "public"."Difficulty",
|
|
91
|
+
"estimatedTime" TEXT,
|
|
92
|
+
"createdById" TEXT,
|
|
93
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
94
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
95
|
+
|
|
96
|
+
CONSTRAINT "Artifact_pkey" PRIMARY KEY ("id")
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
-- CreateTable
|
|
100
|
+
CREATE TABLE "public"."ArtifactVersion" (
|
|
101
|
+
"id" TEXT NOT NULL,
|
|
102
|
+
"artifactId" TEXT NOT NULL,
|
|
103
|
+
"content" TEXT NOT NULL,
|
|
104
|
+
"data" JSONB,
|
|
105
|
+
"version" INTEGER NOT NULL,
|
|
106
|
+
"createdById" TEXT,
|
|
107
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
108
|
+
|
|
109
|
+
CONSTRAINT "ArtifactVersion_pkey" PRIMARY KEY ("id")
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
-- CreateTable
|
|
113
|
+
CREATE TABLE "public"."Flashcard" (
|
|
114
|
+
"id" TEXT NOT NULL,
|
|
115
|
+
"artifactId" TEXT NOT NULL,
|
|
116
|
+
"front" TEXT NOT NULL,
|
|
117
|
+
"back" TEXT NOT NULL,
|
|
118
|
+
"tags" TEXT[],
|
|
119
|
+
"order" INTEGER NOT NULL DEFAULT 0,
|
|
120
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
121
|
+
|
|
122
|
+
CONSTRAINT "Flashcard_pkey" PRIMARY KEY ("id")
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
-- CreateTable
|
|
126
|
+
CREATE TABLE "public"."WorksheetQuestion" (
|
|
127
|
+
"id" TEXT NOT NULL,
|
|
128
|
+
"artifactId" TEXT NOT NULL,
|
|
129
|
+
"prompt" TEXT NOT NULL,
|
|
130
|
+
"answer" TEXT,
|
|
131
|
+
"type" "public"."QuestionType" NOT NULL DEFAULT 'TEXT',
|
|
132
|
+
"difficulty" "public"."Difficulty" NOT NULL DEFAULT 'MEDIUM',
|
|
133
|
+
"order" INTEGER NOT NULL DEFAULT 0,
|
|
134
|
+
"meta" JSONB,
|
|
135
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
136
|
+
|
|
137
|
+
CONSTRAINT "WorksheetQuestion_pkey" PRIMARY KEY ("id")
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
-- CreateIndex
|
|
141
|
+
CREATE UNIQUE INDEX "User_email_key" ON "public"."User"("email");
|
|
142
|
+
|
|
143
|
+
-- CreateIndex
|
|
144
|
+
CREATE UNIQUE INDEX "VerificationToken_token_key" ON "public"."VerificationToken"("token");
|
|
145
|
+
|
|
146
|
+
-- CreateIndex
|
|
147
|
+
CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "public"."VerificationToken"("identifier", "token");
|
|
148
|
+
|
|
149
|
+
-- CreateIndex
|
|
150
|
+
CREATE INDEX "Folder_ownerId_parentId_idx" ON "public"."Folder"("ownerId", "parentId");
|
|
151
|
+
|
|
152
|
+
-- CreateIndex
|
|
153
|
+
CREATE INDEX "Workspace_ownerId_folderId_idx" ON "public"."Workspace"("ownerId", "folderId");
|
|
154
|
+
|
|
155
|
+
-- CreateIndex
|
|
156
|
+
CREATE INDEX "FileAsset_workspaceId_idx" ON "public"."FileAsset"("workspaceId");
|
|
157
|
+
|
|
158
|
+
-- CreateIndex
|
|
159
|
+
CREATE INDEX "FileAsset_userId_createdAt_idx" ON "public"."FileAsset"("userId", "createdAt");
|
|
160
|
+
|
|
161
|
+
-- CreateIndex
|
|
162
|
+
CREATE INDEX "Artifact_workspaceId_type_idx" ON "public"."Artifact"("workspaceId", "type");
|
|
163
|
+
|
|
164
|
+
-- CreateIndex
|
|
165
|
+
CREATE INDEX "ArtifactVersion_artifactId_idx" ON "public"."ArtifactVersion"("artifactId");
|
|
166
|
+
|
|
167
|
+
-- CreateIndex
|
|
168
|
+
CREATE UNIQUE INDEX "ArtifactVersion_artifactId_version_key" ON "public"."ArtifactVersion"("artifactId", "version");
|
|
169
|
+
|
|
170
|
+
-- CreateIndex
|
|
171
|
+
CREATE INDEX "Flashcard_artifactId_idx" ON "public"."Flashcard"("artifactId");
|
|
172
|
+
|
|
173
|
+
-- CreateIndex
|
|
174
|
+
CREATE INDEX "WorksheetQuestion_artifactId_idx" ON "public"."WorksheetQuestion"("artifactId");
|
|
175
|
+
|
|
176
|
+
-- AddForeignKey
|
|
177
|
+
ALTER TABLE "public"."Session" ADD CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
178
|
+
|
|
179
|
+
-- AddForeignKey
|
|
180
|
+
ALTER TABLE "public"."Folder" ADD CONSTRAINT "Folder_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
181
|
+
|
|
182
|
+
-- AddForeignKey
|
|
183
|
+
ALTER TABLE "public"."Folder" ADD CONSTRAINT "Folder_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "public"."Folder"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
184
|
+
|
|
185
|
+
-- AddForeignKey
|
|
186
|
+
ALTER TABLE "public"."Workspace" ADD CONSTRAINT "Workspace_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
187
|
+
|
|
188
|
+
-- AddForeignKey
|
|
189
|
+
ALTER TABLE "public"."Workspace" ADD CONSTRAINT "Workspace_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "public"."Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
190
|
+
|
|
191
|
+
-- AddForeignKey
|
|
192
|
+
ALTER TABLE "public"."FileAsset" ADD CONSTRAINT "FileAsset_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "public"."Workspace"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
193
|
+
|
|
194
|
+
-- AddForeignKey
|
|
195
|
+
ALTER TABLE "public"."FileAsset" ADD CONSTRAINT "FileAsset_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
196
|
+
|
|
197
|
+
-- AddForeignKey
|
|
198
|
+
ALTER TABLE "public"."Artifact" ADD CONSTRAINT "Artifact_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "public"."Workspace"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
199
|
+
|
|
200
|
+
-- AddForeignKey
|
|
201
|
+
ALTER TABLE "public"."Artifact" ADD CONSTRAINT "Artifact_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
202
|
+
|
|
203
|
+
-- AddForeignKey
|
|
204
|
+
ALTER TABLE "public"."ArtifactVersion" ADD CONSTRAINT "ArtifactVersion_artifactId_fkey" FOREIGN KEY ("artifactId") REFERENCES "public"."Artifact"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
205
|
+
|
|
206
|
+
-- AddForeignKey
|
|
207
|
+
ALTER TABLE "public"."ArtifactVersion" ADD CONSTRAINT "ArtifactVersion_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "public"."User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
208
|
+
|
|
209
|
+
-- AddForeignKey
|
|
210
|
+
ALTER TABLE "public"."Flashcard" ADD CONSTRAINT "Flashcard_artifactId_fkey" FOREIGN KEY ("artifactId") REFERENCES "public"."Artifact"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
211
|
+
|
|
212
|
+
-- AddForeignKey
|
|
213
|
+
ALTER TABLE "public"."WorksheetQuestion" ADD CONSTRAINT "WorksheetQuestion_artifactId_fkey" FOREIGN KEY ("artifactId") REFERENCES "public"."Artifact"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- AlterTable
|
|
2
|
+
ALTER TABLE "public"."Artifact" ADD COLUMN "description" TEXT;
|
|
3
|
+
|
|
4
|
+
-- CreateTable
|
|
5
|
+
CREATE TABLE "public"."WorksheetQuestionProgress" (
|
|
6
|
+
"id" TEXT NOT NULL,
|
|
7
|
+
"worksheetQuestionId" TEXT NOT NULL,
|
|
8
|
+
"userId" TEXT NOT NULL,
|
|
9
|
+
"completed" BOOLEAN NOT NULL DEFAULT false,
|
|
10
|
+
"userAnswer" TEXT,
|
|
11
|
+
"completedAt" TIMESTAMP(3),
|
|
12
|
+
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
"timeSpentSec" INTEGER,
|
|
14
|
+
"meta" JSONB,
|
|
15
|
+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
16
|
+
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
17
|
+
|
|
18
|
+
CONSTRAINT "WorksheetQuestionProgress_pkey" PRIMARY KEY ("id")
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
-- CreateIndex
|
|
22
|
+
CREATE INDEX "WorksheetQuestionProgress_userId_idx" ON "public"."WorksheetQuestionProgress"("userId");
|
|
23
|
+
|
|
24
|
+
-- CreateIndex
|
|
25
|
+
CREATE UNIQUE INDEX "WorksheetQuestionProgress_worksheetQuestionId_userId_key" ON "public"."WorksheetQuestionProgress"("worksheetQuestionId", "userId");
|
|
26
|
+
|
|
27
|
+
-- AddForeignKey
|
|
28
|
+
ALTER TABLE "public"."WorksheetQuestionProgress" ADD CONSTRAINT "WorksheetQuestionProgress_worksheetQuestionId_fkey" FOREIGN KEY ("worksheetQuestionId") REFERENCES "public"."WorksheetQuestion"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
29
|
+
|
|
30
|
+
-- AddForeignKey
|
|
31
|
+
ALTER TABLE "public"."WorksheetQuestionProgress" ADD CONSTRAINT "WorksheetQuestionProgress_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
package/prisma/schema.prisma
CHANGED
|
@@ -26,6 +26,15 @@ enum Difficulty {
|
|
|
26
26
|
HARD
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
enum QuestionType {
|
|
30
|
+
MULTIPLE_CHOICE
|
|
31
|
+
TEXT
|
|
32
|
+
NUMERIC
|
|
33
|
+
TRUE_FALSE
|
|
34
|
+
MATCHING
|
|
35
|
+
FILL_IN_THE_BLANK
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
//
|
|
30
39
|
// NextAuth-compatible auth models (minimal)
|
|
31
40
|
//
|
|
@@ -41,10 +50,13 @@ model User {
|
|
|
41
50
|
// Ownership
|
|
42
51
|
folders Folder[] @relation("UserFolders")
|
|
43
52
|
workspaces Workspace[] @relation("UserWorkspaces")
|
|
53
|
+
invitedInWorkspaces Workspace[] @relation("WorkspaceSharedWith") // many-to-many
|
|
44
54
|
uploads FileAsset[] @relation("UserUploads")
|
|
45
55
|
artifacts Artifact[] @relation("UserArtifacts")
|
|
46
56
|
versions ArtifactVersion[] @relation("UserArtifactVersions")
|
|
57
|
+
worksheetQuestionProgress WorksheetQuestionProgress[]
|
|
47
58
|
|
|
59
|
+
chats Chat[]
|
|
48
60
|
createdAt DateTime @default(now())
|
|
49
61
|
updatedAt DateTime @updatedAt
|
|
50
62
|
}
|
|
@@ -77,6 +89,7 @@ model Folder {
|
|
|
77
89
|
parentId String?
|
|
78
90
|
parent Folder? @relation("FolderChildren", fields: [parentId], references: [id], onDelete: Cascade)
|
|
79
91
|
children Folder[] @relation("FolderChildren")
|
|
92
|
+
color String @default("#9D00FF")
|
|
80
93
|
|
|
81
94
|
// Files (workspaces) inside folders
|
|
82
95
|
workspaces Workspace[]
|
|
@@ -95,10 +108,17 @@ model Workspace {
|
|
|
95
108
|
description String? // optional notes/description for the "file"
|
|
96
109
|
ownerId String
|
|
97
110
|
owner User @relation("UserWorkspaces", fields: [ownerId], references: [id], onDelete: Cascade)
|
|
111
|
+
icon String @default("📄")
|
|
98
112
|
|
|
99
113
|
// A workspace (file) lives in a folder (nullable = root)
|
|
100
114
|
folderId String?
|
|
101
115
|
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
116
|
+
|
|
117
|
+
channels Channel[]
|
|
118
|
+
|
|
119
|
+
shareLink String? @unique // optional public share link
|
|
120
|
+
|
|
121
|
+
sharedWith User[] @relation("WorkspaceSharedWith") // many-to-many for sharing
|
|
102
122
|
|
|
103
123
|
// Raw uploads attached to this workspace
|
|
104
124
|
uploads FileAsset[]
|
|
@@ -112,6 +132,34 @@ model Workspace {
|
|
|
112
132
|
@@index([ownerId, folderId])
|
|
113
133
|
}
|
|
114
134
|
|
|
135
|
+
model Channel {
|
|
136
|
+
id String @id @default(cuid())
|
|
137
|
+
workspaceId String
|
|
138
|
+
workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
|
|
139
|
+
|
|
140
|
+
name String
|
|
141
|
+
|
|
142
|
+
createdAt DateTime @default(now())
|
|
143
|
+
chats Chat[]
|
|
144
|
+
|
|
145
|
+
@@index([workspaceId])
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
model Chat {
|
|
149
|
+
id String @id @default(cuid())
|
|
150
|
+
channelId String
|
|
151
|
+
channel Channel @relation(fields: [channelId], references: [id], onDelete: Cascade)
|
|
152
|
+
|
|
153
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
154
|
+
userId String?
|
|
155
|
+
message String // chat message content
|
|
156
|
+
|
|
157
|
+
updatedAt DateTime @updatedAt
|
|
158
|
+
createdAt DateTime @default(now())
|
|
159
|
+
|
|
160
|
+
@@index([channelId, createdAt])
|
|
161
|
+
}
|
|
162
|
+
|
|
115
163
|
//
|
|
116
164
|
// User uploads (source materials for AI)
|
|
117
165
|
//
|
|
@@ -153,6 +201,12 @@ model Artifact {
|
|
|
153
201
|
title String
|
|
154
202
|
isArchived Boolean @default(false)
|
|
155
203
|
|
|
204
|
+
// Worksheet-specific fields
|
|
205
|
+
difficulty Difficulty? // only meaningful for WORKSHEET
|
|
206
|
+
estimatedTime String? // only meaningful for WORKSHEET
|
|
207
|
+
|
|
208
|
+
description String?
|
|
209
|
+
|
|
156
210
|
createdById String?
|
|
157
211
|
createdBy User? @relation("UserArtifacts", fields: [createdById], references: [id], onDelete: SetNull)
|
|
158
212
|
|
|
@@ -211,18 +265,45 @@ model Flashcard {
|
|
|
211
265
|
// Worksheet Questions (child items of a WORKSHEET Artifact)
|
|
212
266
|
//
|
|
213
267
|
model WorksheetQuestion {
|
|
214
|
-
id String
|
|
268
|
+
id String @id @default(cuid())
|
|
215
269
|
artifactId String
|
|
216
|
-
artifact Artifact
|
|
270
|
+
artifact Artifact @relation(fields: [artifactId], references: [id], onDelete: Cascade)
|
|
217
271
|
|
|
218
272
|
prompt String
|
|
219
273
|
answer String?
|
|
220
|
-
|
|
221
|
-
|
|
274
|
+
type QuestionType @default(TEXT)
|
|
275
|
+
difficulty Difficulty @default(MEDIUM)
|
|
276
|
+
order Int @default(0)
|
|
222
277
|
|
|
223
|
-
meta Json?
|
|
278
|
+
meta Json? // e.g., { "choices": ["A","B","C","D"], "correct": 1, "options": [...] }
|
|
224
279
|
|
|
225
|
-
createdAt DateTime
|
|
280
|
+
createdAt DateTime @default(now())
|
|
226
281
|
|
|
227
282
|
@@index([artifactId])
|
|
283
|
+
progress WorksheetQuestionProgress[]
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//
|
|
287
|
+
// Per-user progress for Worksheet Questions
|
|
288
|
+
//
|
|
289
|
+
model WorksheetQuestionProgress {
|
|
290
|
+
id String @id @default(cuid())
|
|
291
|
+
worksheetQuestionId String
|
|
292
|
+
worksheetQuestion WorksheetQuestion @relation(fields: [worksheetQuestionId], references: [id], onDelete: Cascade)
|
|
293
|
+
|
|
294
|
+
userId String
|
|
295
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
296
|
+
|
|
297
|
+
completed Boolean @default(false)
|
|
298
|
+
userAnswer String?
|
|
299
|
+
completedAt DateTime?
|
|
300
|
+
attempts Int @default(0)
|
|
301
|
+
timeSpentSec Int?
|
|
302
|
+
meta Json?
|
|
303
|
+
|
|
304
|
+
createdAt DateTime @default(now())
|
|
305
|
+
updatedAt DateTime @updatedAt
|
|
306
|
+
|
|
307
|
+
@@unique([worksheetQuestionId, userId])
|
|
308
|
+
@@index([userId])
|
|
228
309
|
}
|
package/prisma/seed.mjs
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
|
|
3
|
+
const prisma = new PrismaClient();
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
// Create/find a demo user
|
|
7
|
+
const userEmail = 'demo@example.com';
|
|
8
|
+
const user = await prisma.user.upsert({
|
|
9
|
+
where: { email: userEmail },
|
|
10
|
+
update: {},
|
|
11
|
+
create: {
|
|
12
|
+
email: userEmail,
|
|
13
|
+
name: 'Demo User',
|
|
14
|
+
image: null,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Create a workspace
|
|
19
|
+
const workspace = await prisma.workspace.upsert({
|
|
20
|
+
where: { id: 'ws_demo_1' },
|
|
21
|
+
update: {},
|
|
22
|
+
create: {
|
|
23
|
+
id: 'ws_demo_1',
|
|
24
|
+
title: 'Demo Workspace',
|
|
25
|
+
description: 'Seeded workspace with sample artifacts',
|
|
26
|
+
ownerId: user.id,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Create a Worksheet artifact with diverse question types
|
|
31
|
+
const worksheet = await prisma.artifact.create({
|
|
32
|
+
data: {
|
|
33
|
+
workspaceId: workspace.id,
|
|
34
|
+
type: 'WORKSHEET',
|
|
35
|
+
title: 'Sample Worksheet: Mixed Question Types',
|
|
36
|
+
createdById: user.id,
|
|
37
|
+
questions: {
|
|
38
|
+
create: [
|
|
39
|
+
{
|
|
40
|
+
prompt: 'What is the capital of France?',
|
|
41
|
+
answer: 'Paris',
|
|
42
|
+
type: 'TEXT',
|
|
43
|
+
order: 0,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
prompt: '2 + 2 = ?',
|
|
47
|
+
answer: '4',
|
|
48
|
+
type: 'NUMERIC',
|
|
49
|
+
order: 1,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
prompt: 'Select the prime numbers',
|
|
53
|
+
answer: '2',
|
|
54
|
+
type: 'MULTIPLE_CHOICE',
|
|
55
|
+
order: 2,
|
|
56
|
+
meta: { options: ['1', '2', '4', '6'] },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
prompt: 'The earth is flat.',
|
|
60
|
+
answer: 'False',
|
|
61
|
+
type: 'TRUE_FALSE',
|
|
62
|
+
order: 3,
|
|
63
|
+
meta: { options: ['True', 'False'] },
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
prompt: 'Match the country to its capital (type answers).',
|
|
67
|
+
answer: '',
|
|
68
|
+
type: 'MATCHING',
|
|
69
|
+
order: 4,
|
|
70
|
+
meta: { options: ['Japan ->', 'Germany ->', 'Canada ->'] },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
prompt: 'The chemical symbol for water is ____.',
|
|
74
|
+
answer: 'H2O',
|
|
75
|
+
type: 'FILL_IN_THE_BLANK',
|
|
76
|
+
order: 5,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
include: { questions: true },
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Create a Flashcard set artifact with a couple of cards
|
|
85
|
+
const flashcardSet = await prisma.artifact.create({
|
|
86
|
+
data: {
|
|
87
|
+
workspaceId: workspace.id,
|
|
88
|
+
type: 'FLASHCARD_SET',
|
|
89
|
+
title: 'Sample Flashcards: Basics',
|
|
90
|
+
createdById: user.id,
|
|
91
|
+
flashcards: {
|
|
92
|
+
create: [
|
|
93
|
+
{ front: 'HTTP Status 200', back: 'OK', order: 0 },
|
|
94
|
+
{ front: 'HTTP Status 404', back: 'Not Found', order: 1 },
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
include: { flashcards: true },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Add a simple study guide versioned artifact
|
|
102
|
+
const studyGuide = await prisma.artifact.create({
|
|
103
|
+
data: {
|
|
104
|
+
workspaceId: workspace.id,
|
|
105
|
+
type: 'STUDY_GUIDE',
|
|
106
|
+
title: 'Sample Study Guide',
|
|
107
|
+
createdById: user.id,
|
|
108
|
+
versions: {
|
|
109
|
+
create: [
|
|
110
|
+
{ content: '# Intro\nThis is a seeded study guide.', version: 1, createdById: user.id },
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
include: { versions: true },
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
console.log('Seed complete:', {
|
|
118
|
+
user: { id: user.id, email: user.email },
|
|
119
|
+
workspace: { id: workspace.id, title: workspace.title },
|
|
120
|
+
worksheet: { id: worksheet.id, title: worksheet.title, questions: worksheet.questions.length },
|
|
121
|
+
flashcardSet: { id: flashcardSet.id, cards: flashcardSet.flashcards.length },
|
|
122
|
+
studyGuide: { id: studyGuide.id, versions: studyGuide.versions.length },
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
main()
|
|
127
|
+
.catch((e) => {
|
|
128
|
+
console.error(e);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
})
|
|
131
|
+
.finally(async () => {
|
|
132
|
+
await prisma.$disconnect();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
|