chore: save current changes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
||||
import type { DocumentTableSnapshot, TableRowData } from "@/types/online-table";
|
||||
|
||||
interface RouteContext {
|
||||
params: {
|
||||
@@ -7,19 +8,43 @@ interface RouteContext {
|
||||
};
|
||||
}
|
||||
|
||||
export async function GET(request: Request, context: RouteContext) {
|
||||
type UpdateTableRequest = {
|
||||
title?: string;
|
||||
snapshot?: DocumentTableSnapshot | null;
|
||||
rows?: TableRowData[];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
viewPreferences?: Record<string, any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
schema?: Record<string, any>;
|
||||
};
|
||||
|
||||
const extractTableId = async (context: RouteContext) => {
|
||||
// Next.js 16 / Turbopack 下 params 是 Promise,需要等待。
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return (await (context as any).params).tableId as string;
|
||||
};
|
||||
|
||||
const getAuthUser = async () => {
|
||||
const supabase = await createSupabaseRouteClient();
|
||||
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
if (error) {
|
||||
console.error("Auth getUser error:", error);
|
||||
}
|
||||
if (!data?.user) {
|
||||
return { supabase, user: null as const };
|
||||
}
|
||||
return { supabase, user: data.user };
|
||||
};
|
||||
|
||||
export async function GET(request: Request, context: RouteContext) {
|
||||
const { supabase, user } = await getAuthUser();
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
// 强制 await params,以解决 Next.js 16/Turbopack 错误。
|
||||
// 必须忽略类型检查,因为 Next.js 16/Turbopack 在运行时将 params 视为 Promise。
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const tableId = (await (context as any).params).tableId;
|
||||
const tableId = await extractTableId(context);
|
||||
|
||||
if (!tableId) {
|
||||
return NextResponse.json({ error: "Missing tableId" }, { status: 400 });
|
||||
@@ -49,3 +74,160 @@ export async function GET(request: Request, context: RouteContext) {
|
||||
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: Request, context: RouteContext) {
|
||||
const { supabase, user } = await getAuthUser();
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const tableId = await extractTableId(context);
|
||||
if (!tableId) {
|
||||
return NextResponse.json({ error: "Missing tableId" }, { status: 400 });
|
||||
}
|
||||
|
||||
let body: UpdateTableRequest | null = null;
|
||||
try {
|
||||
body = await request.json() as UpdateTableRequest;
|
||||
} catch (error) {
|
||||
console.error("Invalid payload:", error);
|
||||
return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: tableMeta, error: metaError } = await supabase
|
||||
.from("document_tables")
|
||||
.select("id, workspace_id, document_id")
|
||||
.eq("id", tableId)
|
||||
.single();
|
||||
|
||||
if (metaError || !tableMeta) {
|
||||
console.error("Table not found or load error:", metaError);
|
||||
return NextResponse.json({ error: "Table not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
const updatePayload: Record<string, unknown> = {
|
||||
updated_by: user.id,
|
||||
last_synced_at: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (body?.title !== undefined) {
|
||||
updatePayload.title = body.title;
|
||||
}
|
||||
if (body?.schema) {
|
||||
updatePayload.schema = body.schema;
|
||||
}
|
||||
if (body?.snapshot !== undefined) {
|
||||
updatePayload.snapshot = body.snapshot ?? {};
|
||||
}
|
||||
if (body?.viewPreferences) {
|
||||
updatePayload.view_preferences = body.viewPreferences;
|
||||
}
|
||||
|
||||
const { error: updateError } = await supabase
|
||||
.from("document_tables")
|
||||
.update(updatePayload)
|
||||
.eq("id", tableId);
|
||||
|
||||
if (updateError) {
|
||||
console.error("Failed to update table:", updateError);
|
||||
return NextResponse.json({ error: "Failed to update table", details: updateError.message }, { status: 500 });
|
||||
}
|
||||
|
||||
const nextRows = body?.rows ?? body?.snapshot?.rows ?? [];
|
||||
if (Array.isArray(nextRows)) {
|
||||
const { error: deleteRowsError } = await supabase
|
||||
.from("document_table_rows")
|
||||
.delete()
|
||||
.eq("table_id", tableId);
|
||||
|
||||
if (deleteRowsError) {
|
||||
console.error("Failed to clear old rows:", deleteRowsError);
|
||||
return NextResponse.json({ error: "Failed to update rows", details: deleteRowsError.message }, { status: 500 });
|
||||
}
|
||||
|
||||
const sanitizedRows = nextRows
|
||||
.filter((row) => row && typeof row === "object" && Object.keys(row).length > 0);
|
||||
|
||||
if (sanitizedRows.length > 0) {
|
||||
const rowsToInsert = sanitizedRows.map((row, index) => ({
|
||||
table_id: tableId,
|
||||
workspace_id: tableMeta.workspace_id,
|
||||
document_id: tableMeta.document_id,
|
||||
row_index: index,
|
||||
row_data: row,
|
||||
row_hash: null,
|
||||
is_deleted: false,
|
||||
updated_by: user.id,
|
||||
}));
|
||||
|
||||
const { error: insertError } = await supabase
|
||||
.from("document_table_rows")
|
||||
.insert(rowsToInsert);
|
||||
|
||||
if (insertError) {
|
||||
console.error("Failed to insert rows:", insertError);
|
||||
return NextResponse.json({ error: "Failed to insert rows", details: insertError.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { data: latest, error: fetchError } = await supabase
|
||||
.from("document_tables")
|
||||
.select("*")
|
||||
.eq("id", tableId)
|
||||
.single();
|
||||
|
||||
if (fetchError || !latest) {
|
||||
console.error("Failed to fetch updated table:", fetchError);
|
||||
return NextResponse.json({ error: "Failed to load updated table", details: fetchError?.message }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json(latest, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("API error:", error);
|
||||
const message = error instanceof Error ? error.message : "Internal Server Error";
|
||||
return NextResponse.json({ error: message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: Request, context: RouteContext) {
|
||||
const { supabase, user } = await getAuthUser();
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const tableId = await extractTableId(context);
|
||||
if (!tableId) {
|
||||
return NextResponse.json({ error: "Missing tableId" }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const { error: deleteRowsError } = await supabase
|
||||
.from("document_table_rows")
|
||||
.delete()
|
||||
.eq("table_id", tableId);
|
||||
|
||||
if (deleteRowsError) {
|
||||
console.error("Failed to delete table rows:", deleteRowsError);
|
||||
return NextResponse.json({ error: "Failed to delete table rows" }, { status: 500 });
|
||||
}
|
||||
|
||||
const { error: deleteTableError } = await supabase
|
||||
.from("document_tables")
|
||||
.delete()
|
||||
.eq("id", tableId);
|
||||
|
||||
if (deleteTableError) {
|
||||
console.error("Failed to delete table:", deleteTableError);
|
||||
return NextResponse.json({ error: "Failed to delete table" }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true }, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("API error:", error);
|
||||
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ export async function POST(request: Request) {
|
||||
document_id: documentId,
|
||||
title: title,
|
||||
schema: schema,
|
||||
view_preferences: {},
|
||||
is_archived: false,
|
||||
created_by: user.id,
|
||||
updated_by: user.id,
|
||||
snapshot: snapshot ?? {},
|
||||
|
||||
Reference in New Issue
Block a user