From c9984ecf080694f7d649d630bb6e64fbabb3b72e Mon Sep 17 00:00:00 2001 From: krilklem Date: Wed, 10 Dec 2025 13:19:24 +0000 Subject: [PATCH 1/6] feat: Connect supabase to the backend --- backend/.env.example | 2 + backend/package-lock.json | 132 ++++++++ backend/package.json | 1 + .../src/controllers/supabase.controllers.ts | 7 + backend/src/index.ts | 5 + backend/src/routes/supabase.routes.ts | 8 + backend/src/services/supabase.service.ts | 14 + backend/src/types/supabase.ts | 289 ++++++++++++++++++ 8 files changed, 458 insertions(+) create mode 100644 backend/src/controllers/supabase.controllers.ts create mode 100644 backend/src/routes/supabase.routes.ts create mode 100644 backend/src/services/supabase.service.ts create mode 100644 backend/src/types/supabase.ts diff --git a/backend/.env.example b/backend/.env.example index 31a85bc..0630e8a 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -7,6 +7,8 @@ # Example: Database connection string # DB_CONNECTION_STRING="your_database_connection_string_here" +SUPABASE_URL=supabase-url-here +SUPABASE_KEY=supabase-key-here # Example: Port # PORT=3000 \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index c470800..93957f4 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@anthropic-ai/sdk": "^0.71.0", + "@supabase/supabase-js": "^2.87.1", "@types/multer": "^2.0.0", "dotenv": "^17.2.3", "express": "^5.1.0", @@ -549,6 +550,86 @@ "node": ">= 0.4" } }, + "node_modules/@supabase/auth-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.87.1.tgz", + "integrity": "sha512-6RDeOf5TVoaXFtEstN188ykp3pXLZaU9qoAWfx8dc50FFAAqt+kcFJ96V0IvSmcpb4mDAWcpTJ7BegmVDn/WIw==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.87.1.tgz", + "integrity": "sha512-rWmYo4gRD0XAjMhYDlz7IH67bp4TIQ1UE4VqwIQtl1gGPwtLDq6wcRnu7jLKlXx0Gtrknw/eoiHYG9//XrCTzQ==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.87.1.tgz", + "integrity": "sha512-Yzu5eL3iGmZW0C/8x+vEojAOou63FI9oVw8HI8YOq63+5yM8g8aGh7Y1E2vbXFb7+gHGsPqLnaC6dPhrYt7qBA==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.87.1.tgz", + "integrity": "sha512-XvLtEznxmYZXA7LYuy5zbSXpSYjDLJq2wQeRh3MzON2OR4U8Kq+RtPz2E2Wi8HEzvBfsc+nNu1TG8LQ9+3DRkA==", + "license": "MIT", + "dependencies": { + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.87.1.tgz", + "integrity": "sha512-0Uc8tNV4yzkNNmp1inpXru0RB4a7ECq05G2S6BDvSpMxTxJrDVJ4vVDwyhqB8ZZ+O9+8prHaQYoByQeuDnwpFQ==", + "license": "MIT", + "dependencies": { + "iceberg-js": "^0.8.1", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.87.1", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.87.1.tgz", + "integrity": "sha512-tVgqZqnHZVum584KuUKSQZgcy6ZkhVd6gG8QWg2QfIXH9HmXdamauxdVsLXwaNPJxEdOyfAfwIyi5XUsiVYWtg==", + "license": "MIT", + "dependencies": { + "@supabase/auth-js": "2.87.1", + "@supabase/functions-js": "2.87.1", + "@supabase/postgrest-js": "2.87.1", + "@supabase/realtime-js": "2.87.1", + "@supabase/storage-js": "2.87.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", @@ -650,6 +731,12 @@ "undici-types": "~7.16.0" } }, + "node_modules/@types/phoenix": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", + "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", + "license": "MIT" + }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -692,6 +779,15 @@ "@types/node": "*" } }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -1566,6 +1662,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/iceberg-js": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", + "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", @@ -2506,6 +2611,12 @@ } } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/tsx": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", @@ -2639,6 +2750,27 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/backend/package.json b/backend/package.json index 116719b..f54cece 100644 --- a/backend/package.json +++ b/backend/package.json @@ -16,6 +16,7 @@ "type": "module", "dependencies": { "@anthropic-ai/sdk": "^0.71.0", + "@supabase/supabase-js": "^2.87.1", "@types/multer": "^2.0.0", "dotenv": "^17.2.3", "express": "^5.1.0", diff --git a/backend/src/controllers/supabase.controllers.ts b/backend/src/controllers/supabase.controllers.ts new file mode 100644 index 0000000..7018d4c --- /dev/null +++ b/backend/src/controllers/supabase.controllers.ts @@ -0,0 +1,7 @@ +import type { Request, Response } from "express"; +import supabase from "../services/supabase.service.js"; + +export const save = async (req: Request, res: Response):Promise => { + const { data, error } = await supabase.from("test_relation").select("*"); + return res.status(200).json({ data }); +}; \ No newline at end of file diff --git a/backend/src/index.ts b/backend/src/index.ts index ce72b8f..b6a5e65 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -5,6 +5,7 @@ import path from "path"; import { fileURLToPath } from "url"; import aiRoutes from "./routes/ai.routes.js"; +import supabaseRoutes from "./routes/supabase.routes.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -22,6 +23,9 @@ app.use(express.urlencoded({ extended: true, limit: "10mb" })); // Parse URL-enc // Serve static files from the 'public' directory app.use(express.static(path.join(__dirname, "public"))); +// Supabase routes +app.use("/api/supabase", supabaseRoutes); + // Routes app.get("/", (_req: Request, res: Response) => { res.send("KeyCV Backend API - AI Toolkit Enabled"); @@ -31,6 +35,7 @@ app.get("/health", (_req: Request, res: Response) => { res.status(200).json({ status: "ok" }); }); + app.listen(Number(port), "0.0.0.0", () => { console.log(`Server is running at http://localhost:${port}`); console.log( diff --git a/backend/src/routes/supabase.routes.ts b/backend/src/routes/supabase.routes.ts new file mode 100644 index 0000000..c7be511 --- /dev/null +++ b/backend/src/routes/supabase.routes.ts @@ -0,0 +1,8 @@ +import { Router } from "express"; +import { save } from "../controllers/supabase.controllers.js"; + +const router = Router(); + +router.post("/save", save); + +export default router; \ No newline at end of file diff --git a/backend/src/services/supabase.service.ts b/backend/src/services/supabase.service.ts new file mode 100644 index 0000000..c90336d --- /dev/null +++ b/backend/src/services/supabase.service.ts @@ -0,0 +1,14 @@ +import 'dotenv/config'; +import { createClient } from '@supabase/supabase-js'; +import type { Database } from '../types/supabase.ts'; + +const SUPABASE_URL = process.env.SUPABASE_URL; +const SUPABASE_KEY = process.env.SUPABASE_KEY; + +if (!SUPABASE_URL || !SUPABASE_KEY) { + throw new Error('Missing DB_URL or DB_KEY in .env'); +} + +const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); + +export default supabase; \ No newline at end of file diff --git a/backend/src/types/supabase.ts b/backend/src/types/supabase.ts new file mode 100644 index 0000000..96f9b0d --- /dev/null +++ b/backend/src/types/supabase.ts @@ -0,0 +1,289 @@ +export type Json = + | string + | number + | boolean + | null + | { [key: string]: Json | undefined } + | Json[] + +export type Database = { + // Allows to automatically instantiate createClient with right options + // instead of createClient(URL, KEY) + __InternalSupabase: { + PostgrestVersion: "13.0.5" + } + graphql_public: { + Tables: { + [_ in never]: never + } + Views: { + [_ in never]: never + } + Functions: { + graphql: { + Args: { + extensions?: Json + operationName?: string + query?: string + variables?: Json + } + Returns: Json + } + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } + public: { + Tables: { + cvs: { + Row: { + created_at: string + cv: string | null + cv_id: number + name: string | null + user_id: string + } + Insert: { + created_at?: string + cv?: string | null + cv_id?: number + name?: string | null + user_id: string + } + Update: { + created_at?: string + cv?: string | null + cv_id?: number + name?: string | null + user_id?: string + } + Relationships: [ + { + foreignKeyName: "cvs_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["user_id"] + }, + ] + } + jobs: { + Row: { + created_at: string + cv_id: number | null + gen_feedback: string | null + job_description: string | null + job_id: number + user_id: string + } + Insert: { + created_at?: string + cv_id?: number | null + gen_feedback?: string | null + job_description?: string | null + job_id?: number + user_id: string + } + Update: { + created_at?: string + cv_id?: number | null + gen_feedback?: string | null + job_description?: string | null + job_id?: number + user_id?: string + } + Relationships: [ + { + foreignKeyName: "jobs_cv_id_fkey" + columns: ["cv_id"] + isOneToOne: false + referencedRelation: "cvs" + referencedColumns: ["cv_id"] + }, + { + foreignKeyName: "jobs_user_id_fkey" + columns: ["user_id"] + isOneToOne: false + referencedRelation: "users" + referencedColumns: ["user_id"] + }, + ] + } + test_relation: { + Row: { + created_at: string + id: number + some_text: string | null + } + Insert: { + created_at?: string + id?: number + some_text?: string | null + } + Update: { + created_at?: string + id?: number + some_text?: string | null + } + Relationships: [] + } + users: { + Row: { + created_at: string + user_id: string + } + Insert: { + created_at?: string + user_id: string + } + Update: { + created_at?: string + user_id?: string + } + Relationships: [] + } + } + Views: { + [_ in never]: never + } + Functions: { + [_ in never]: never + } + Enums: { + [_ in never]: never + } + CompositeTypes: { + [_ in never]: never + } + } +} + +type DatabaseWithoutInternals = Omit + +type DefaultSchema = DatabaseWithoutInternals[Extract] + +export type Tables< + DefaultSchemaTableNameOrOptions extends + | keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"]) + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & + DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends { + Row: infer R + } + ? R + : never + : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & + DefaultSchema["Views"]) + ? (DefaultSchema["Tables"] & + DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { + Row: infer R + } + ? R + : never + : never + +export type TablesInsert< + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Insert: infer I + } + ? I + : never + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { + Insert: infer I + } + ? I + : never + : never + +export type TablesUpdate< + DefaultSchemaTableNameOrOptions extends + | keyof DefaultSchema["Tables"] + | { schema: keyof DatabaseWithoutInternals }, + TableName extends DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] + : never = never, +> = DefaultSchemaTableNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { + Update: infer U + } + ? U + : never + : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] + ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { + Update: infer U + } + ? U + : never + : never + +export type Enums< + DefaultSchemaEnumNameOrOptions extends + | keyof DefaultSchema["Enums"] + | { schema: keyof DatabaseWithoutInternals }, + EnumName extends DefaultSchemaEnumNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"] + : never = never, +> = DefaultSchemaEnumNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName] + : DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"] + ? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions] + : never + +export type CompositeTypes< + PublicCompositeTypeNameOrOptions extends + | keyof DefaultSchema["CompositeTypes"] + | { schema: keyof DatabaseWithoutInternals }, + CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { + schema: keyof DatabaseWithoutInternals + } + ? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] + : never = never, +> = PublicCompositeTypeNameOrOptions extends { + schema: keyof DatabaseWithoutInternals +} + ? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] + : PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"] + ? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] + : never + +export const Constants = { + graphql_public: { + Enums: {}, + }, + public: { + Enums: {}, + }, +} as const From e0aaa4f36ef62d5b0cc26cefc34c5b9bfd9b7a7e Mon Sep 17 00:00:00 2001 From: krilklem Date: Wed, 10 Dec 2025 16:45:11 +0000 Subject: [PATCH 2/6] feat: Add clean resume and job description to response object --- backend/src/controllers/ai.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/controllers/ai.controller.ts b/backend/src/controllers/ai.controller.ts index 2824d21..4a3c109 100644 --- a/backend/src/controllers/ai.controller.ts +++ b/backend/src/controllers/ai.controller.ts @@ -51,7 +51,7 @@ export const analyzeResume = async ( jobDescription, }); - res.status(200).json(result); + res.status(200).json({ resumeText: cleanResumeText, jobDescription, feedback: result }); } catch (error) { console.error("Error in analyzeResume:", error); res.status(500).json({ From b1065092d18af495427ce10e545930209bd46630 Mon Sep 17 00:00:00 2001 From: krilklem Date: Wed, 10 Dec 2025 17:40:35 +0000 Subject: [PATCH 3/6] feat: Receive data to save from the front --- backend/src/controllers/supabase.controllers.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/supabase.controllers.ts b/backend/src/controllers/supabase.controllers.ts index 7018d4c..89fc914 100644 --- a/backend/src/controllers/supabase.controllers.ts +++ b/backend/src/controllers/supabase.controllers.ts @@ -2,6 +2,7 @@ import type { Request, Response } from "express"; import supabase from "../services/supabase.service.js"; export const save = async (req: Request, res: Response):Promise => { - const { data, error } = await supabase.from("test_relation").select("*"); - return res.status(200).json({ data }); + const { resume, jobDescription, feedback, cvName } = req.body; + //const { data, error } = await supabase.from("test_relation").select("*"); + return res.status(200).json({ message: "received files to save" }); }; \ No newline at end of file From 23fbc35c73322bf42df0ef550f367a498a78d27e Mon Sep 17 00:00:00 2001 From: krilklem Date: Thu, 11 Dec 2025 14:36:54 +0000 Subject: [PATCH 4/6] fix: Remove connection to supabase as all interfacing will be done through the front --- backend/.env.example | 5 - backend/package-lock.json | 132 -------- backend/package.json | 1 - .../src/controllers/supabase.controllers.ts | 8 - backend/src/routes/supabase.routes.ts | 8 - backend/src/services/supabase.service.ts | 14 - backend/src/types/supabase.ts | 289 ------------------ 7 files changed, 457 deletions(-) delete mode 100644 backend/src/controllers/supabase.controllers.ts delete mode 100644 backend/src/routes/supabase.routes.ts delete mode 100644 backend/src/services/supabase.service.ts delete mode 100644 backend/src/types/supabase.ts diff --git a/backend/.env.example b/backend/.env.example index 0630e8a..316ea59 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -5,10 +5,5 @@ # Get your API key from: https://console.anthropic.com/ # ANTHROPIC_API_KEY="your_anthropic_api_key_here" -# Example: Database connection string -# DB_CONNECTION_STRING="your_database_connection_string_here" -SUPABASE_URL=supabase-url-here -SUPABASE_KEY=supabase-key-here - # Example: Port # PORT=3000 \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index a000000..2053b48 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -10,7 +10,6 @@ "license": "ISC", "dependencies": { "@anthropic-ai/sdk": "^0.71.0", - "@supabase/supabase-js": "^2.87.1", "@types/multer": "^2.0.0", "cors": "^2.8.5", "dotenv": "^17.2.3", @@ -553,86 +552,6 @@ "node": ">= 0.4" } }, - "node_modules/@supabase/auth-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.87.1.tgz", - "integrity": "sha512-6RDeOf5TVoaXFtEstN188ykp3pXLZaU9qoAWfx8dc50FFAAqt+kcFJ96V0IvSmcpb4mDAWcpTJ7BegmVDn/WIw==", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@supabase/functions-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.87.1.tgz", - "integrity": "sha512-rWmYo4gRD0XAjMhYDlz7IH67bp4TIQ1UE4VqwIQtl1gGPwtLDq6wcRnu7jLKlXx0Gtrknw/eoiHYG9//XrCTzQ==", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@supabase/postgrest-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.87.1.tgz", - "integrity": "sha512-Yzu5eL3iGmZW0C/8x+vEojAOou63FI9oVw8HI8YOq63+5yM8g8aGh7Y1E2vbXFb7+gHGsPqLnaC6dPhrYt7qBA==", - "license": "MIT", - "dependencies": { - "tslib": "2.8.1" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@supabase/realtime-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.87.1.tgz", - "integrity": "sha512-XvLtEznxmYZXA7LYuy5zbSXpSYjDLJq2wQeRh3MzON2OR4U8Kq+RtPz2E2Wi8HEzvBfsc+nNu1TG8LQ9+3DRkA==", - "license": "MIT", - "dependencies": { - "@types/phoenix": "^1.6.6", - "@types/ws": "^8.18.1", - "tslib": "2.8.1", - "ws": "^8.18.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@supabase/storage-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.87.1.tgz", - "integrity": "sha512-0Uc8tNV4yzkNNmp1inpXru0RB4a7ECq05G2S6BDvSpMxTxJrDVJ4vVDwyhqB8ZZ+O9+8prHaQYoByQeuDnwpFQ==", - "license": "MIT", - "dependencies": { - "iceberg-js": "^0.8.1", - "tslib": "2.8.1" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@supabase/supabase-js": { - "version": "2.87.1", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.87.1.tgz", - "integrity": "sha512-tVgqZqnHZVum584KuUKSQZgcy6ZkhVd6gG8QWg2QfIXH9HmXdamauxdVsLXwaNPJxEdOyfAfwIyi5XUsiVYWtg==", - "license": "MIT", - "dependencies": { - "@supabase/auth-js": "2.87.1", - "@supabase/functions-js": "2.87.1", - "@supabase/postgrest-js": "2.87.1", - "@supabase/realtime-js": "2.87.1", - "@supabase/storage-js": "2.87.1" - }, - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", @@ -744,12 +663,6 @@ "undici-types": "~7.16.0" } }, - "node_modules/@types/phoenix": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.7.tgz", - "integrity": "sha512-oN9ive//QSBkf19rfDv45M7eZPi0eEXylht2OLEXicu5b4KoQ1OzXIw+xDSGWxSxe1JmepRR/ZH283vsu518/Q==", - "license": "MIT" - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -792,15 +705,6 @@ "@types/node": "*" } }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -1687,15 +1591,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/iceberg-js": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.1.tgz", - "integrity": "sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==", - "license": "MIT", - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", @@ -2703,12 +2598,6 @@ } } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/tsx": { "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", @@ -2842,27 +2731,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/backend/package.json b/backend/package.json index 4966cf2..b93b13e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -16,7 +16,6 @@ "type": "module", "dependencies": { "@anthropic-ai/sdk": "^0.71.0", - "@supabase/supabase-js": "^2.87.1", "@types/multer": "^2.0.0", "cors": "^2.8.5", "dotenv": "^17.2.3", diff --git a/backend/src/controllers/supabase.controllers.ts b/backend/src/controllers/supabase.controllers.ts deleted file mode 100644 index 89fc914..0000000 --- a/backend/src/controllers/supabase.controllers.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Request, Response } from "express"; -import supabase from "../services/supabase.service.js"; - -export const save = async (req: Request, res: Response):Promise => { - const { resume, jobDescription, feedback, cvName } = req.body; - //const { data, error } = await supabase.from("test_relation").select("*"); - return res.status(200).json({ message: "received files to save" }); -}; \ No newline at end of file diff --git a/backend/src/routes/supabase.routes.ts b/backend/src/routes/supabase.routes.ts deleted file mode 100644 index c7be511..0000000 --- a/backend/src/routes/supabase.routes.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Router } from "express"; -import { save } from "../controllers/supabase.controllers.js"; - -const router = Router(); - -router.post("/save", save); - -export default router; \ No newline at end of file diff --git a/backend/src/services/supabase.service.ts b/backend/src/services/supabase.service.ts deleted file mode 100644 index c90336d..0000000 --- a/backend/src/services/supabase.service.ts +++ /dev/null @@ -1,14 +0,0 @@ -import 'dotenv/config'; -import { createClient } from '@supabase/supabase-js'; -import type { Database } from '../types/supabase.ts'; - -const SUPABASE_URL = process.env.SUPABASE_URL; -const SUPABASE_KEY = process.env.SUPABASE_KEY; - -if (!SUPABASE_URL || !SUPABASE_KEY) { - throw new Error('Missing DB_URL or DB_KEY in .env'); -} - -const supabase = createClient(SUPABASE_URL, SUPABASE_KEY); - -export default supabase; \ No newline at end of file diff --git a/backend/src/types/supabase.ts b/backend/src/types/supabase.ts deleted file mode 100644 index 96f9b0d..0000000 --- a/backend/src/types/supabase.ts +++ /dev/null @@ -1,289 +0,0 @@ -export type Json = - | string - | number - | boolean - | null - | { [key: string]: Json | undefined } - | Json[] - -export type Database = { - // Allows to automatically instantiate createClient with right options - // instead of createClient(URL, KEY) - __InternalSupabase: { - PostgrestVersion: "13.0.5" - } - graphql_public: { - Tables: { - [_ in never]: never - } - Views: { - [_ in never]: never - } - Functions: { - graphql: { - Args: { - extensions?: Json - operationName?: string - query?: string - variables?: Json - } - Returns: Json - } - } - Enums: { - [_ in never]: never - } - CompositeTypes: { - [_ in never]: never - } - } - public: { - Tables: { - cvs: { - Row: { - created_at: string - cv: string | null - cv_id: number - name: string | null - user_id: string - } - Insert: { - created_at?: string - cv?: string | null - cv_id?: number - name?: string | null - user_id: string - } - Update: { - created_at?: string - cv?: string | null - cv_id?: number - name?: string | null - user_id?: string - } - Relationships: [ - { - foreignKeyName: "cvs_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["user_id"] - }, - ] - } - jobs: { - Row: { - created_at: string - cv_id: number | null - gen_feedback: string | null - job_description: string | null - job_id: number - user_id: string - } - Insert: { - created_at?: string - cv_id?: number | null - gen_feedback?: string | null - job_description?: string | null - job_id?: number - user_id: string - } - Update: { - created_at?: string - cv_id?: number | null - gen_feedback?: string | null - job_description?: string | null - job_id?: number - user_id?: string - } - Relationships: [ - { - foreignKeyName: "jobs_cv_id_fkey" - columns: ["cv_id"] - isOneToOne: false - referencedRelation: "cvs" - referencedColumns: ["cv_id"] - }, - { - foreignKeyName: "jobs_user_id_fkey" - columns: ["user_id"] - isOneToOne: false - referencedRelation: "users" - referencedColumns: ["user_id"] - }, - ] - } - test_relation: { - Row: { - created_at: string - id: number - some_text: string | null - } - Insert: { - created_at?: string - id?: number - some_text?: string | null - } - Update: { - created_at?: string - id?: number - some_text?: string | null - } - Relationships: [] - } - users: { - Row: { - created_at: string - user_id: string - } - Insert: { - created_at?: string - user_id: string - } - Update: { - created_at?: string - user_id?: string - } - Relationships: [] - } - } - Views: { - [_ in never]: never - } - Functions: { - [_ in never]: never - } - Enums: { - [_ in never]: never - } - CompositeTypes: { - [_ in never]: never - } - } -} - -type DatabaseWithoutInternals = Omit - -type DefaultSchema = DatabaseWithoutInternals[Extract] - -export type Tables< - DefaultSchemaTableNameOrOptions extends - | keyof (DefaultSchema["Tables"] & DefaultSchema["Views"]) - | { schema: keyof DatabaseWithoutInternals }, - TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals - } - ? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & - DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"]) - : never = never, -> = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals -} - ? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] & - DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends { - Row: infer R - } - ? R - : never - : DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] & - DefaultSchema["Views"]) - ? (DefaultSchema["Tables"] & - DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends { - Row: infer R - } - ? R - : never - : never - -export type TablesInsert< - DefaultSchemaTableNameOrOptions extends - | keyof DefaultSchema["Tables"] - | { schema: keyof DatabaseWithoutInternals }, - TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals - } - ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] - : never = never, -> = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals -} - ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Insert: infer I - } - ? I - : never - : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] - ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { - Insert: infer I - } - ? I - : never - : never - -export type TablesUpdate< - DefaultSchemaTableNameOrOptions extends - | keyof DefaultSchema["Tables"] - | { schema: keyof DatabaseWithoutInternals }, - TableName extends DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals - } - ? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] - : never = never, -> = DefaultSchemaTableNameOrOptions extends { - schema: keyof DatabaseWithoutInternals -} - ? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends { - Update: infer U - } - ? U - : never - : DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"] - ? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends { - Update: infer U - } - ? U - : never - : never - -export type Enums< - DefaultSchemaEnumNameOrOptions extends - | keyof DefaultSchema["Enums"] - | { schema: keyof DatabaseWithoutInternals }, - EnumName extends DefaultSchemaEnumNameOrOptions extends { - schema: keyof DatabaseWithoutInternals - } - ? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"] - : never = never, -> = DefaultSchemaEnumNameOrOptions extends { - schema: keyof DatabaseWithoutInternals -} - ? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName] - : DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"] - ? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions] - : never - -export type CompositeTypes< - PublicCompositeTypeNameOrOptions extends - | keyof DefaultSchema["CompositeTypes"] - | { schema: keyof DatabaseWithoutInternals }, - CompositeTypeName extends PublicCompositeTypeNameOrOptions extends { - schema: keyof DatabaseWithoutInternals - } - ? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"] - : never = never, -> = PublicCompositeTypeNameOrOptions extends { - schema: keyof DatabaseWithoutInternals -} - ? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName] - : PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"] - ? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions] - : never - -export const Constants = { - graphql_public: { - Enums: {}, - }, - public: { - Enums: {}, - }, -} as const From 24eb60cf0aed6139778851963f5b0879fd015aba Mon Sep 17 00:00:00 2001 From: krilklem Date: Mon, 15 Dec 2025 12:24:17 +0000 Subject: [PATCH 5/6] fix: Remove left over routing from previous backend supabase connection --- backend/src/index.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/src/index.ts b/backend/src/index.ts index b11bdbc..ce827c3 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -6,7 +6,6 @@ import { fileURLToPath } from "node:url"; import cors from "cors"; import aiRoutes from "./routes/ai.routes.js"; -import supabaseRoutes from "./routes/supabase.routes.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -34,9 +33,6 @@ app.use(express.urlencoded({ extended: true, limit: "10mb" })); // Parse URL-enc // Serve static files from the 'public' directory app.use(express.static(path.join(__dirname, "public"))); -// Supabase routes -app.use("/api/supabase", supabaseRoutes); - // Routes app.get("/", (_req: Request, res: Response) => { res.send("KeyCV Backend API - AI Toolkit Enabled"); From f664aca23e9c51164e6326b02d20496ef8175c9a Mon Sep 17 00:00:00 2001 From: krilklem Date: Mon, 15 Dec 2025 15:40:06 +0000 Subject: [PATCH 6/6] chore: Format --- backend/src/controllers/ai.controller.ts | 4 +++- backend/src/index.ts | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/controllers/ai.controller.ts b/backend/src/controllers/ai.controller.ts index 4a3c109..34f8ac0 100644 --- a/backend/src/controllers/ai.controller.ts +++ b/backend/src/controllers/ai.controller.ts @@ -51,7 +51,9 @@ export const analyzeResume = async ( jobDescription, }); - res.status(200).json({ resumeText: cleanResumeText, jobDescription, feedback: result }); + res + .status(200) + .json({ resumeText: cleanResumeText, jobDescription, feedback: result }); } catch (error) { console.error("Error in analyzeResume:", error); res.status(500).json({ diff --git a/backend/src/index.ts b/backend/src/index.ts index ce827c3..ca09940 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -42,7 +42,6 @@ app.get("/health", (_req: Request, res: Response) => { res.status(200).json({ status: "ok" }); }); - app.listen(Number(port), "0.0.0.0", () => { console.log(`Server is running at http://localhost:${port}`); console.log(