From 72e26ce33fcbb8149c1bcbc520d9962640b6c6e4 Mon Sep 17 00:00:00 2001
From: zakrok <31936449+zakrok@users.noreply.github.com>
Date: Thu, 9 Jul 2026 01:06:08 +0200
Subject: [PATCH 1/4] chore: add .idea folder and commit
No reason to not publish the .idea folder since the recommended way of working with CAIT is via WebStorm. Additionally, we save run configurations in it that we can use.
---
.gitignore | 1 -
.idea/.gitignore | 10 ++++++
.idea/CAIT.iml | 11 +++++++
.idea/codeStyles/Project.xml | 48 ++++++++++++++++++++++++++++
.idea/codeStyles/codeStyleConfig.xml | 5 +++
.idea/modules.xml | 8 +++++
.idea/prettier.xml | 6 ++++
.idea/vcs.xml | 6 ++++
8 files changed, 94 insertions(+), 1 deletion(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/CAIT.iml
create mode 100644 .idea/codeStyles/Project.xml
create mode 100644 .idea/codeStyles/codeStyleConfig.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/prettier.xml
create mode 100644 .idea/vcs.xml
diff --git a/.gitignore b/.gitignore
index 9ff31651..40551f15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,6 @@ node_modules
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
-/.idea
reports
.snaplet
static/uploadedFiles
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..30cf57ed
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/CAIT.iml b/.idea/CAIT.iml
new file mode 100644
index 00000000..833fb3ca
--- /dev/null
+++ b/.idea/CAIT.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..be810ecc
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..6c001fea
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/prettier.xml b/.idea/prettier.xml
new file mode 100644
index 00000000..b0c1c68f
--- /dev/null
+++ b/.idea/prettier.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
From 160c55149b09ef7bb7a7cae31e73df7c9c9e671b Mon Sep 17 00:00:00 2001
From: zakrok <31936449+zakrok@users.noreply.github.com>
Date: Thu, 9 Jul 2026 01:31:55 +0200
Subject: [PATCH 2/4] chore: mass delete random comments
Signed-off-by: zakrok <31936449+zakrok@users.noreply.github.com>
---
README.md | 2 -
src/lib/components/PublishReview.svelte | 17 ---
src/lib/database/file.ts | 110 +++++++-----------
src/lib/database/index.ts | 95 ++++++---------
src/lib/database/prisma.ts | 12 --
.../use-in-course/[publicationId]/+server.ts | 9 +-
src/routes/courses/[course]/+page.svelte | 50 +-------
svelte.config.js | 5 -
8 files changed, 80 insertions(+), 220 deletions(-)
diff --git a/README.md b/README.md
index 101c384e..89d40885 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,6 @@ This will spawn a new shell with all the dependencies needed to run CAIT (includ
### Using an imperative package manager (or running in windows) (not recommended)
-[//]: # (TODO)
-
### Running the application
First, make sure all the dependencies are installed and the correct prisma client is generated by running the following
diff --git a/src/lib/components/PublishReview.svelte b/src/lib/components/PublishReview.svelte
index 260bb0be..21180c14 100644
--- a/src/lib/components/PublishReview.svelte
+++ b/src/lib/components/PublishReview.svelte
@@ -13,23 +13,6 @@
export let maintainers: UserWithProfilePic[];
export let publisher: UserWithProfilePic;
- // todo: ask bobby and remove if unnecessary.
- // let p = $page.data.session?.user as User & {profilePic: string};
- // let publisher = {
- // id: p.id,
- // firstName: p.firstName,
- // lastName: p.lastName,
- // username: p.username,
- // aboutMe: p.aboutMe,
- // email: p.email,
- // emailVerified: p.emailVerified,
- // reputation: p.reputation,
- // password: p.password,
- // isAdmin: p.isAdmin,
- // createdAt: p.createdAt,
- // updatedAt: p.updatedAt
- // }
-
diff --git a/src/lib/database/file.ts b/src/lib/database/file.ts
index 3e268c27..b93c3706 100644
--- a/src/lib/database/file.ts
+++ b/src/lib/database/file.ts
@@ -2,7 +2,7 @@ import {
type FetchedFileItem,
type FileDiffActions,
fileSystem,
- prisma
+ prisma,
} from '$lib/database';
import { Prisma } from '@prisma/client/extension';
import type { File as PrismaFile, FileChunk } from '@prisma/client';
@@ -11,53 +11,31 @@ import type { FileChunks } from '$lib/PiscinaUtils/runner';
import { addFileURL } from '$lib/database/fileURL';
import { SupabaseFileSystem } from '$lib/FileSystemPort/SupabaseFileSystem';
-
-// // TODO: This seems to be useless, could remove if nothing breaks
-// export async function bufToBase64(files: FetchedFileArray) {
-// // If JSON stringify cannot handle raw Buffer, use this:
-// return files.map((file) => ({
-// ...file,
-// data: file.data.toString(),
-// }));
-// }
-// export type ProfilePic = {
-// fileId: string;
-// data: string | null;
-// }
-
-export async function profilePicFetcher(profilePic: PrismaFile | null): Promise {
+export async function profilePicFetcher(
+ profilePic: PrismaFile | null,
+): Promise {
let filePath;
// if coverPic is not defined (falsy), fetch default photo based on encapsulating type
if (!profilePic) {
-
// TODO: Let frontend handle this, just return null and use static content as usual
filePath = path.join('static', 'defaultProfilePic', 'profile.jpg');
-
- //const currentFileData = fs.readFileSync(filePath);
- //const currentFileData = fileSystem.readFile(filePath);
-
return {
fileId: filePath,
//data: currentFileData.toString('base64'),
- data: null
+ data: null,
};
} else {
// since photo is defined, read the file based on the path (just like a File)
filePath = profilePic.path;
-
- // const currentFileData = await fileSystem.readFile(filePath);
- // return {
- // fileId: filePath,
- // data: currentFileData.toString('base64'),
- // };
let currentFileData;
if (fileSystem instanceof SupabaseFileSystem) {
currentFileData = await fileSystem.readFileURL(filePath);
- }
- else {
- currentFileData = (await fileSystem.readFile(filePath)).toString('base64'); //skipcheck
+ } else {
+ currentFileData = (await fileSystem.readFile(filePath)).toString(
+ 'base64',
+ ); //skipcheck
}
return {
@@ -74,13 +52,11 @@ export async function profilePicFetcher(profilePic: PrismaFile | null): Promise<
*/
export async function coverPicFetcher(
encapsulatingType: string | null = null,
- coverPic: PrismaFile | null = null
-) : Promise {
+ coverPic: PrismaFile | null = null,
+): Promise {
let filePath;
- // if coverPic is not defined (falsy), fetch default photo based on encapsulating type
if (!coverPic) {
-
// TODO: Figure out if this picture is good enough for default
// TODO: Let frontend handle this, just return null and use static content as usual
@@ -91,30 +67,22 @@ export async function coverPicFetcher(
'assignment' + '.jpg',
);
- //const currentFileData = fs.readFileSync(filePath);
- //const currentFileData = fileSystem.readFile(filePath);
-
return {
fileId: filePath,
- //data: currentFileData.toString('base64'),
- data: null
+ data: null,
};
} else {
// since photo is defined, read the file based on the path (just like a File)
filePath = coverPic.path;
- // const currentFileData = await fileSystem.readFile(filePath);
- // return {
- // fileId: filePath,
- // data: currentFileData.toString('base64'),
- // };
let currentFileData;
if (fileSystem instanceof SupabaseFileSystem) {
currentFileData = await fileSystem.readFileURL(filePath);
- }
- else {
+ } else {
// TODO: frontend expects urls currently, add base64 checks jic
- currentFileData = (await fileSystem.readFile(filePath)).toString('base64'); //skipcheck
+ currentFileData = (await fileSystem.readFile(filePath)).toString(
+ 'base64',
+ ); //skipcheck
}
return {
@@ -140,7 +108,7 @@ export async function addCoverPic(
path: path,
title: title,
type,
- }
+ };
if (isCourse) {
query.courseId = id;
} else {
@@ -224,9 +192,9 @@ export async function updateCoverPic(
prismaContext: Prisma.TransactionClient = prisma,
) {
// handle both courses and publications
- let query : any = {publicationId : id}
+ let query: any = { publicationId: id };
if (isCourse) {
- query = {courseId : id}
+ query = { courseId: id };
}
// check if the publication already has a coverPic
const coverFile = await prismaContext.file.findUnique({
@@ -275,10 +243,9 @@ export async function addFile(
) {
try {
let path: string;
- if (info instanceof Buffer){
+ if (info instanceof Buffer) {
path = await fileSystem.saveFile(info, title, ownerId, type);
- }
- else path = info;
+ } else path = info;
try {
return prismaContext.file.create({
@@ -363,14 +330,21 @@ export async function updateFiles(
) {
// add files
for (const file of fileInfo.add) {
- if (file.type == "URL" ) {
+ if (file.type == 'URL') {
await addFileURL(file.title, file.info, materialId, prismaContext);
continue;
}
// const buffer: Buffer = Buffer.from(file.info, 'base64');
const path: string = file.info;
- await addFile(file.title, file.type, userId, path, materialId, prismaContext);
+ await addFile(
+ file.title,
+ file.type,
+ userId,
+ path,
+ materialId,
+ prismaContext,
+ );
}
// delete files
@@ -393,18 +367,18 @@ export async function updateFiles(
*/
export async function handleFileTokens(
filesToUpdate: { filePath: string; tokens: string; chunks: FileChunks }[],
- prismaContext: Prisma.TransactionClient = prisma
+ prismaContext: Prisma.TransactionClient = prisma,
) {
for (const dataCurrent of filesToUpdate) {
// Update file text
await prisma.file.update({
where: { path: dataCurrent.filePath },
- data: { text: dataCurrent.tokens }
+ data: { text: dataCurrent.tokens },
});
// Delete previous documents
await prisma.fileChunk.deleteMany({
- where: { filePath: dataCurrent.filePath }
+ where: { filePath: dataCurrent.filePath },
});
// Insert new documents using raw SQL for the vector type
@@ -425,7 +399,9 @@ export async function handleFileTokens(
}
// Select embeddings which are at least 40% similar to the user query, return at most 5
-export async function performCosineSimilarityWithHNSWIndex(embeddedUserQuery: number[]): Promise<(FileChunk & {similarity: number})[]>{
+export async function performCosineSimilarityWithHNSWIndex(
+ embeddedUserQuery: number[],
+): Promise<(FileChunk & { similarity: number })[]> {
return prisma.$queryRaw`
SELECT id, content, metadata, "filePath",
(1 - (embedding <=> ${embeddedUserQuery}::vector)) AS similarity
@@ -454,7 +430,9 @@ export async function getFileChunks() {
content: doc.content,
metadata: doc.metadata,
filePath: doc.filePath,
- embedding: doc.embedding_text ? parseVectorString(doc.embedding_text) : null
+ embedding: doc.embedding_text
+ ? parseVectorString(doc.embedding_text)
+ : null,
}));
}
@@ -467,19 +445,15 @@ function parseVectorString(vectorStr: string): number[] {
.replace('[', '')
.replace(']', '')
.split(',')
- .map(num => parseFloat(num.trim()));
+ .map((num) => parseFloat(num.trim()));
} catch (e) {
console.error('Error parsing vector string:', e);
return [];
}
}
-
-
-export async function getFilesForMaterial(
- materialId: number
-) {
+export async function getFilesForMaterial(materialId: number) {
return prisma.file.findMany({
where: { materialId: materialId },
- })
+ });
}
diff --git a/src/lib/database/index.ts b/src/lib/database/index.ts
index ba9b4cbe..adf53fac 100644
--- a/src/lib/database/index.ts
+++ b/src/lib/database/index.ts
@@ -4,103 +4,87 @@ import { SERVICE_ROLE_KEY } from '$env/static/private';
import { PUBLIC_SUPABASE_URL } from '$env/static/public';
import {
- getMaterialByPublicationId,
- getAllMaterials,
- updateMaterialByPublicationId,
- deleteMaterialByPublicationId,
createMaterialPublication,
+ deleteMaterialByPublicationId,
+ getAllMaterials,
+ getMaterialByPublicationId,
+ updateMaterialByPublicationId
} from './material';
import {
- getCircuitByPublicationId,
- getAllCircuits,
- updateCircuitByPublicationId,
- deleteCircuitByPublicationId,
createCircuitPublication,
+ deleteCircuitByPublicationId,
+ getAllCircuits,
+ getCircuitByPublicationId,
+ updateCircuitByPublicationId
} from './circuit';
import {
- updatePublicationConnectTags,
- updatePublicationConnectMaintainers,
connectMaintainers,
connectTags,
+ getPublisherId,
handleConnections,
updateAllTimeSaved,
- getPublisherId
+ updatePublicationConnectMaintainers,
+ updatePublicationConnectTags
} from './publication';
-import {
- addTag,
- addTags,
- getAllTags,
- getTagByContent,
- deleteTagByContent,
-} from '$lib/database/tag';
+import { addTag, addTags, deleteTagByContent, getAllTags, getTagByContent } from '$lib/database/tag';
-import {
- handleEdges,
- fetchExtensions,
- addNode,
- editNode,
- deleteNode,
-} from './node';
+import { addNode, deleteNode, editNode, fetchExtensions, handleEdges } from './node';
-import { savePublication, getSavedPublications } from '$lib/database/save';
+import { getSavedPublications, savePublication } from '$lib/database/save';
+import type { userEditData } from '$lib/database/user';
import {
- getUserById,
createUser,
deleteUser,
editUser,
- likePublication,
+ getLikedComments,
getLikedPublications,
- likesReplyUpdate,
- likesCommentUpdate,
getLikedReplies,
- getLikedComments,
- updateReputation,
+ getUserById,
+ likePublication,
+ likesCommentUpdate,
+ likesReplyUpdate,
+ updateReputation
} from '$lib/database/user';
+import type { createCommentData, editCommentData } from '$lib/database/comment';
import {
createComment,
deleteComment,
getComment,
- updateComment,
getCommentsByPublicationId,
+ updateComment
} from '$lib/database/comment';
-import {
- getReply,
- deleteReply,
- updateReply,
- createReply,
- getRepliesByCommentId,
-} from '$lib/database/reply';
+import type { createReplyData, editReplyData } from '$lib/database/reply';
+import { createReply, deleteReply, getRepliesByCommentId, getReply, updateReply } from '$lib/database/reply';
import {
addPublicationToUsedInCourse,
coursesUsingPublication,
- publicationsAUserUses,
+ publicationsAUserUses
} from '$lib/database/usedInCourse';
-import type { userEditData } from '$lib/database/user';
-import type { editReplyData, createReplyData } from '$lib/database/reply';
-import type { createCommentData, editCommentData } from '$lib/database/comment';
-
import {
+ addCoverPic,
addFile,
+ coverPicFetcher,
deleteFile,
editFile,
- addCoverPic,
- coverPicFetcher,
updateCoverPic,
- updateFiles,
+ updateFiles
} from '$lib/database/file';
-import {handleSimilarity} from "$lib/database/similarity";
+import { handleSimilarity } from '$lib/database/similarity';
import { prisma } from './prisma';
import { Difficulty, MaterialType } from '@prisma/client';
+import { SupabaseFileSystem } from '$lib/FileSystemPort/SupabaseFileSystem';
+import { LocalFileSystem } from '$lib/FileSystemPort/LocalFileSystem';
+import type { ChangeLogPayload } from '$lib/database/publicationHistory';
/**
* MaterialForm is the type of the form data that is sent to the server when creating a new material.
@@ -170,7 +154,6 @@ type CircuitForm = {
*
* @note These changes are evaluated on the server in `+page.server.ts` and then sent like this
* to the server in the POST request to `/api/materials`
- * @todo may be much better to use an object with keys `add`, `delete`, and `edit` instead of arrays
*/
type FileDiffActions = {
add: { title: string; type: string; info: string }[];
@@ -178,14 +161,6 @@ type FileDiffActions = {
edit: { path: string; title: string; info: string }[];
};
-/**
- * Fetched file item with the id and the data in the form of a base64 string.
- */
-// type FetchedFileItem = {
-// fileId: string;
-// data: string | null;
-// };
-
type FetchedFileItem = {
fileId: string;
name?: string;
@@ -226,10 +201,6 @@ type NodeDiffActions = {
/// SELECT FILESYSTEM TYPE BASED ON .ENV VARIABLE
////////////////////////////////////////////////////////
-import { SupabaseFileSystem } from '$lib/FileSystemPort/SupabaseFileSystem';
-import { LocalFileSystem } from '$lib/FileSystemPort/LocalFileSystem';
-import type { ChangeLogPayload } from '$lib/database/publicationHistory';
-
export const basePath = "uploadedFiles"
let fileSystem: SupabaseFileSystem | LocalFileSystem;
diff --git a/src/lib/database/prisma.ts b/src/lib/database/prisma.ts
index 2ae162b2..bd238275 100644
--- a/src/lib/database/prisma.ts
+++ b/src/lib/database/prisma.ts
@@ -1,15 +1,3 @@
import { PrismaClient } from './prismaClient';
-//TODO: this causes 409 conflicts with the remote dashboard. Could kill the entire process if not handled
-//import { withOptimize } from "@prisma/extension-optimize";
-
-// import { createRequire } from 'module';
-//
-// const require = createRequire(import.meta.url);
-// const { withOptimize } = require('@prisma/extension-optimize');
-//
-// export const prisma: PrismaClient = new PrismaClient().$extends(
-// withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY })
-// );
-
export const prisma: PrismaClient = new PrismaClient();
diff --git a/src/routes/api/user/[id]/use-in-course/[publicationId]/+server.ts b/src/routes/api/user/[id]/use-in-course/[publicationId]/+server.ts
index 912326d0..c32ea2d9 100644
--- a/src/routes/api/user/[id]/use-in-course/[publicationId]/+server.ts
+++ b/src/routes/api/user/[id]/use-in-course/[publicationId]/+server.ts
@@ -1,9 +1,4 @@
-import {
- addPublicationToUsedInCourse,
- getPublicationById,
- getUserById,
- updateReputation,
-} from '$lib/database';
+import { addPublicationToUsedInCourse, getUserById, updateReputation } from '$lib/database';
import { verifyAuth } from '$lib/database/auth';
import { getPublicationByIdLight } from '$lib/database/db.ts';
@@ -36,7 +31,7 @@ export async function POST({ params, request, locals }) {
const body = await request.json();
try {
await addPublicationToUsedInCourse(
- id, //todo fix
+ id,
parseInt(publicationId),
body.courses,
);
diff --git a/src/routes/courses/[course]/+page.svelte b/src/routes/courses/[course]/+page.svelte
index c2b910f2..0bdb92e5 100644
--- a/src/routes/courses/[course]/+page.svelte
+++ b/src/routes/courses/[course]/+page.svelte
@@ -1,17 +1,10 @@