From a857c3da072fb2f7dd38d686d3ccf01e8767f6f1 Mon Sep 17 00:00:00 2001 From: Cameron Redmore Date: Fri, 25 Apr 2025 08:48:14 +0100 Subject: [PATCH] Adds in initial migration, recommends ESLint VS Code extension and sets up defaults to format with ESLint on save and use ESLint as the general formatter --- .vscode/extensions.json | 3 +- .vscode/settings.json | 15 +- package.json | 2 +- .../migration.sql | 156 ---------------- .../20250425072554_init/migration.sql | 166 ++++++++++++++++++ prisma/schema.prisma | 88 ++++------ src-ssr/middlewares/render.js | 2 - src/router/index.js | 2 +- src/stores/auth.js | 2 +- 9 files changed, 217 insertions(+), 219 deletions(-) delete mode 100644 prisma/migrations/20250424205631_add_chat_models/migration.sql create mode 100644 prisma/migrations/20250425072554_init/migration.sql diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 9b3c8c8..9653806 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,7 @@ { "recommendations": [ - "prisma.prisma" + "prisma.prisma", + "dbaeumer.vscode-eslint" ], "unwantedRecommendations": [ "octref.vetur", diff --git a/.vscode/settings.json b/.vscode/settings.json index fdb070a..8dec94a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,17 @@ { "editor.bracketPairColorization.enabled": true, - "editor.guides.bracketPairs": true + "editor.guides.bracketPairs": true, + "eslint.validate": [ + "javascript" + ], + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "eslint.format.enable": true, + "eslint.codeActionsOnSave.rules": null, + "[jsonc]": { + "editor.defaultFormatter": "vscode.json-language-features" + }, + "[vue]": { + "editor.defaultFormatter": "dbaeumer.vscode-eslint" + }, + "editor.formatOnSave": true } \ No newline at end of file diff --git a/package.json b/package.json index 8482ef0..1233ffe 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "private": true, "scripts": { "test": "echo \"No test specified\" && exit 0", - "dev": "prisma db push && quasar dev -m ssr", + "dev": "pnpm prisma migrate dev && quasar dev -m ssr", "build": "quasar build -m ssr", "postinstall": "quasar prepare" }, diff --git a/prisma/migrations/20250424205631_add_chat_models/migration.sql b/prisma/migrations/20250424205631_add_chat_models/migration.sql deleted file mode 100644 index 8841cfe..0000000 --- a/prisma/migrations/20250424205631_add_chat_models/migration.sql +++ /dev/null @@ -1,156 +0,0 @@ --- CreateEnum -CREATE TYPE "FieldType" AS ENUM ('text', 'number', 'date', 'textarea', 'boolean'); - --- CreateTable -CREATE TABLE "forms" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "description" TEXT, - "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "forms_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "categories" ( - "id" SERIAL NOT NULL, - "form_id" INTEGER NOT NULL, - "name" TEXT NOT NULL, - "sort_order" INTEGER NOT NULL DEFAULT 0, - - CONSTRAINT "categories_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "fields" ( - "id" SERIAL NOT NULL, - "category_id" INTEGER NOT NULL, - "label" TEXT NOT NULL, - "type" "FieldType" NOT NULL, - "description" TEXT, - "sort_order" INTEGER NOT NULL, - - CONSTRAINT "fields_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "responses" ( - "id" SERIAL NOT NULL, - "form_id" INTEGER NOT NULL, - "submitted_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "responses_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "response_values" ( - "id" SERIAL NOT NULL, - "response_id" INTEGER NOT NULL, - "field_id" INTEGER NOT NULL, - "value" TEXT, - - CONSTRAINT "response_values_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "mantis_summaries" ( - "id" SERIAL NOT NULL, - "summary_date" DATE NOT NULL, - "summary_text" TEXT NOT NULL, - "generated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "mantis_summaries_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "EmailSummary" ( - "id" SERIAL NOT NULL, - "summaryDate" DATE NOT NULL, - "summaryText" TEXT NOT NULL, - "generatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "EmailSummary_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "settings" ( - "key" TEXT NOT NULL, - "value" TEXT NOT NULL, - - CONSTRAINT "settings_pkey" PRIMARY KEY ("key") -); - --- CreateTable -CREATE TABLE "users" ( - "id" TEXT NOT NULL, - "username" TEXT NOT NULL, - - CONSTRAINT "users_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "authenticators" ( - "id" TEXT NOT NULL, - "credential_id" TEXT NOT NULL, - "credential_public_key" BYTEA NOT NULL, - "counter" BIGINT NOT NULL, - "credential_device_type" TEXT NOT NULL, - "credential_backed_up" BOOLEAN NOT NULL, - "transports" TEXT, - "user_id" TEXT NOT NULL, - - CONSTRAINT "authenticators_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "chat_threads" ( - "id" TEXT NOT NULL, - "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updated_at" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "chat_threads_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "chat_messages" ( - "id" TEXT NOT NULL, - "thread_id" TEXT NOT NULL, - "sender" TEXT NOT NULL, - "content" TEXT NOT NULL, - "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "chat_messages_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "mantis_summaries_summary_date_key" ON "mantis_summaries"("summary_date"); - --- CreateIndex -CREATE UNIQUE INDEX "EmailSummary_summaryDate_key" ON "EmailSummary"("summaryDate"); - --- CreateIndex -CREATE UNIQUE INDEX "users_username_key" ON "users"("username"); - --- CreateIndex -CREATE UNIQUE INDEX "authenticators_credential_id_key" ON "authenticators"("credential_id"); - --- AddForeignKey -ALTER TABLE "categories" ADD CONSTRAINT "categories_form_id_fkey" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "fields" ADD CONSTRAINT "fields_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "categories"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "responses" ADD CONSTRAINT "responses_form_id_fkey" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "response_values" ADD CONSTRAINT "response_values_response_id_fkey" FOREIGN KEY ("response_id") REFERENCES "responses"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "response_values" ADD CONSTRAINT "response_values_field_id_fkey" FOREIGN KEY ("field_id") REFERENCES "fields"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "authenticators" ADD CONSTRAINT "authenticators_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "chat_messages" ADD CONSTRAINT "chat_messages_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "chat_threads"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20250425072554_init/migration.sql b/prisma/migrations/20250425072554_init/migration.sql new file mode 100644 index 0000000..65ea4fc --- /dev/null +++ b/prisma/migrations/20250425072554_init/migration.sql @@ -0,0 +1,166 @@ +CREATE EXTENSION IF NOT EXISTS "citext"; + +-- CreateEnum +CREATE TYPE "FieldType" AS ENUM ('text', 'number', 'date', 'textarea', 'boolean'); + +-- CreateTable +CREATE TABLE "Form" ( + "id" SERIAL NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Form_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Category" ( + "id" SERIAL NOT NULL, + "form_id" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "sort_order" INTEGER NOT NULL DEFAULT 0, + + CONSTRAINT "Category_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Field" ( + "id" SERIAL NOT NULL, + "category_id" INTEGER NOT NULL, + "label" TEXT NOT NULL, + "type" "FieldType" NOT NULL, + "description" TEXT, + "sort_order" INTEGER NOT NULL, + + CONSTRAINT "Field_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Response" ( + "id" SERIAL NOT NULL, + "form_id" INTEGER NOT NULL, + "submitted_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "Response_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ResponseValue" ( + "id" SERIAL NOT NULL, + "response_id" INTEGER NOT NULL, + "field_id" INTEGER NOT NULL, + "value" TEXT, + + CONSTRAINT "ResponseValue_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MantisSummary" ( + "id" SERIAL NOT NULL, + "summary_date" DATE NOT NULL, + "summary_text" TEXT NOT NULL, + "generated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "MantisSummary_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Setting" ( + "key" TEXT NOT NULL, + "value" TEXT NOT NULL, + + CONSTRAINT "Setting_pkey" PRIMARY KEY ("key") +); + +-- CreateTable +CREATE TABLE "User" ( + "id" TEXT NOT NULL, + "username" CITEXT NOT NULL, + "email" CITEXT, + "fullName" TEXT, + + CONSTRAINT "User_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "UserPreference" ( + "id" SERIAL NOT NULL, + "user_id" TEXT NOT NULL, + "key" TEXT NOT NULL, + "value" TEXT NOT NULL, + + CONSTRAINT "UserPreference_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "Authenticator" ( + "id" TEXT NOT NULL, + "credential_id" TEXT NOT NULL, + "credential_public_key" BYTEA NOT NULL, + "counter" BIGINT NOT NULL, + "credential_device_type" TEXT NOT NULL, + "credential_backed_up" BOOLEAN NOT NULL, + "transports" TEXT, + "user_id" TEXT NOT NULL, + + CONSTRAINT "Authenticator_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ChatThread" ( + "id" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "ChatThread_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "ChatMessage" ( + "id" TEXT NOT NULL, + "thread_id" TEXT NOT NULL, + "sender" TEXT NOT NULL, + "content" TEXT NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "ChatMessage_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "MantisSummary_summary_date_key" ON "MantisSummary"("summary_date"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_username_key" ON "User"("username"); + +-- CreateIndex +CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "UserPreference_user_id_key_key" ON "UserPreference"("user_id", "key"); + +-- CreateIndex +CREATE UNIQUE INDEX "Authenticator_credential_id_key" ON "Authenticator"("credential_id"); + +-- AddForeignKey +ALTER TABLE "Category" ADD CONSTRAINT "Category_form_id_fkey" FOREIGN KEY ("form_id") REFERENCES "Form"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Field" ADD CONSTRAINT "Field_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "Category"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Response" ADD CONSTRAINT "Response_form_id_fkey" FOREIGN KEY ("form_id") REFERENCES "Form"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ResponseValue" ADD CONSTRAINT "ResponseValue_response_id_fkey" FOREIGN KEY ("response_id") REFERENCES "Response"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ResponseValue" ADD CONSTRAINT "ResponseValue_field_id_fkey" FOREIGN KEY ("field_id") REFERENCES "Field"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserPreference" ADD CONSTRAINT "UserPreference_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Authenticator" ADD CONSTRAINT "Authenticator_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ChatMessage" ADD CONSTRAINT "ChatMessage_thread_id_fkey" FOREIGN KEY ("thread_id") REFERENCES "ChatThread"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5dc1de4..ed23db9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,9 +1,3 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - -// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions? -// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init - generator client { provider = "prisma-client-js" } @@ -20,8 +14,6 @@ model Form { createdAt DateTime @default(now()) @map("created_at") categories Category[] responses Response[] - - @@map("forms") // Map to the 'forms' table } model Category { @@ -31,8 +23,6 @@ model Category { sortOrder Int @default(0) @map("sort_order") form Form @relation(fields: [formId], references: [id], onDelete: Cascade) fields Field[] - - @@map("categories") // Map to the 'categories' table } enum FieldType { @@ -44,26 +34,22 @@ enum FieldType { } model Field { - id Int @id @default(autoincrement()) - categoryId Int @map("category_id") - label String - type FieldType // Using Prisma Enum based on CHECK constraint - description String? - sortOrder Int @map("sort_order") - category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade) + id Int @id @default(autoincrement()) + categoryId Int @map("category_id") + label String + type FieldType + description String? + sortOrder Int @map("sort_order") + category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade) responseValues ResponseValue[] - - @@map("fields") // Map to the 'fields' table } model Response { - id Int @id @default(autoincrement()) - formId Int @map("form_id") - submittedAt DateTime @default(now()) @map("submitted_at") - form Form @relation(fields: [formId], references: [id], onDelete: Cascade) + id Int @id @default(autoincrement()) + formId Int @map("form_id") + submittedAt DateTime @default(now()) @map("submitted_at") + form Form @relation(fields: [formId], references: [id], onDelete: Cascade) responseValues ResponseValue[] - - @@map("responses") // Map to the 'responses' table } model ResponseValue { @@ -73,66 +59,58 @@ model ResponseValue { value String? response Response @relation(fields: [responseId], references: [id], onDelete: Cascade) field Field @relation(fields: [fieldId], references: [id], onDelete: Cascade) - - @@map("response_values") // Map to the 'response_values' table } model MantisSummary { - id Int @id @default(autoincrement()) - summaryDate DateTime @unique @db.Date @map("summary_date") - summaryText String @map("summary_text") - generatedAt DateTime @default(now()) @map("generated_at") - - @@map("mantis_summaries") // Map to the 'mantis_summaries' table -} - -model EmailSummary { id Int @id @default(autoincrement()) - summaryDate DateTime @unique @db.Date - summaryText String - generatedAt DateTime @default(now()) + summaryDate DateTime @unique @map("summary_date") @db.Date + summaryText String @map("summary_text") + generatedAt DateTime @default(now()) @map("generated_at") } model Setting { key String @id value String - - @@map("settings") // Map to the 'settings' table } -// Added for WebAuthn model User { - id String @id @default(uuid()) - username String @unique + id String @id @default(uuid()) + username String @unique @db.Citext() authenticators Authenticator[] + preferences UserPreference[] - @@map("users") + email String? @unique @db.Citext() + fullName String? +} + +model UserPreference { + id Int @id @default(autoincrement()) + userId String @map("user_id") + key String + value String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@unique([userId, key]) } model Authenticator { id String @id @default(uuid()) - credentialID String @unique @map("credential_id") // Base64URL encoded + credentialID String @unique @map("credential_id") credentialPublicKey Bytes @map("credential_public_key") counter BigInt - credentialDeviceType String @map("credential_device_type") // 'singleDevice' or 'multiDevice' + credentialDeviceType String @map("credential_device_type") credentialBackedUp Boolean @map("credential_backed_up") - transports String? // Comma-separated list like "internal,hybrid" + transports String? userId String @map("user_id") user User @relation(fields: [userId], references: [id], onDelete: Cascade) - - @@map("authenticators") } -// --- Add Chat Models --- - model ChatThread { id String @id @default(uuid()) createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") messages ChatMessage[] - - @@map("chat_threads") } model ChatMessage { @@ -142,6 +120,4 @@ model ChatMessage { content String createdAt DateTime @default(now()) @map("created_at") thread ChatThread @relation(fields: [threadId], references: [id], onDelete: Cascade) - - @@map("chat_messages") } diff --git a/src-ssr/middlewares/render.js b/src-ssr/middlewares/render.js index 3775646..dedd3b5 100644 --- a/src-ssr/middlewares/render.js +++ b/src-ssr/middlewares/render.js @@ -36,8 +36,6 @@ export default defineSsrMiddleware(({ app, resolve, render, serve }) => } else if (err.code === 404) { - // hmm, Vue Router could not find the requested route - // Should reach here only if no "catch-all" route // is defined in /src/routes res.status(404).send('404 | Page Not Found'); diff --git a/src/router/index.js b/src/router/index.js index 06bce7e..2b66f7b 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -43,7 +43,7 @@ export default defineRouter(function({ store /* { store, ssrContext } */ }) } catch (e) { - console.error('Initial auth check failed', e); + // console.error('Initial auth check failed', e); // Decide how to handle initial check failure (e.g., proceed, redirect to error page) } } diff --git a/src/stores/auth.js b/src/stores/auth.js index a69459e..d39de40 100644 --- a/src/stores/auth.js +++ b/src/stores/auth.js @@ -29,7 +29,7 @@ export const useAuthStore = defineStore('auth', { } catch (error) { - console.error('Failed to check authentication status:', error); + // console.error('Failed to check authentication status:', error); this.error = 'Could not verify login status.'; this.isAuthenticated = false; this.user = null;