Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -1,3 +0,0 @@
|
|||||||
# Configuration for private npm package dependencies
|
|
||||||
# For more information on using private registries with Edge Functions, see:
|
|
||||||
# https://supabase.com/docs/guides/functions/import-maps#importing-from-private-registries
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"imports": {
|
|
||||||
"@supabase/functions-js": "jsr:@supabase/functions-js@^2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
// Setup type definitions for built-in Supabase Runtime APIs
|
|
||||||
import "@supabase/functions-js/edge-runtime.d.ts";
|
|
||||||
import { createClient } from "npm:@supabase/supabase-js@2";
|
|
||||||
type WebhookPayload = {
|
|
||||||
type: "INSERT" | "UPDATE" | "DELETE";
|
|
||||||
table: string;
|
|
||||||
schema: string;
|
|
||||||
record: Record<string, unknown> | null;
|
|
||||||
old_record: Record<string, unknown> | null;
|
|
||||||
};
|
|
||||||
const SUPABASE_URL = Deno.env.get("SUPABASE_URL") ?? "";
|
|
||||||
const SUPABASE_SERVICE_ROLE_KEY = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ??
|
|
||||||
"";
|
|
||||||
const OPENAI_API_KEY = Deno.env.get("OPENAI_API_KEY") ?? "";
|
|
||||||
const OPENAI_BASE_URL = Deno.env.get("OPENAI_BASE_URL") ??
|
|
||||||
"https://api.openai.com/v1";
|
|
||||||
const ALLOWED_SCHEMA = "public";
|
|
||||||
const ALLOWED_TABLES = new Set(["planes_estudio", "asignaturas"]);
|
|
||||||
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
|
|
||||||
auth: { persistSession: false },
|
|
||||||
});
|
|
||||||
function jsonResponse(status: number, body: Record<string, unknown>) {
|
|
||||||
return new Response(JSON.stringify(body), {
|
|
||||||
status,
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function createConversationId(metadata: Record<string, string>) {
|
|
||||||
const response = await fetch(`${OPENAI_BASE_URL}/conversations`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${OPENAI_API_KEY}`,
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ metadata }),
|
|
||||||
});
|
|
||||||
if (!response.ok) {
|
|
||||||
const errorText = await response.text();
|
|
||||||
throw new Error(`OpenAI error: ${response.status} ${errorText}`);
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
|
||||||
const conversationId = data?.id as string | undefined;
|
|
||||||
if (!conversationId) {
|
|
||||||
throw new Error("OpenAI response missing conversation id");
|
|
||||||
}
|
|
||||||
return conversationId;
|
|
||||||
}
|
|
||||||
Deno.serve(async (req) => {
|
|
||||||
if (req.method !== "POST") {
|
|
||||||
return jsonResponse(405, { error: "Method not allowed" });
|
|
||||||
}
|
|
||||||
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
|
|
||||||
return jsonResponse(500, { error: "Supabase env vars missing" });
|
|
||||||
}
|
|
||||||
if (!OPENAI_API_KEY) {
|
|
||||||
return jsonResponse(500, { error: "OPENAI_API_KEY missing" });
|
|
||||||
}
|
|
||||||
let payload: WebhookPayload;
|
|
||||||
try {
|
|
||||||
payload = await req.json();
|
|
||||||
} catch {
|
|
||||||
return jsonResponse(400, { error: "Invalid JSON body" });
|
|
||||||
}
|
|
||||||
const { type, table, schema, record } = payload;
|
|
||||||
if (schema !== ALLOWED_SCHEMA || !ALLOWED_TABLES.has(table)) {
|
|
||||||
return jsonResponse(400, { error: "Table not allowed" });
|
|
||||||
}
|
|
||||||
if (type !== "INSERT") {
|
|
||||||
return jsonResponse(200, { status: "ignored", reason: "event_type" });
|
|
||||||
}
|
|
||||||
if (!record || typeof record !== "object") {
|
|
||||||
return jsonResponse(400, { error: "Missing record" });
|
|
||||||
}
|
|
||||||
const recordId = record["id"] as string | number | undefined;
|
|
||||||
if (!recordId) {
|
|
||||||
return jsonResponse(400, { error: "Record id missing" });
|
|
||||||
}
|
|
||||||
const existingConversationId = record["conversation_id"] as
|
|
||||||
| string
|
|
||||||
| null
|
|
||||||
| undefined;
|
|
||||||
if (existingConversationId) {
|
|
||||||
return jsonResponse(200, {
|
|
||||||
status: "skipped",
|
|
||||||
conversation_id: existingConversationId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let conversationId: string;
|
|
||||||
try {
|
|
||||||
conversationId = await createConversationId({
|
|
||||||
table,
|
|
||||||
record_id: String(recordId),
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
return jsonResponse(502, { error: (error as Error).message });
|
|
||||||
}
|
|
||||||
const { error } = await supabase
|
|
||||||
.from(table)
|
|
||||||
.update({ conversation_id: conversationId })
|
|
||||||
.eq("id", recordId);
|
|
||||||
if (error) {
|
|
||||||
return jsonResponse(500, { error: error.message });
|
|
||||||
}
|
|
||||||
return jsonResponse(200, {
|
|
||||||
status: "updated",
|
|
||||||
table,
|
|
||||||
record_id: recordId,
|
|
||||||
conversation_id: conversationId,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
create type "public"."estado_conversacion" as enum ('ACTIVA', 'ARCHIVANDO', 'ARCHIVADA', 'ERROR');
|
||||||
|
|
||||||
|
alter table "public"."planes_estudio" drop constraint "planes_estudio_conversation_id_key";
|
||||||
|
|
||||||
|
drop view if exists "public"."plantilla_plan";
|
||||||
|
|
||||||
|
drop index if exists "public"."planes_estudio_conversation_id_key";
|
||||||
|
|
||||||
|
|
||||||
|
create table "public"."conversaciones_asignatura" (
|
||||||
|
"id" uuid not null default gen_random_uuid(),
|
||||||
|
"asignatura_id" uuid not null,
|
||||||
|
"openai_conversation_id" text not null,
|
||||||
|
"estado" public.estado_conversacion not null default 'ACTIVA'::public.estado_conversacion,
|
||||||
|
"conversacion_json" jsonb not null default '{}'::jsonb,
|
||||||
|
"creado_por" uuid,
|
||||||
|
"creado_en" timestamp with time zone not null default now(),
|
||||||
|
"archivado_por" uuid,
|
||||||
|
"archivado_en" timestamp with time zone,
|
||||||
|
"intento_archivado" integer not null default 0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
create table "public"."conversaciones_plan" (
|
||||||
|
"id" uuid not null default gen_random_uuid(),
|
||||||
|
"plan_estudio_id" uuid not null,
|
||||||
|
"openai_conversation_id" text not null,
|
||||||
|
"estado" public.estado_conversacion not null default 'ACTIVA'::public.estado_conversacion,
|
||||||
|
"conversacion_json" jsonb not null default '{}'::jsonb,
|
||||||
|
"creado_por" uuid,
|
||||||
|
"creado_en" timestamp with time zone not null default now(),
|
||||||
|
"archivado_por" uuid,
|
||||||
|
"archivado_en" timestamp with time zone,
|
||||||
|
"intento_archivado" integer not null default 0
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
alter table "public"."planes_estudio" drop column "conversation_id";
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX conversaciones_asignatura_openai_id_unico ON public.conversaciones_asignatura USING btree (openai_conversation_id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX conversaciones_asignatura_pkey ON public.conversaciones_asignatura USING btree (id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX conversaciones_plan_openai_id_unico ON public.conversaciones_plan USING btree (openai_conversation_id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX conversaciones_plan_pkey ON public.conversaciones_plan USING btree (id);
|
||||||
|
|
||||||
|
CREATE INDEX idx_conv_asig_asignatura ON public.conversaciones_asignatura USING btree (asignatura_id);
|
||||||
|
|
||||||
|
CREATE INDEX idx_conv_asig_estado ON public.conversaciones_asignatura USING btree (estado);
|
||||||
|
|
||||||
|
CREATE INDEX idx_conv_plan_estado ON public.conversaciones_plan USING btree (estado);
|
||||||
|
|
||||||
|
CREATE INDEX idx_conv_plan_plan_estudio ON public.conversaciones_plan USING btree (plan_estudio_id);
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" add constraint "conversaciones_asignatura_pkey" PRIMARY KEY using index "conversaciones_asignatura_pkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" add constraint "conversaciones_plan_pkey" PRIMARY KEY using index "conversaciones_plan_pkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" add constraint "conversaciones_asignatura_archivado_por_fkey" FOREIGN KEY (archivado_por) REFERENCES public.usuarios_app(id) ON DELETE SET NULL not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" validate constraint "conversaciones_asignatura_archivado_por_fkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" add constraint "conversaciones_asignatura_asignatura_id_fkey" FOREIGN KEY (asignatura_id) REFERENCES public.asignaturas(id) ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" validate constraint "conversaciones_asignatura_asignatura_id_fkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" add constraint "conversaciones_asignatura_creado_por_fkey" FOREIGN KEY (creado_por) REFERENCES public.usuarios_app(id) ON DELETE SET NULL not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" validate constraint "conversaciones_asignatura_creado_por_fkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_asignatura" add constraint "conversaciones_asignatura_openai_id_unico" UNIQUE using index "conversaciones_asignatura_openai_id_unico";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" add constraint "conversaciones_plan_archivado_por_fkey" FOREIGN KEY (archivado_por) REFERENCES public.usuarios_app(id) ON DELETE SET NULL not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" validate constraint "conversaciones_plan_archivado_por_fkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" add constraint "conversaciones_plan_creado_por_fkey" FOREIGN KEY (creado_por) REFERENCES public.usuarios_app(id) ON DELETE SET NULL not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" validate constraint "conversaciones_plan_creado_por_fkey";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" add constraint "conversaciones_plan_openai_id_unico" UNIQUE using index "conversaciones_plan_openai_id_unico";
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" add constraint "conversaciones_plan_plan_estudio_id_fkey" FOREIGN KEY (plan_estudio_id) REFERENCES public.planes_estudio(id) ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."conversaciones_plan" validate constraint "conversaciones_plan_plan_estudio_id_fkey";
|
||||||
|
|
||||||
|
create or replace view "public"."plantilla_plan" as SELECT plan.id AS plan_estudio_id,
|
||||||
|
struct.id AS estructura_id,
|
||||||
|
struct.template_id
|
||||||
|
FROM (public.planes_estudio plan
|
||||||
|
JOIN public.estructuras_plan struct ON ((plan.estructura_id = struct.id)));
|
||||||
|
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_asignatura" to "anon";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_asignatura" to "authenticated";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_asignatura" to "postgres";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_asignatura" to "service_role";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_plan" to "anon";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_plan" to "authenticated";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_plan" to "postgres";
|
||||||
|
|
||||||
|
grant delete on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."conversaciones_plan" to "service_role";
|
||||||
|
|
||||||
|
|
||||||
+26
-2063
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user