@danielcok17/prisma-db 1.18.0 → 1.19.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielcok17/prisma-db",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Shared Prisma schema for Legal AI applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/prisma/app.prisma CHANGED
@@ -137,6 +137,11 @@ model User {
137
137
  sequenceEnrollments EmailSequenceEnrollment[]
138
138
  referralsSent Referral[] @relation("ReferralsSent")
139
139
  referralsReceived Referral[] @relation("ReferralsReceived")
140
+ // Files & folders system
141
+ userFiles UserFile[] @relation("UserFiles")
142
+ reviewTables FileReviewTable[] @relation("UserReviewTables")
143
+ filesTotalBytes BigInt @default(0)
144
+ filesCount Int @default(0)
140
145
 
141
146
  // Multi-brand: compound unique allows same email across brands
142
147
  @@unique([email, brand])
@@ -325,6 +330,7 @@ model Answer {
325
330
  WorkflowLog WorkflowLog[]
326
331
  files MessageFile[]
327
332
  canvasDocumentId String? // No FK constraint - flexible document management
333
+ userFiles UserFile[] @relation("UserFileAnswers")
328
334
 
329
335
  @@index([conversationId])
330
336
  @@index([messageId])
@@ -890,7 +896,8 @@ enum FolderItemType {
890
896
  CONVERSATION
891
897
  CANVAS_DOCUMENT
892
898
  REFERENCE
893
- ATTACHMENT
899
+ ATTACHMENT // deprecated — kept for migration of old data
900
+ USER_FILE
894
901
  }
895
902
 
896
903
  // Folder activity types (for timeline)
@@ -902,10 +909,35 @@ enum FolderActivityType {
902
909
  ITEM_ADDED
903
910
  ITEM_REMOVED
904
911
  ITEM_UPDATED
912
+ ITEM_MOVED
905
913
  SHARE_ADDED
906
914
  SHARE_REMOVED
907
915
  USER_MESSAGE
908
916
  USER_NOTE
917
+ FILE_INDEXED
918
+ FILE_INDEX_ERROR
919
+ }
920
+
921
+ enum UserFileStatus {
922
+ STORED
923
+ QUEUED
924
+ INDEXING
925
+ INDEXED
926
+ ERROR
927
+ DELETED
928
+ }
929
+
930
+ enum IndexingJobStatus {
931
+ QUEUED
932
+ RUNNING
933
+ COMPLETED
934
+ FAILED
935
+ }
936
+
937
+ enum FolderType {
938
+ PERSONAL
939
+ MATTER
940
+ KNOWLEDGE_BASE
909
941
  }
910
942
 
911
943
  // Folder permission levels
@@ -1089,6 +1121,121 @@ enum IngestionStatus {
1089
1121
  ERROR
1090
1122
  }
1091
1123
 
1124
+ model UserFile {
1125
+ id String @id @default(cuid())
1126
+ userId String
1127
+
1128
+ storageKey String @unique
1129
+ storageUrl String?
1130
+ checksumSha256 String
1131
+
1132
+ fileName String
1133
+ fileType String
1134
+ fileSize Int
1135
+ pageCount Int?
1136
+ language String? @default("sk")
1137
+
1138
+ status UserFileStatus @default(STORED)
1139
+
1140
+ docType String?
1141
+ legalArea String?
1142
+ summary String?
1143
+ extractedData Json?
1144
+ references String[] @default([])
1145
+ chunkCount Int?
1146
+ qdrantDocId String? @unique
1147
+ indexingCost Float?
1148
+ indexedAt DateTime?
1149
+ indexError String?
1150
+
1151
+ tags String[] @default([])
1152
+
1153
+ parentFileId String?
1154
+ versionNumber Int @default(1)
1155
+
1156
+ answerId String?
1157
+
1158
+ createdAt DateTime @default(now())
1159
+ updatedAt DateTime @updatedAt
1160
+ deletedAt DateTime?
1161
+
1162
+ user User @relation("UserFiles", fields: [userId], references: [id], onDelete: Cascade)
1163
+ answer Answer? @relation("UserFileAnswers", fields: [answerId], references: [id], onDelete: SetNull)
1164
+ indexingJobs FileIndexingJob[]
1165
+ deadlines FileDeadline[]
1166
+ parentFile UserFile? @relation("FileVersions", fields: [parentFileId], references: [id], onDelete: SetNull)
1167
+ childVersions UserFile[] @relation("FileVersions")
1168
+
1169
+ @@index([userId])
1170
+ @@index([status])
1171
+ @@index([userId, status])
1172
+ @@index([userId, deletedAt])
1173
+ @@index([qdrantDocId])
1174
+ @@index([answerId])
1175
+ @@index([checksumSha256])
1176
+ }
1177
+
1178
+ model FileIndexingJob {
1179
+ id String @id @default(cuid())
1180
+ fileId String
1181
+ userId String
1182
+ status IndexingJobStatus @default(QUEUED)
1183
+ attempts Int @default(0)
1184
+ maxAttempts Int @default(3)
1185
+ errorMsg String?
1186
+ startedAt DateTime?
1187
+ finishedAt DateTime?
1188
+ createdAt DateTime @default(now())
1189
+
1190
+ file UserFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
1191
+
1192
+ @@index([fileId])
1193
+ @@index([userId])
1194
+ @@index([status])
1195
+ @@index([createdAt])
1196
+ }
1197
+
1198
+ model FileDeadline {
1199
+ id String @id @default(cuid())
1200
+ fileId String
1201
+ userId String
1202
+ label String
1203
+ deadlineAt DateTime
1204
+ notifyAt DateTime?
1205
+ isNotified Boolean @default(false)
1206
+ isDismissed Boolean @default(false)
1207
+ sourceSection String?
1208
+ sourcePage Int?
1209
+ createdAt DateTime @default(now())
1210
+
1211
+ file UserFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
1212
+
1213
+ @@index([fileId])
1214
+ @@index([userId])
1215
+ @@index([deadlineAt])
1216
+ @@index([notifyAt, isNotified])
1217
+ @@index([userId, isDismissed])
1218
+ }
1219
+
1220
+ model FileReviewTable {
1221
+ id String @id @default(cuid())
1222
+ userId String
1223
+ folderId String?
1224
+ name String
1225
+ columns Json
1226
+ fileIds String[] @default([])
1227
+ results Json?
1228
+ status String @default("draft")
1229
+ createdAt DateTime @default(now())
1230
+ updatedAt DateTime @updatedAt
1231
+
1232
+ user User @relation("UserReviewTables", fields: [userId], references: [id], onDelete: Cascade)
1233
+
1234
+ @@index([userId])
1235
+ @@index([folderId])
1236
+ @@index([status])
1237
+ }
1238
+
1092
1239
  enum LifecycleStage {
1093
1240
  REGISTERED
1094
1241
  ACTIVATED
@@ -1237,6 +1384,9 @@ model Folder {
1237
1384
  path String @default("/") // Materialized path: "/parentId/grandparentId/..."
1238
1385
  depth Int @default(0)
1239
1386
 
1387
+ // Folder type
1388
+ folderType FolderType @default(PERSONAL)
1389
+
1240
1390
  // Metadata
1241
1391
  sortOrder Int @default(0)
1242
1392
  isArchived Boolean @default(false)
@@ -0,0 +1,194 @@
1
+ -- CreateEnum
2
+ CREATE TYPE "UserFileStatus" AS ENUM ('STORED', 'QUEUED', 'INDEXING', 'INDEXED', 'ERROR', 'DELETED');
3
+
4
+ -- CreateEnum
5
+ CREATE TYPE "IndexingJobStatus" AS ENUM ('QUEUED', 'RUNNING', 'COMPLETED', 'FAILED');
6
+
7
+ -- CreateEnum
8
+ CREATE TYPE "FolderType" AS ENUM ('PERSONAL', 'MATTER', 'KNOWLEDGE_BASE');
9
+
10
+ -- AlterEnum
11
+ -- This migration adds more than one value to an enum.
12
+ -- With PostgreSQL versions 11 and earlier, this is not possible
13
+ -- in a single migration. This can be worked around by creating
14
+ -- multiple migrations, each migration adding only one value to
15
+ -- the enum.
16
+
17
+
18
+ ALTER TYPE "FolderActivityType" ADD VALUE 'ITEM_MOVED';
19
+ ALTER TYPE "FolderActivityType" ADD VALUE 'FILE_INDEXED';
20
+ ALTER TYPE "FolderActivityType" ADD VALUE 'FILE_INDEX_ERROR';
21
+
22
+ -- AlterEnum
23
+ ALTER TYPE "FolderItemType" ADD VALUE 'USER_FILE';
24
+
25
+ -- AlterTable
26
+ ALTER TABLE "Folder" ADD COLUMN "folderType" "FolderType" NOT NULL DEFAULT 'PERSONAL';
27
+
28
+ -- AlterTable
29
+ ALTER TABLE "User" ADD COLUMN "filesCount" INTEGER NOT NULL DEFAULT 0,
30
+ ADD COLUMN "filesTotalBytes" BIGINT NOT NULL DEFAULT 0;
31
+
32
+ -- CreateTable
33
+ CREATE TABLE "UserFile" (
34
+ "id" TEXT NOT NULL,
35
+ "userId" TEXT NOT NULL,
36
+ "storageKey" TEXT NOT NULL,
37
+ "storageUrl" TEXT,
38
+ "checksumSha256" TEXT NOT NULL,
39
+ "fileName" TEXT NOT NULL,
40
+ "fileType" TEXT NOT NULL,
41
+ "fileSize" INTEGER NOT NULL,
42
+ "pageCount" INTEGER,
43
+ "language" TEXT DEFAULT 'sk',
44
+ "status" "UserFileStatus" NOT NULL DEFAULT 'STORED',
45
+ "docType" TEXT,
46
+ "legalArea" TEXT,
47
+ "summary" TEXT,
48
+ "extractedData" JSONB,
49
+ "references" TEXT[] DEFAULT ARRAY[]::TEXT[],
50
+ "chunkCount" INTEGER,
51
+ "qdrantDocId" TEXT,
52
+ "indexingCost" DOUBLE PRECISION,
53
+ "indexedAt" TIMESTAMP(3),
54
+ "indexError" TEXT,
55
+ "tags" TEXT[] DEFAULT ARRAY[]::TEXT[],
56
+ "parentFileId" TEXT,
57
+ "versionNumber" INTEGER NOT NULL DEFAULT 1,
58
+ "answerId" TEXT,
59
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
60
+ "updatedAt" TIMESTAMP(3) NOT NULL,
61
+ "deletedAt" TIMESTAMP(3),
62
+
63
+ CONSTRAINT "UserFile_pkey" PRIMARY KEY ("id")
64
+ );
65
+
66
+ -- CreateTable
67
+ CREATE TABLE "FileIndexingJob" (
68
+ "id" TEXT NOT NULL,
69
+ "fileId" TEXT NOT NULL,
70
+ "userId" TEXT NOT NULL,
71
+ "status" "IndexingJobStatus" NOT NULL DEFAULT 'QUEUED',
72
+ "attempts" INTEGER NOT NULL DEFAULT 0,
73
+ "maxAttempts" INTEGER NOT NULL DEFAULT 3,
74
+ "errorMsg" TEXT,
75
+ "startedAt" TIMESTAMP(3),
76
+ "finishedAt" TIMESTAMP(3),
77
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
78
+
79
+ CONSTRAINT "FileIndexingJob_pkey" PRIMARY KEY ("id")
80
+ );
81
+
82
+ -- CreateTable
83
+ CREATE TABLE "FileDeadline" (
84
+ "id" TEXT NOT NULL,
85
+ "fileId" TEXT NOT NULL,
86
+ "userId" TEXT NOT NULL,
87
+ "label" TEXT NOT NULL,
88
+ "deadlineAt" TIMESTAMP(3) NOT NULL,
89
+ "notifyAt" TIMESTAMP(3),
90
+ "isNotified" BOOLEAN NOT NULL DEFAULT false,
91
+ "isDismissed" BOOLEAN NOT NULL DEFAULT false,
92
+ "sourceSection" TEXT,
93
+ "sourcePage" INTEGER,
94
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
95
+
96
+ CONSTRAINT "FileDeadline_pkey" PRIMARY KEY ("id")
97
+ );
98
+
99
+ -- CreateTable
100
+ CREATE TABLE "FileReviewTable" (
101
+ "id" TEXT NOT NULL,
102
+ "userId" TEXT NOT NULL,
103
+ "folderId" TEXT,
104
+ "name" TEXT NOT NULL,
105
+ "columns" JSONB NOT NULL,
106
+ "fileIds" TEXT[] DEFAULT ARRAY[]::TEXT[],
107
+ "results" JSONB,
108
+ "status" TEXT NOT NULL DEFAULT 'draft',
109
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
110
+ "updatedAt" TIMESTAMP(3) NOT NULL,
111
+
112
+ CONSTRAINT "FileReviewTable_pkey" PRIMARY KEY ("id")
113
+ );
114
+
115
+ -- CreateIndex
116
+ CREATE UNIQUE INDEX "UserFile_storageKey_key" ON "UserFile"("storageKey");
117
+
118
+ -- CreateIndex
119
+ CREATE UNIQUE INDEX "UserFile_qdrantDocId_key" ON "UserFile"("qdrantDocId");
120
+
121
+ -- CreateIndex
122
+ CREATE INDEX "UserFile_userId_idx" ON "UserFile"("userId");
123
+
124
+ -- CreateIndex
125
+ CREATE INDEX "UserFile_status_idx" ON "UserFile"("status");
126
+
127
+ -- CreateIndex
128
+ CREATE INDEX "UserFile_userId_status_idx" ON "UserFile"("userId", "status");
129
+
130
+ -- CreateIndex
131
+ CREATE INDEX "UserFile_userId_deletedAt_idx" ON "UserFile"("userId", "deletedAt");
132
+
133
+ -- CreateIndex
134
+ CREATE INDEX "UserFile_qdrantDocId_idx" ON "UserFile"("qdrantDocId");
135
+
136
+ -- CreateIndex
137
+ CREATE INDEX "UserFile_answerId_idx" ON "UserFile"("answerId");
138
+
139
+ -- CreateIndex
140
+ CREATE INDEX "UserFile_checksumSha256_idx" ON "UserFile"("checksumSha256");
141
+
142
+ -- CreateIndex
143
+ CREATE INDEX "FileIndexingJob_fileId_idx" ON "FileIndexingJob"("fileId");
144
+
145
+ -- CreateIndex
146
+ CREATE INDEX "FileIndexingJob_userId_idx" ON "FileIndexingJob"("userId");
147
+
148
+ -- CreateIndex
149
+ CREATE INDEX "FileIndexingJob_status_idx" ON "FileIndexingJob"("status");
150
+
151
+ -- CreateIndex
152
+ CREATE INDEX "FileIndexingJob_createdAt_idx" ON "FileIndexingJob"("createdAt");
153
+
154
+ -- CreateIndex
155
+ CREATE INDEX "FileDeadline_fileId_idx" ON "FileDeadline"("fileId");
156
+
157
+ -- CreateIndex
158
+ CREATE INDEX "FileDeadline_userId_idx" ON "FileDeadline"("userId");
159
+
160
+ -- CreateIndex
161
+ CREATE INDEX "FileDeadline_deadlineAt_idx" ON "FileDeadline"("deadlineAt");
162
+
163
+ -- CreateIndex
164
+ CREATE INDEX "FileDeadline_notifyAt_isNotified_idx" ON "FileDeadline"("notifyAt", "isNotified");
165
+
166
+ -- CreateIndex
167
+ CREATE INDEX "FileDeadline_userId_isDismissed_idx" ON "FileDeadline"("userId", "isDismissed");
168
+
169
+ -- CreateIndex
170
+ CREATE INDEX "FileReviewTable_userId_idx" ON "FileReviewTable"("userId");
171
+
172
+ -- CreateIndex
173
+ CREATE INDEX "FileReviewTable_folderId_idx" ON "FileReviewTable"("folderId");
174
+
175
+ -- CreateIndex
176
+ CREATE INDEX "FileReviewTable_status_idx" ON "FileReviewTable"("status");
177
+
178
+ -- AddForeignKey
179
+ ALTER TABLE "UserFile" ADD CONSTRAINT "UserFile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
180
+
181
+ -- AddForeignKey
182
+ ALTER TABLE "UserFile" ADD CONSTRAINT "UserFile_answerId_fkey" FOREIGN KEY ("answerId") REFERENCES "Answer"("id") ON DELETE SET NULL ON UPDATE CASCADE;
183
+
184
+ -- AddForeignKey
185
+ ALTER TABLE "UserFile" ADD CONSTRAINT "UserFile_parentFileId_fkey" FOREIGN KEY ("parentFileId") REFERENCES "UserFile"("id") ON DELETE SET NULL ON UPDATE CASCADE;
186
+
187
+ -- AddForeignKey
188
+ ALTER TABLE "FileIndexingJob" ADD CONSTRAINT "FileIndexingJob_fileId_fkey" FOREIGN KEY ("fileId") REFERENCES "UserFile"("id") ON DELETE CASCADE ON UPDATE CASCADE;
189
+
190
+ -- AddForeignKey
191
+ ALTER TABLE "FileDeadline" ADD CONSTRAINT "FileDeadline_fileId_fkey" FOREIGN KEY ("fileId") REFERENCES "UserFile"("id") ON DELETE CASCADE ON UPDATE CASCADE;
192
+
193
+ -- AddForeignKey
194
+ ALTER TABLE "FileReviewTable" ADD CONSTRAINT "FileReviewTable_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;